From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/crm/statistics/performance/components/ContractPricePerformance.vue | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 236 insertions(+), 0 deletions(-)
diff --git a/src/views/crm/statistics/performance/components/ContractPricePerformance.vue b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue
new file mode 100644
index 0000000..dd52d9f
--- /dev/null
+++ b/src/views/crm/statistics/performance/components/ContractPricePerformance.vue
@@ -0,0 +1,236 @@
+<!-- 鍛樺伐涓氱哗缁熻 -->
+<template>
+ <!-- Echarts鍥� -->
+ <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="tableData">
+ <el-table-column
+ v-for="item in columnsData"
+ :key="item.prop"
+ :label="item.label"
+ :prop="item.prop"
+ align="center"
+ >
+ <template #default="scope">
+ {{ scope.row[item.prop] }}
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-card>
+</template>
+<script setup lang="ts">
+import { EChartsOption } from 'echarts'
+import {
+ StatisticsPerformanceApi,
+ StatisticsPerformanceRespVO
+} from '@/api/crm/statistics/performance'
+
+defineOptions({ name: 'ContractPricePerformance' })
+const props = defineProps<{ queryParams: any }>() // 鎼滅储鍙傛暟
+
+const loading = ref(false) // 鍔犺浇涓�
+const list = ref<StatisticsPerformanceRespVO[]>([]) // 鍒楄〃鐨勬暟鎹�
+
+/** 鏌辩姸鍥鹃厤缃細绾靛悜 */
+const echartsOption = reactive<EChartsOption>({
+ grid: {
+ left: 20,
+ right: 20,
+ bottom: 20,
+ containLabel: true
+ },
+ legend: {},
+ series: [
+ {
+ name: '褰撴湀鍚堝悓閲戦锛堝厓锛�',
+ type: 'line',
+ data: []
+ },
+ {
+ name: '涓婃湀鍚堝悓閲戦锛堝厓锛�',
+ type: 'line',
+ data: []
+ },
+ {
+ name: '鍘诲勾鍚屾湀鍚堝悓閲戦锛堝厓锛�',
+ type: 'line',
+ data: []
+ },
+ {
+ name: '鐜瘮澧為暱鐜囷紙%锛�',
+ type: 'line',
+ yAxisIndex: 1,
+ data: []
+ },
+ {
+ name: '鍚屾瘮澧為暱鐜囷紙%锛�',
+ type: 'line',
+ yAxisIndex: 1,
+ data: []
+ }
+ ],
+ toolbox: {
+ feature: {
+ dataZoom: {
+ xAxisIndex: false // 鏁版嵁鍖哄煙缂╂斁锛歒 杞翠笉缂╂斁
+ },
+ brush: {
+ type: ['lineX', 'clear'] // 鍖哄煙缂╂斁鎸夐挳銆佽繕鍘熸寜閽�
+ },
+ saveAsImage: { show: true, name: '瀹㈡埛鎬婚噺鍒嗘瀽' } // 淇濆瓨涓哄浘鐗�
+ }
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow'
+ }
+ },
+ yAxis: [
+ {
+ type: 'value',
+ name: '閲戦锛堝厓锛�',
+ axisTick: {
+ show: false
+ },
+ axisLabel: {
+ color: '#BDBDBD',
+ formatter: '{value}'
+ },
+ /** 鍧愭爣杞磋酱绾跨浉鍏宠缃� */
+ axisLine: {
+ lineStyle: {
+ color: '#BDBDBD'
+ }
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: '#e6e6e6'
+ }
+ }
+ },
+ {
+ type: 'value',
+ name: '',
+ axisTick: {
+ alignWithLabel: true,
+ lineStyle: {
+ width: 0
+ }
+ },
+ axisLabel: {
+ color: '#BDBDBD',
+ formatter: '{value}%'
+ },
+ /** 鍧愭爣杞磋酱绾跨浉鍏宠缃� */
+ axisLine: {
+ lineStyle: {
+ color: '#BDBDBD'
+ }
+ },
+ splitLine: {
+ show: true,
+ lineStyle: {
+ color: '#e6e6e6'
+ }
+ }
+ }
+ ],
+ xAxis: {
+ type: 'category',
+ name: '鏃ユ湡',
+ data: []
+ }
+}) as EChartsOption
+
+/** 鑾峰彇缁熻鏁版嵁 */
+const loadData = async () => {
+ // 1. 鍔犺浇缁熻鏁版嵁
+ loading.value = true
+ const performanceList = await StatisticsPerformanceApi.getContractPricePerformance(
+ props.queryParams
+ )
+
+ // 2.1 鏇存柊 Echarts 鏁版嵁
+ if (echartsOption.xAxis && echartsOption.xAxis['data']) {
+ echartsOption.xAxis['data'] = performanceList.map((s: StatisticsPerformanceRespVO) => s.time)
+ }
+ if (echartsOption.series && echartsOption.series[0] && echartsOption.series[0]['data']) {
+ echartsOption.series[0]['data'] = performanceList.map(
+ (s: StatisticsPerformanceRespVO) => s.currentMonthCount
+ )
+ }
+ if (echartsOption.series && echartsOption.series[1] && echartsOption.series[1]['data']) {
+ echartsOption.series[1]['data'] = performanceList.map(
+ (s: StatisticsPerformanceRespVO) => s.lastMonthCount
+ )
+ echartsOption.series[3]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) =>
+ s.lastMonthCount !== 0
+ ? (((s.currentMonthCount - s.lastMonthCount) / s.lastMonthCount) * 100).toFixed(2)
+ : 'NULL'
+ )
+ }
+ if (echartsOption.series && echartsOption.series[2] && echartsOption.series[2]['data']) {
+ echartsOption.series[2]['data'] = performanceList.map(
+ (s: StatisticsPerformanceRespVO) => s.lastYearCount
+ )
+ echartsOption.series[4]['data'] = performanceList.map((s: StatisticsPerformanceRespVO) =>
+ s.lastYearCount !== 0
+ ? (((s.currentMonthCount - s.lastYearCount) / s.lastYearCount) * 100).toFixed(2)
+ : 'NULL'
+ )
+ }
+
+ // 2.2 鏇存柊鍒楄〃鏁版嵁
+ list.value = performanceList
+ convertListData()
+ loading.value = false
+}
+
+// 鍒濆鍖栨暟鎹�
+const columnsData = reactive([])
+const tableData = reactive([
+ { title: '褰撴湀鍚堝悓閲戦缁熻锛堝厓锛�' },
+ { title: '涓婃湀鍚堝悓閲戦缁熻锛堝厓锛�' },
+ { title: '鍘诲勾褰撴湀鍚堝悓閲戦缁熻锛堝厓锛�' },
+ { title: '鐜瘮澧為暱鐜囷紙%锛�' },
+ { title: '鍚屾瘮澧為暱鐜囷紙%锛�' }
+])
+
+// 瀹氫箟 init 鏂规硶
+const convertListData = () => {
+ const columnObj = { label: '鏃ユ湡', prop: 'title' }
+ columnsData.splice(0, columnsData.length) //娓呯┖鏁扮粍
+ columnsData.push(columnObj)
+
+ list.value.forEach((item, index) => {
+ const columnObj = { label: item.time, prop: 'prop' + index }
+ columnsData.push(columnObj)
+ tableData[0]['prop' + index] = item.currentMonthCount
+ tableData[1]['prop' + index] = item.lastMonthCount
+ tableData[2]['prop' + index] = item.lastYearCount
+ tableData[3]['prop' + index] =
+ item.lastMonthCount !== 0
+ ? (((item.currentMonthCount - item.lastMonthCount) / item.lastMonthCount) * 100).toFixed(2)
+ : 'NULL'
+ tableData[4]['prop' + index] =
+ item.lastYearCount !== 0
+ ? (((item.currentMonthCount - item.lastYearCount) / item.lastYearCount) * 100).toFixed(2)
+ : 'NULL'
+ })
+}
+
+defineExpose({ loadData })
+
+/** 鍒濆鍖� */
+onMounted(async () => {
+ await loadData()
+})
+</script>
--
Gitblit v1.8.0