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
4549f8ed
authored
Feb 03, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CRM:优化合同金额排行、回款金额排行
parent
d6438943
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
117 additions
and
199 deletions
+117
-199
src/api/crm/bi/rank.ts
+7
-20
src/store/modules/user.ts
+6
-2
src/views/crm/bi/rank/ContractPriceRank.vue
+40
-76
src/views/crm/bi/rank/ReceivablePriceRank.vue
+40
-75
src/views/crm/bi/rank/index.vue
+24
-26
No files found.
src/api/crm/bi/rank
ing
.ts
→
src/api/crm/bi/rank.ts
View file @
4549f8ed
import
request
from
'@/config/axios'
export
interface
Bi
ContractRanKing
RespVO
{
price
:
number
export
interface
Bi
Rank
RespVO
{
count
:
number
nickname
:
string
deptName
:
string
}
export
interface
BiReceivablesRanKingRespVO
{
price
:
number
nickname
:
string
deptName
:
string
}
export
interface
BiRankReqVO
{
deptId
:
number
orderDate
:
Date
[]
startTime
:
Date
endTime
:
Date
}
// 排行 API
export
const
Rank
ingStatistics
Api
=
{
export
const
RankApi
=
{
// 获得合同排行榜
contractAmountRanking
:
(
params
:
any
)
=>
{
getContractPriceRank
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/bi-rank
ing/contract-ranking
'
,
url
:
'/crm/bi-rank
/get-contract-price-rank
'
,
params
})
},
// 获得回款排行榜
receivablesAmountRanking
:
(
params
:
any
)
=>
{
getReceivablePriceRank
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/crm/bi-rank
ing/receivables-ranking
'
,
url
:
'/crm/bi-rank
/get-receivable-price-rank
'
,
params
})
}
...
...
src/store/modules/user.ts
View file @
4549f8ed
...
...
@@ -10,7 +10,9 @@ interface UserVO {
id
:
number
avatar
:
string
nickname
:
string
deptId
:
number
}
interface
UserInfoVO
{
permissions
:
string
[]
roles
:
string
[]
...
...
@@ -26,7 +28,8 @@ export const useUserStore = defineStore('admin-user', {
user
:
{
id
:
0
,
avatar
:
''
,
nickname
:
''
nickname
:
''
,
deptId
:
0
}
}),
getters
:
{
...
...
@@ -73,7 +76,8 @@ export const useUserStore = defineStore('admin-user', {
this
.
user
=
{
id
:
0
,
avatar
:
''
,
nickname
:
''
nickname
:
''
,
deptId
:
0
}
}
}
...
...
src/views/crm/bi/rank
ing/components/RankingContractStatistics
.vue
→
src/views/crm/bi/rank
/ContractPriceRank
.vue
View file @
4549f8ed
<!-- 合同金额排行 -->
<
template
>
<!-- 柱状图 -->
<el-card
shadow=
"never"
>
<!-- 柱状图 -->
<el-skeleton
:loading=
"trendLoading"
animated
>
<Echart
:height=
"500"
:options=
"barChartOptions"
/>
<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=
"nickname"
min-width=
"200"
/>
<el-table-column
label=
"部门"
align=
"center"
prop=
"deptName"
min-width=
"200"
/>
<el-table-column
label=
"合同金额(元)"
align=
"center"
prop=
"price"
min-width=
"200"
/>
<el-table-column
label=
"合同金额(元)"
align=
"center"
prop=
"count"
min-width=
"200"
:formatter=
"fenToYuanFormat"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
Rank
ingStatisticsApi
,
BiContractRanKingRespVO
,
BiRankReqVO
}
from
'@/api/crm/bi/ranking
'
import
{
Rank
Api
,
BiRankRespVO
}
from
'@/api/crm/bi/rank
'
import
{
EChartsOption
}
from
'echarts'
import
{
beginOfDay
,
endOfDay
,
formatDate
}
from
'@/utils/formatTime'
/** 合同金额排行 */
defineOptions
({
name
:
'RankingContractStatistics'
})
import
{
fenToYuanFormat
}
from
'@/utils/formatter'
import
{
fenToYuan
}
from
'@/utils'
import
{
clone
}
from
'unocss'
const
params
=
reactive
({
deptId
:
undefined
,
startTime
:
undefined
,
endTime
:
undefined
})
defineOptions
({
name
:
'ContractPriceRank'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
trendLoading
=
ref
(
true
)
// 状态加载中
const
loading
=
ref
(
false
)
// 列表的加载中
const
list
=
ref
<
BiContractRanKingRespVO
[]
>
([])
// 列表的数据
const
queryParams
=
defineProps
<
{
queryParams
:
BiRankReqVO
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
BiRankRespVO
[]
>
([])
// 列表的数据
/** 柱状图配置
横向 */
const
barChartOptions
=
reactive
<
EChartsOption
>
({
/** 柱状图配置
:
横向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
dataset
:
{
dimensions
:
[
'n
ame'
,
'value
'
],
dimensions
:
[
'n
ickname'
,
'count
'
],
source
:
[]
},
grid
:
{
left
:
20
,
right
:
20
,
bottom
:
20
,
top
:
80
,
containLabel
:
true
},
legend
:
{
...
...
@@ -53,16 +54,13 @@ const barChartOptions = reactive<EChartsOption>({
series
:
[
{
name
:
'合同金额排行'
,
type
:
'bar'
,
smooth
:
true
,
itemStyle
:
{
color
:
'#B37FEB'
}
type
:
'bar'
}
],
toolbox
:
{
feature
:
{
// 数据区域缩放
dataZoom
:
{
yAxisIndex
:
false
//
Y
轴不缩放
yAxisIndex
:
false
//
数据区域缩放:Y
轴不缩放
},
brush
:
{
type
:
[
'lineX'
,
'clear'
]
// 区域缩放按钮、还原按钮
...
...
@@ -74,70 +72,36 @@ const barChartOptions = reactive<EChartsOption>({
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
}
},
valueFormatter
:
fenToYuan
},
xAxis
:
{
type
:
'value'
,
name
:
'合同金额(元)'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
}
name
:
'合同金额(元)'
},
yAxis
:
{
type
:
'category'
,
name
:
'签订人'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
},
axisLabel
:
{
formatter
:
(
value
:
string
)
=>
{
return
value
}
}
name
:
'签订人'
}
})
as
EChartsOption
/** 获取合同金额排行 */
const
getRankingContractStatistics
=
async
()
=>
{
trendLoading
.
value
=
true
const
loadData
=
async
()
=>
{
// 1. 加载排行数据
loading
.
value
=
true
params
.
deptId
=
queryParams
.
queryParams
.
deptId
params
.
startTime
=
formatDate
(
beginOfDay
(
new
Date
(
queryParams
.
queryParams
.
orderDate
[
0
])))
params
.
endTime
=
formatDate
(
endOfDay
(
new
Date
(
queryParams
.
queryParams
.
orderDate
[
1
])))
const
rankingList
=
await
RankingStatisticsApi
.
contractAmountRanking
(
params
)
let
source
=
rankingList
.
map
((
item
:
BiContractRanKingRespVO
)
=>
{
return
{
name
:
item
.
nickname
,
value
:
item
.
price
}
})
// 反转数据源
source
=
source
.
reverse
()
// 更新 Echarts 数据
if
(
barChartOptions
.
dataset
&&
barChartOptions
.
dataset
[
'source'
])
{
barChartOptions
.
dataset
[
'source'
]
=
source
const
rankingList
=
await
RankApi
.
getContractPriceRank
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
dataset
&&
echartsOption
.
dataset
[
'source'
])
{
echartsOption
.
dataset
[
'source'
]
=
clone
(
rankingList
).
reverse
()
}
// 更新列表数据
//
2.2
更新列表数据
list
.
value
=
rankingList
trendLoading
.
value
=
false
loading
.
value
=
false
}
defineExpose
({
loadData
})
/** 重新加载数据 */
const
reloadData
=
async
()
=>
{
await
getRankingContractStatistics
()
}
// 暴露 reloadData 函数
defineExpose
({
reloadData
})
/** 初始化 */
onMounted
(()
=>
{
getRankingContractStatistics
()
loadData
()
})
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/views/crm/bi/rank
ing/components/RankingReceivablesStatistics
.vue
→
src/views/crm/bi/rank
/ReceivablePriceRank
.vue
View file @
4549f8ed
<!-- 回款金额排行 -->
<
template
>
<!-- 柱状图 -->
<el-card
shadow=
"never"
>
<!-- 柱状图 -->
<el-skeleton
:loading=
"trendLoading"
animated
>
<Echart
:height=
"500"
:options=
"barChartOptions"
/>
<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=
"nickname"
min-width=
"200"
/>
<el-table-column
label=
"部门"
align=
"center"
prop=
"deptName"
min-width=
"200"
/>
<el-table-column
label=
"合同金额(元)"
align=
"center"
prop=
"price"
min-width=
"200"
/>
<el-table-column
label=
"回款金额(元)"
align=
"center"
prop=
"count"
min-width=
"200"
:formatter=
"fenToYuanFormat"
/>
</el-table>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
Rank
ingStatisticsApi
,
BiReceivablesRanKingRespVO
,
BiRankReqVO
}
from
'@/api/crm/bi/ranking
'
import
{
Rank
Api
,
BiRankRespVO
}
from
'@/api/crm/bi/rank
'
import
{
EChartsOption
}
from
'echarts'
import
{
beginOfDay
,
endOfDay
,
formatDate
}
from
'@/utils/formatTime'
/** 回款金额排行 */
defineOptions
({
name
:
'RankingReceivablesStatistics'
})
import
{
fenToYuanFormat
}
from
'@/utils/formatter'
import
{
fenToYuan
}
from
'@/utils'
import
{
clone
}
from
'unocss'
const
params
=
reactive
({
deptId
:
undefined
,
startTime
:
undefined
,
endTime
:
undefined
})
defineOptions
({
name
:
'ReceivablePriceRank'
})
const
props
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
const
trendLoading
=
ref
(
true
)
// 状态加载中
const
loading
=
ref
(
false
)
// 列表的加载中
const
list
=
ref
<
BiReceivablesRanKingRespVO
[]
>
([])
// 列表的数据
const
queryParams
=
defineProps
<
{
queryParams
:
BiRankReqVO
}
>
()
// 搜索参数
const
loading
=
ref
(
false
)
// 加载中
const
list
=
ref
<
BiRankRespVO
[]
>
([])
// 列表的数据
/** 柱状图配置
横向 */
const
barChartOptions
=
reactive
<
EChartsOption
>
({
/** 柱状图配置
:
横向 */
const
echartsOption
=
reactive
<
EChartsOption
>
({
dataset
:
{
dimensions
:
[
'n
ame'
,
'value
'
],
dimensions
:
[
'n
ickname'
,
'count
'
],
source
:
[]
},
grid
:
{
left
:
20
,
right
:
20
,
bottom
:
20
,
top
:
80
,
containLabel
:
true
},
legend
:
{
...
...
@@ -53,16 +54,13 @@ const barChartOptions = reactive<EChartsOption>({
series
:
[
{
name
:
'回款金额排行'
,
type
:
'bar'
,
smooth
:
true
,
itemStyle
:
{
color
:
'#B37FEB'
}
type
:
'bar'
}
],
toolbox
:
{
feature
:
{
// 数据区域缩放
dataZoom
:
{
yAxisIndex
:
false
//
Y
轴不缩放
yAxisIndex
:
false
//
数据区域缩放:Y
轴不缩放
},
brush
:
{
type
:
[
'lineX'
,
'clear'
]
// 区域缩放按钮、还原按钮
...
...
@@ -74,70 +72,37 @@ const barChartOptions = reactive<EChartsOption>({
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
}
},
valueFormatter
:
fenToYuan
},
xAxis
:
{
type
:
'value'
,
name
:
'回款金额(元)'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
}
name
:
'回款金额(元)'
},
yAxis
:
{
type
:
'category'
,
name
:
'签订人'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
},
axisLabel
:
{
formatter
:
(
value
:
string
)
=>
{
return
value
}
}
nameGap
:
30
}
})
as
EChartsOption
/** 获取回款金额排行 */
const
getRankingReceivablesStatistics
=
async
()
=>
{
trendLoading
.
value
=
true
const
loadData
=
async
()
=>
{
// 1. 加载排行数据
loading
.
value
=
true
params
.
deptId
=
queryParams
.
queryParams
.
deptId
params
.
startTime
=
formatDate
(
beginOfDay
(
new
Date
(
queryParams
.
queryParams
.
orderDate
[
0
])))
params
.
endTime
=
formatDate
(
endOfDay
(
new
Date
(
queryParams
.
queryParams
.
orderDate
[
1
])))
const
rankingList
=
await
RankingStatisticsApi
.
receivablesAmountRanking
(
params
)
let
source
=
rankingList
.
map
((
item
:
BiReceivablesRanKingRespVO
)
=>
{
return
{
name
:
item
.
nickname
,
value
:
item
.
price
}
})
// 反转数据源
source
=
source
.
reverse
()
// 更新 Echarts 数据
if
(
barChartOptions
.
dataset
&&
barChartOptions
.
dataset
[
'source'
])
{
barChartOptions
.
dataset
[
'source'
]
=
source
const
rankingList
=
await
RankApi
.
getReceivablePriceRank
(
props
.
queryParams
)
// 2.1 更新 Echarts 数据
if
(
echartsOption
.
dataset
&&
echartsOption
.
dataset
[
'source'
])
{
echartsOption
.
dataset
[
'source'
]
=
clone
(
rankingList
).
reverse
()
}
// 更新列表数据
//
2.2
更新列表数据
list
.
value
=
rankingList
trendLoading
.
value
=
false
loading
.
value
=
false
}
defineExpose
({
loadData
})
/** 重新加载数据 */
const
reloadData
=
async
()
=>
{
await
getRankingReceivablesStatistics
()
}
// 暴露 reloadData 函数
defineExpose
({
reloadData
})
/** 初始化 */
onMounted
(()
=>
{
getRankingReceivablesStatistics
()
loadData
()
})
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/views/crm/bi/rank
ing
/index.vue
→
src/views/crm/bi/rank/index.vue
View file @
4549f8ed
<!-- BI 排行版 -->
<
template
>
<ContentWrap>
<!-- 搜索工作栏 -->
...
...
@@ -8,9 +9,9 @@
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"时间"
prop=
"orderDate"
>
<el-form-item
label=
"时间
范围
"
prop=
"orderDate"
>
<el-date-picker
v-model=
"queryParams.
orderDate
"
v-model=
"queryParams.
times
"
:shortcuts=
"defaultShortcuts"
class=
"!w-240px"
end-placeholder=
"结束日期"
...
...
@@ -36,55 +37,52 @@
</el-form-item>
</el-form>
</ContentWrap>
<!-- 排行数据 -->
<el-col>
<el-tabs
v-model=
"activeTab"
>
<!-- 合同金额排行 -->
<el-tab-pane
label=
"合同金额排行"
name=
"contract
AmountRanking"
>
<
RankingContractStatistics
:queryParams=
"queryParams"
ref=
"rankingContractStatistics
Ref"
/>
<el-tab-pane
label=
"合同金额排行"
name=
"contract
PriceRank"
lazy
>
<
ContractPriceRank
:query-params=
"queryParams"
ref=
"contractPriceRank
Ref"
/>
</el-tab-pane>
<!-- 回款金额排行 -->
<el-tab-pane
label=
"回款金额排行"
name=
"receivablesRanKing"
lazy
>
<RankingReceivablesStatistics
:queryParams=
"queryParams"
ref=
"rankingReceivablesStatisticsRef"
/>
<el-tab-pane
label=
"回款金额排行"
name=
"receivablePriceRank"
lazy
>
<ReceivablePriceRank
:query-params=
"queryParams"
ref=
"receivablePriceRankRef"
/>
</el-tab-pane>
</el-tabs>
</el-col>
</
template
>
<
script
lang=
"ts"
setup
>
import
RankingContractStatistics
from
'./components/RankingContractStatistics.vue'
import
ContractPriceRank
from
'./ContractPriceRank.vue'
import
ReceivablePriceRank
from
'./ReceivablePriceRank.vue'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
*
as
DeptApi
from
'@/api/system/dept'
import
{
beginOfDay
,
defaultShortcuts
,
endOfDay
,
formatDate
}
from
'@/utils/formatTime'
import
RankingReceivablesStatistics
from
'@/views/crm/bi/ranking/components/RankingReceivablesStatistics.vue
'
import
{
useUserStore
}
from
'@/store/modules/user
'
/** 排行榜 */
defineOptions
({
name
:
'RankingStatistics'
})
defineOptions
({
name
:
'CrmBiRank'
})
const
queryParams
=
reactive
({
deptId
:
u
ndefine
d
,
//默认显示最近一周的数据
orderDate
:
[
deptId
:
u
seUserStore
().
getUser
.
deptI
d
,
times
:
[
// 默认显示最近一周的数据
formatDate
(
beginOfDay
(
new
Date
(
new
Date
().
getTime
()
-
3600
*
1000
*
24
*
7
))),
formatDate
(
endOfDay
(
new
Date
(
new
Date
().
getTime
()
-
3600
*
1000
*
24
)))
],
startTime
:
undefined
,
endTime
:
undefined
]
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
deptList
=
ref
<
Tree
[]
>
([])
// 树形结构
const
activeTab
=
ref
(
'contract
AmountRanking
'
)
const
rankingContractStatisticsRef
=
ref
()
// RankingContractStatistics
组件的引用
const
r
ankingReceivablesStatisticsRef
=
ref
()
// RankingReceivablesStatistics
组件的引用
const
activeTab
=
ref
(
'contract
PriceRank
'
)
const
contractPriceRankRef
=
ref
()
// ContractPriceRank
组件的引用
const
r
eceivablePriceRankRef
=
ref
()
// ReceivablePriceRank
组件的引用
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
if
(
activeTab
.
value
===
'contract
AmountRanking
'
)
{
rankingContractStatisticsRef
.
value
.
re
loadData
()
}
else
if
(
activeTab
.
value
===
'receivable
sRanKing
'
)
{
r
ankingReceivablesStatisticsRef
.
value
.
re
loadData
()
if
(
activeTab
.
value
===
'contract
PriceRank
'
)
{
contractPriceRankRef
.
value
.
loadData
()
}
else
if
(
activeTab
.
value
===
'receivable
PriceRank
'
)
{
r
eceivablePriceRankRef
.
value
.
loadData
()
}
}
...
...
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