Skip to content

Commit f0a2c52

Browse files
YunaiVgitee-org
authored andcommitted
!378 新增:商业智能-排行榜,合同金额排行和回款金额排行
Merge pull request !378 from 安浩浩/dev
2 parents 64cfcbf + 770e551 commit f0a2c52

File tree

5 files changed

+395
-1
lines changed

5 files changed

+395
-1
lines changed

src/api/crm/bi/ranking.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import request from '@/config/axios'
2+
3+
export interface BiContractRanKingRespVO {
4+
price: number
5+
nickname: string
6+
deptName: string
7+
}
8+
export interface BiReceivablesRanKingRespVO {
9+
price: number
10+
nickname: string
11+
deptName: string
12+
}
13+
export interface BiRankReqVO {
14+
deptId: number
15+
type: string
16+
}
17+
18+
// 排行 API
19+
export const RankingStatisticsApi = {
20+
// 获得合同排行榜
21+
contractAmountRanking: (params: any) => {
22+
return request.get({
23+
url: '/bi/ranking/contract-ranking',
24+
params
25+
})
26+
},
27+
// 获得回款排行榜
28+
receivablesAmountRanking: (params: any) => {
29+
return request.get({
30+
url: '/bi/ranking/receivables-ranking',
31+
params
32+
})
33+
}
34+
}

