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
770e5519
authored
Jan 28, 2024
by
anhaohao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增:商业智能-排行榜,合同金额排行和回款金额排行
parent
64cfcbf6
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
395 additions
and
1 deletions
+395
-1
src/api/crm/bi/ranking.ts
+34
-0
src/utils/dict.ts
+4
-1
src/views/crm/bi/ranking/components/RankingContractStatistics.vue
+133
-0
src/views/crm/bi/ranking/components/RankingReceivablesStatistics.vue
+133
-0
src/views/crm/bi/ranking/index.vue
+91
-0
No files found.
src/api/crm/bi/ranking.ts
0 → 100644
View file @
770e5519
import
request
from
'@/config/axios'
export
interface
BiContractRanKingRespVO
{
price
:
number
nickname
:
string
deptName
:
string
}
export
interface
BiReceivablesRanKingRespVO
{
price
:
number
nickname
:
string
deptName
:
string
}
export
interface
BiRankReqVO
{
deptId
:
number
type
:
string
}
// 排行 API
export
const
RankingStatisticsApi
=
{
// 获得合同排行榜
contractAmountRanking
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/bi/ranking/contract-ranking'
,
params
})
},
// 获得回款排行榜
receivablesAmountRanking
:
(
params
:
any
)
=>
{
return
request
.
get
({
url
:
'/bi/ranking/receivables-ranking'
,
params
})
}
}
src/utils/dict.ts
View file @
770e5519
...
...
@@ -203,5 +203,8 @@ export enum DICT_TYPE {
CRM_PRODUCT_STATUS
=
'crm_product_status'
,
CRM_PERMISSION_LEVEL
=
'crm_permission_level'
,
// CRM 数据权限的级别
CRM_PRODUCT_UNIT
=
'crm_product_unit'
,
// 产品单位
CRM_FOLLOW_UP_TYPE
=
'crm_follow_up_type'
// 跟进方式
CRM_FOLLOW_UP_TYPE
=
'crm_follow_up_type'
,
// 跟进方式
// ========== BI - 商业智能模块 ==========
BI_ANALYZE_TYPE
=
'bi_analyze_type'
// 分析类型
}
src/views/crm/bi/ranking/components/RankingContractStatistics.vue
0 → 100644
View file @
770e5519
<
template
>
<el-card
shadow=
"never"
>
<!-- 柱状图 -->
<el-skeleton
:loading=
"trendLoading"
animated
>
<Echart
:height=
"500"
:options=
"barChartOptions"
/>
</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>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
RankingStatisticsApi
,
BiContractRanKingRespVO
,
BiRankReqVO
}
from
'@/api/crm/bi/ranking'
import
{
EChartsOption
}
from
'echarts'
/** 合同金额排行 */
defineOptions
({
name
:
'RankingContractStatistics'
})
const
trendLoading
=
ref
(
true
)
// 状态加载中
const
loading
=
ref
(
false
)
// 列表的加载中
const
list
=
ref
<
BiContractRanKingRespVO
[]
>
([])
// 列表的数据
const
params
=
defineProps
<
{
queryParams
:
BiRankReqVO
}
>
()
// 搜索参数
/** 柱状图配置 横向 */
const
barChartOptions
=
reactive
<
EChartsOption
>
({
dataset
:
{
dimensions
:
[
'name'
,
'value'
],
source
:
[]
},
grid
:
{
left
:
20
,
right
:
20
,
bottom
:
20
,
top
:
80
,
containLabel
:
true
},
legend
:
{
top
:
50
},
series
:
[
{
name
:
'合同金额排行'
,
type
:
'bar'
,
smooth
:
true
,
itemStyle
:
{
color
:
'#B37FEB'
}
}
],
toolbox
:
{
feature
:
{
// 数据区域缩放
dataZoom
:
{
yAxisIndex
:
false
// Y轴不缩放
},
brush
:
{
type
:
[
'lineX'
,
'clear'
]
// 区域缩放按钮、还原按钮
},
saveAsImage
:
{
show
:
true
,
name
:
'合同金额排行'
}
// 保存为图片
}
},
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
}
},
xAxis
:
{
type
:
'value'
,
name
:
'合同金额(元)'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
}
},
yAxis
:
{
type
:
'category'
,
name
:
'签订人'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
},
axisLabel
:
{
formatter
:
(
value
:
string
)
=>
{
return
value
}
}
}
})
as
EChartsOption
/** 获取合同金额排行 */
const
getRankingContractStatistics
=
async
()
=>
{
trendLoading
.
value
=
true
loading
.
value
=
true
const
rankingList
=
await
RankingStatisticsApi
.
contractAmountRanking
(
params
.
queryParams
)
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
}
// 更新列表数据
list
.
value
=
rankingList
trendLoading
.
value
=
false
loading
.
value
=
false
}
/** 重新加载数据 */
const
reloadData
=
async
()
=>
{
await
getRankingContractStatistics
()
}
// 暴露 reloadData 函数
defineExpose
({
reloadData
})
onMounted
(()
=>
{
getRankingContractStatistics
()
})
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/views/crm/bi/ranking/components/RankingReceivablesStatistics.vue
0 → 100644
View file @
770e5519
<
template
>
<el-card
shadow=
"never"
>
<!-- 柱状图 -->
<el-skeleton
:loading=
"trendLoading"
animated
>
<Echart
:height=
"500"
:options=
"barChartOptions"
/>
</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>
</el-card>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
RankingStatisticsApi
,
BiReceivablesRanKingRespVO
}
from
'@/api/crm/bi/ranking'
import
{
EChartsOption
}
from
'echarts'
/** 回款金额排行 */
defineOptions
({
name
:
'RankingReceivablesStatistics'
})
const
trendLoading
=
ref
(
true
)
// 状态加载中
const
loading
=
ref
(
false
)
// 列表的加载中
const
list
=
ref
<
BiReceivablesRanKingRespVO
[]
>
([])
// 列表的数据
const
params
=
defineProps
<
{
queryParams
:
any
}
>
()
// 搜索参数
/** 柱状图配置 横向 */
const
barChartOptions
=
reactive
<
EChartsOption
>
({
dataset
:
{
dimensions
:
[
'name'
,
'value'
],
source
:
[]
},
grid
:
{
left
:
20
,
right
:
20
,
bottom
:
20
,
top
:
80
,
containLabel
:
true
},
legend
:
{
top
:
50
},
series
:
[
{
name
:
'回款金额排行'
,
type
:
'bar'
,
smooth
:
true
,
itemStyle
:
{
color
:
'#B37FEB'
}
}
],
toolbox
:
{
feature
:
{
// 数据区域缩放
dataZoom
:
{
yAxisIndex
:
false
// Y轴不缩放
},
brush
:
{
type
:
[
'lineX'
,
'clear'
]
// 区域缩放按钮、还原按钮
},
saveAsImage
:
{
show
:
true
,
name
:
'回款金额排行'
}
// 保存为图片
}
},
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
}
},
xAxis
:
{
type
:
'value'
,
name
:
'回款金额(元)'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
}
},
yAxis
:
{
type
:
'category'
,
name
:
'签订人'
,
nameGap
:
30
,
nameTextStyle
:
{
color
:
'#666'
,
fontSize
:
14
},
axisLabel
:
{
formatter
:
(
value
:
string
)
=>
{
return
value
}
}
}
})
as
EChartsOption
/** 获取回款金额排行 */
const
getRankingReceivablesStatistics
=
async
()
=>
{
trendLoading
.
value
=
true
loading
.
value
=
true
const
rankingList
=
await
RankingStatisticsApi
.
receivablesAmountRanking
(
params
.
queryParams
)
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
}
// 更新列表数据
list
.
value
=
rankingList
trendLoading
.
value
=
false
loading
.
value
=
false
}
/** 重新加载数据 */
const
reloadData
=
async
()
=>
{
await
getRankingReceivablesStatistics
()
}
// 暴露 reloadData 函数
defineExpose
({
reloadData
})
onMounted
(()
=>
{
getRankingReceivablesStatistics
()
})
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
src/views/crm/bi/ranking/index.vue
0 → 100644
View file @
770e5519
<
template
>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"类型"
prop=
"type"
>
<el-select
v-model=
"queryParams.type"
placeholder=
"请选择类型"
clearable
class=
"!w-240px"
>
<el-option
v-for=
"dict in getIntDictOptions(DICT_TYPE.BI_ANALYZE_TYPE)"
:key=
"dict.value"
:label=
"dict.label"
:value=
"dict.value"
/>
</el-select>
</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=
"请选择归属部门"
/>
</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=
"contractAmountRanking"
>
<!-- 合同金额排行 -->
<RankingContractStatistics
:queryParams=
"queryParams"
ref=
"rankingContractStatisticsRef"
/>
</el-tab-pane>
<el-tab-pane
label=
"回款金额排行"
name=
"receivablesRanKing"
lazy
>
<!-- 回款金额排行 -->
<RankingReceivablesStatistics
:queryParams=
"queryParams"
ref=
"rankingReceivablesStatisticsRef"
/>
</el-tab-pane>
</el-tabs>
</el-col>
</
template
>
<
script
lang=
"ts"
setup
>
import
RankingContractStatistics
from
'./components/RankingContractStatistics.vue'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
*
as
DeptApi
from
'@/api/system/dept'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
/** 排行榜 */
defineOptions
({
name
:
'RankingStatistics'
})
const
queryParams
=
reactive
({
type
:
9
,
// 将 type 的初始值设置为 9 本年
deptId
:
null
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
deptList
=
ref
<
Tree
[]
>
([])
// 树形结构
const
activeTab
=
ref
(
'contractAmountRanking'
)
const
rankingContractStatisticsRef
=
ref
()
// RankingContractStatistics组件的引用
const
rankingReceivablesStatisticsRef
=
ref
()
// RankingReceivablesStatistics组件的引用
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
if
(
activeTab
.
value
===
'contractAmountRanking'
)
{
rankingContractStatisticsRef
.
value
.
reloadData
()
}
else
if
(
activeTab
.
value
===
'receivablesRanKing'
)
{
rankingReceivablesStatisticsRef
.
value
.
reloadData
()
}
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
.
value
.
resetFields
()
handleQuery
()
}
// 加载部门树
onMounted
(
async
()
=>
{
deptList
.
value
=
handleTree
(
await
DeptApi
.
getSimpleDeptList
())
})
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
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