src/utils/dict.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,5 +203,8 @@ export enum DICT_TYPE {
203203
CRM_PRODUCT_STATUS = 'crm_product_status',
204204
CRM_PERMISSION_LEVEL = 'crm_permission_level', // CRM 数据权限的级别
205205
CRM_PRODUCT_UNIT = 'crm_product_unit', // 产品单位
206-
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type' // 跟进方式
206+
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // 跟进方式
207+
208+
// ========== BI - 商业智能模块 ==========
209+
BI_ANALYZE_TYPE = 'bi_analyze_type' // 分析类型
207210
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<template>
2+
<el-card shadow="never">
3+
<!-- 柱状图 -->
4+
<el-skeleton :loading="trendLoading" animated>
5+
<Echart :height="500" :options="barChartOptions" />
6+
</el-skeleton>
7+
</el-card>
8+
<el-card shadow="never" class="mt-16px">
9+
<!-- 排行列表 -->
10+
<el-table v-loading="loading" :data="list">
11+
<el-table-column label="公司排名" align="center" type="index" width="80" />
12+
<el-table-column label="签订人" align="center" prop="nickname" min-width="200" />
13+
<el-table-column label="部门" align="center" prop="deptName" min-width="200" />
14+
<el-table-column label="合同金额(元)" align="center" prop="price" min-width="200" />
15+
</el-table>
16+
</el-card>
17+
</template>
18+
<script setup lang="ts">
19+
import { RankingStatisticsApi, BiContractRanKingRespVO, BiRankReqVO } from '@/api/crm/bi/ranking'
20+
import { EChartsOption } from 'echarts'
21+
22+
/** 合同金额排行 */
23+
defineOptions({ name: 'RankingContractStatistics' })
24+
25+
const trendLoading = ref(true) // 状态加载中
26+
const loading = ref(false) // 列表的加载中
27+
const list = ref<BiContractRanKingRespVO[]>([]) // 列表的数据
28+
const params = defineProps<{ queryParams: BiRankReqVO }>() // 搜索参数
29+
30+
/** 柱状图配置 横向 */
31+
const barChartOptions = reactive<EChartsOption>({
32+
dataset: {
33+
dimensions: ['name', 'value'],
34+
source: []
35+
},
36+
grid: {
37+
left: 20,
38+
right: 20,
39+
bottom: 20,
40+
top: 80,
41+
containLabel: true
42+
},
43+
legend: {
44+
top: 50
45+
},
46+
series: [
47+
{
48+
name: '合同金额排行',
49+
type: 'bar',
50+
smooth: true,
51+
itemStyle: { color: '#B37FEB' }
52+
}
53+
],
54+
toolbox: {
55+
feature: {
56+
// 数据区域缩放
57+
dataZoom: {
58+
yAxisIndex: false // Y轴不缩放
59+
},
60+
brush: {
61+
type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮
62+
},
63+
saveAsImage: { show: true, name: '合同金额排行' } // 保存为图片
64+
}
65+
},
66+
tooltip: {
67+
trigger: 'axis',
68+
axisPointer: {
69+
type: 'shadow'
70+
}
71+
},
72+
xAxis: {
73+
type: 'value',
74+
name: '合同金额(元)',
75+
nameGap: 30,
76+
nameTextStyle: {
77+
color: '#666',
78+
fontSize: 14
79+
}
80+
},
81+
yAxis: {
82+
type: 'category',
83+
name: '签订人',
84+
nameGap: 30,
85+
nameTextStyle: {
86+
color: '#666',
87+
fontSize: 14
88+
},
89+
axisLabel: {
90+
formatter: (value: string) => {
91+
return value
92+
}
93+
}
94+
}
95+
}) as EChartsOption
96+
97+
/** 获取合同金额排行 */
98+
const getRankingContractStatistics = async () => {
99+
trendLoading.value = true
100+
loading.value = true
101+
const rankingList = await RankingStatisticsApi.contractAmountRanking(params.queryParams)
102+
let source = rankingList.map((item: BiContractRanKingRespVO) => {
103+
return {
104+
name: item.nickname,
105+
value: item.price
106+
}
107+
})
108+
// 反转数据源
109+
source = source.reverse()
110+
// 更新 Echarts 数据
111+
if (barChartOptions.dataset && barChartOptions.dataset['source']) {
112+
barChartOptions.dataset['source'] = source
113+
}
114+
// 更新列表数据
115+
list.value = rankingList
116+
trendLoading.value = false
117+
loading.value = false
118+
}
119+
120+
/** 重新加载数据 */
121+
const reloadData = async () => {
122+
await getRankingContractStatistics()
123+
}
124+
// 暴露 reloadData 函数
125+
defineExpose({
126+
reloadData
127+
})
128+
129+
onMounted(() => {
130+
getRankingContractStatistics()
131+
})
132+
</script>
133+
<style scoped lang="scss"></style>
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<template>
2+
<el-card shadow="never">
3+
<!-- 柱状图 -->
4+
<el-skeleton :loading="trendLoading" animated>
5+
<Echart :height="500" :options="barChartOptions" />
6+
</el-skeleton>
7+
</el-card>
8+
<el-card shadow="never" class="mt-16px">
9+
<!-- 排行列表 -->
10+
<el-table v-loading="loading" :data="list">
11+
<el-table-column label="公司排名" align="center" type="index" width="80" />
12+
<el-table-column label="签订人" align="center" prop="nickname" min-width="200" />
13+
<el-table-column label="部门" align="center" prop="deptName" min-width="200" />
14+
<el-table-column label="合同金额(元)" align="center" prop="price" min-width="200" />
15+
</el-table>
16+
</el-card>
17+
</template>
18+
<script setup lang="ts">
19+
import { RankingStatisticsApi, BiReceivablesRanKingRespVO } from '@/api/crm/bi/ranking'
20+
import { EChartsOption } from 'echarts'
21+
22+
/** 回款金额排行 */
23+
defineOptions({ name: 'RankingReceivablesStatistics' })
24+
25+
const trendLoading = ref(true) // 状态加载中
26+
const loading = ref(false) // 列表的加载中
27+
const list = ref<BiReceivablesRanKingRespVO[]>([]) // 列表的数据
28+
const params = defineProps<{ queryParams: any }>() // 搜索参数
29+
30+
/** 柱状图配置 横向 */
31+
const barChartOptions = reactive<EChartsOption>({
32+
dataset: {
33+
dimensions: ['name', 'value'],
34+
source: []
35+
},
36+
grid: {
37+
left: 20,
38+
right: 20,
39+
bottom: 20,
40+
top: 80,
41+
containLabel: true
42+
},
43+
legend: {
44+
top: 50
45+
},
46+
series: [
47+
{
48+
name: '回款金额排行',
49+
type: 'bar',
50+
smooth: true,
51+
itemStyle: { color: '#B37FEB' }
52+
}
53+
],
54+
toolbox: {
55+
feature: {
56+
// 数据区域缩放
57+
dataZoom: {
58+
yAxisIndex: false // Y轴不缩放
59+
},
60+
brush: {
61+
type: ['lineX', 'clear'] // 区域缩放按钮、还原按钮
62+
},
63+
saveAsImage: { show: true, name: '回款金额排行' } // 保存为图片
64+
}
65+
},
66+
tooltip: {
67+
trigger: 'axis',
68+
axisPointer: {
69+
type: 'shadow'
70+
}
71+
},
72+
xAxis: {
73+
type: 'value',
74+
name: '回款金额(元)',
75+
nameGap: 30,
76+
nameTextStyle: {
77+
color: '#666',
78+
fontSize: 14
79+
}
80+
},
81+
yAxis: {
82+
type: 'category',
83+
name: '签订人',
84+
nameGap: 30,
85+
nameTextStyle: {
86+
color: '#666',
87+
fontSize: 14
88+
},
89+
axisLabel: {
90+
formatter: (value: string) => {
91+
return value
92+
}
93+
}
94+
}
95+
}) as EChartsOption
96+
97+
/** 获取回款金额排行 */
98+
const getRankingReceivablesStatistics = async () => {
99+
trendLoading.value = true
100+
loading.value = true
101+
const rankingList = await RankingStatisticsApi.receivablesAmountRanking(params.queryParams)
102+
let source = rankingList.map((item: BiReceivablesRanKingRespVO) => {
103+
return {
104+
name: item.nickname,
105+
value: item.price
106+
}
107+
})
108+
// 反转数据源
109+
source = source.reverse()
110+
// 更新 Echarts 数据
111+
if (barChartOptions.dataset && barChartOptions.dataset['source']) {
112+
barChartOptions.dataset['source'] = source
113+
}
114+
// 更新列表数据
115+
list.value = rankingList
116+
trendLoading.value = false
117+
loading.value = false
118+
}
119+
120+
/** 重新加载数据 */
121+
const reloadData = async () => {
122+
await getRankingReceivablesStatistics()
123+
}
124+
// 暴露 reloadData 函数
125+
defineExpose({
126+
reloadData
127+
})
128+
129+
onMounted(() => {
130+
getRankingReceivablesStatistics()
131+
})
132+
</script>
133+
<style scoped lang="scss"></style>

0 commit comments

Comments
 (0)