Bladeren bron

站点看板统计

zuy 2 jaren geleden
bovenliggende
commit
042fcfe628
1 gewijzigde bestanden met toevoegingen van 351 en 94 verwijderingen
  1. 351 94
      admin-web/src/views/admin/kanban/index.vue

+ 351 - 94
admin-web/src/views/admin/kanban/index.vue

@@ -40,6 +40,7 @@
             label-key="stationName"
             clearable
             multiple
+            @on-change="loadData"
             :data-list="state.stationList"
             style="min-width: 150px;"
             class=" mr10">
@@ -55,6 +56,7 @@
             :value-format="state.dateFormat"
             v-model="state.formQuery.dateRange"
             :type="state.dateType"
+            @change="loadData"
             unlink-panels
             range-separator="至"
             start-placeholder="开始时间"
@@ -74,71 +76,27 @@
     <el-scrollbar>
       <el-card>
         <el-card shadow="hover" class="layout-padding-auto">
-          <template #header>充电用户数</template>
+          <template #header>充电用户及有效订单数</template>
           <template #default>
             <div style="min-height: 500px;padding: 20px;" ref="chartOneRef"></div>
           </template>
         </el-card>
 
-        <el-card shadow="hover" class="layout-padding-auto">
-          <template #header>有效订单数</template>
+        <el-card shadow="hover" class="layout-padding-auto mt10">
+          <template #header>电费/服务费</template>
           <template #default>
-            <div style="min-height: 300px;padding: 20px;" ref="chartTwoRef"></div>
+            <div style="min-height: 500px;padding: 20px;" ref="chartTwoRef"></div>
           </template>
         </el-card>
 
-        <el-card shadow="hover" class="layout-padding-auto">
-          <template #header>电量</template>
+        <el-card shadow="hover" class="layout-padding-auto mt10">
+          <template #header>电量/平均电量</template>
           <template #default>
-            <div style="min-height: 300px;padding: 20px;" ref="chartThreeRef"></div>
+            <div style="min-height: 500px;padding: 20px;" ref="chartThreeRef"></div>
           </template>
         </el-card>
 
-        <!--
-                <el-card shadow="hover" class="layout-padding-auto">
-                  <template #header>总金额</template>
-                  <template #default>
-                    XXXx
-                  </template>
-                </el-card>
-
-
-                <el-card shadow="hover" class="layout-padding-auto">
-                  <template #header>总电费</template>
-                  <template #default>
-                    XXXx
-                  </template>
-                </el-card>
-
-                <el-card shadow="hover" class="layout-padding-auto">
-                  <template #header>服务费</template>
-                  <template #default>
-                    XXXx
-                  </template>
-                </el-card>
-
-                <el-card shadow="hover" class="layout-padding-auto">
-                  <template #header>平均电量</template>
-                  <template #default>
-                    XXXx
-                  </template>
-                </el-card>
-
-
-                <el-card shadow="hover" class="layout-padding-auto">
-                  <template #header>平均订单费用</template>
-                  <template #default>
-                    XXXx
-                  </template>
-                </el-card>
-
-
-                <el-card shadow="hover" class="layout-padding-auto">
-                  <template #header>平均充电用电量</template>
-                  <template #default>
-                    XXXx
-                  </template>
-                </el-card>-->
+
       </el-card>
 
     </el-scrollbar>
@@ -146,7 +104,7 @@
 </template>
 
 <script setup lang="ts" name="KanbanList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onUnmounted} from 'vue';
+import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onUnmounted, markRaw} from 'vue';
 import {$body, $get} from "/@/utils/request";
 import {Msg} from "/@/utils/message";
 import * as echarts from 'echarts';
@@ -241,6 +199,8 @@ onUnmounted(() => {
 window.onresize = function () {
   //自适应大小
   state.chartOne.resize();
+  state.chartTwo.resize();
+  state.chartThree.resize();
 };
 
 //region 方法区
@@ -287,31 +247,44 @@ const loadData = () => {
     console.log(res)
     state.chartData = res;
     buildOrderChart()
+    buildMoneyChart()
+    buildElectricChart()
   })
 };
 
 /**
- * 充电人数、有限订单数
+ * 充电人数、有限订单数散点图
  */
 const buildOrderChart = () => {
+
   if (state.chartOne) {
     state.chartOne.dispose();
   }
-  state.chartOne = echarts.init(chartOneRef.value, state.theme);
+  state.chartOne = markRaw(echarts.init(chartOneRef.value, state.theme));
   let {type} = state.formQuery
   let stationIdList = Object.keys(state.chartData);
   if (u.isEmptyOrNull(stationIdList)) {
     Msg.message('未查询到统计数据', 'error')
     return;
   }
-  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => k.statDay);
+  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => type==='day'?k.statDay:k.statMonth);
   let legends:Array<string> =[];
   state.stationList.filter((k: any) => stationIdList.includes(k.stationId)).forEach(item=>{
-    legends.push(item.stationName+'-充电人数')
-    legends.push(item.stationName+'-订单数')
+    legends.push(item.stationName)
+    // legends.push(item.stationName+'-平均订单电量')
+    // legends.push(item.stationName+'-平均充电电量')
   })
 
-  let y1Max = 0, y2Max = 0;
+  const itemStyle = {
+    opacity: 0.8,
+    shadowBlur: 10,
+    shadowOffsetX: 0,
+    shadowOffsetY: 0,
+    shadowColor: 'rgba(0,0,0,0.3)'
+  };
+
+
+  let y1Max = 0,y2Max=0;
   let series: Array<any> = [];
   stationIdList.forEach((stationId: string) => {
     let tmpUserMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.chargeUsers))
@@ -320,45 +293,204 @@ const buildOrderChart = () => {
     let tmpOrderMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.validOrders))
     y2Max = Math.max(y2Max, tmpOrderMax)
 
+    let station = state.stationList.find((k: any) => k.stationId == stationId);
+    let {stationName} = station;
+
+    series.push({
+      name: stationName,
+      type: 'scatter',
+      itemStyle:itemStyle,
+      data: state.chartData[stationId].map((k: any) =>  {
+        return [type==='day'?k.statDay:k.statMonth,k.chargeUsers,k.validOrders]
+      })
+    })
+  });
+
+
+
+
+  const schema = [
+    { name: 'date', index: 0, text: '日' },
+    { name: '充电人次', index: 1, text: '充电人次' },
+    { name: '有效订单', index: 2, text: '有效订单' },
+  ];
+
+  let option = {
+    color: ['#dd4444', '#fec42c', '#80F1BE','#353EE9'],
+    legend: {
+      top: 10,
+      data: legends,
+      textStyle: {
+        fontSize: 16
+      }
+    },
+    grid: {
+      left: '10%',
+      right: 150,
+      top: '18%',
+      bottom: '10%'
+    },
+    tooltip: {
+      backgroundColor: 'rgba(255,255,255,0.7)',
+      formatter: function (param) {
+        var value = param.value;
+        // prettier-ignore
+        return '<div style="border-bottom: 1px solid rgba(255,255,255,.3); font-size: 18px;padding-bottom: 7px;margin-bottom: 7px">'
+            + value[0] + '</br> ' +  param.seriesName + ''
+            + '</div>'
+            + schema[1].text + ':' + value[1] + '人<br>'
+            + schema[2].text + ':' + value[2] + '笔<br>'
+      }
+    },
+    xAxis: {
+      type: 'category',
+      data: xAxis,
+    },
+    yAxis: {
+      type: 'value',
+      name: '数量',
+      nameLocation: 'end',
+      nameGap: 20,
+      nameTextStyle: {
+        fontSize: 16
+      },
+    },
+    visualMap: [
+      {
+        left: 'right',
+        top: '10%',
+        dimension: 1,
+        min: 0,
+        max: y1Max,
+        itemWidth: 30,
+        itemHeight: 120,
+        calculable: true,
+        precision: 0.1,
+        text: ['圆形大小:充电人次'],
+        textGap: 30,
+        inRange: {
+          symbolSize: [10, 70]
+        },
+        outOfRange: {
+          symbolSize: [10, 70],
+          color: ['rgba(255,255,255,0.4)']
+        },
+        controller: {
+          inRange: {
+            color: ['#c23531']
+          },
+          outOfRange: {
+            color: ['#999']
+          }
+        }
+      },
+      {
+        left: 'right',
+        bottom: '5%',
+        dimension: 2,
+        min: 0,
+        max: y2Max,
+        itemHeight: 120,
+        text: ['明暗:有效订单数'],
+        textGap: 30,
+        inRange: {
+          colorLightness: [0.9, 0.5]
+        },
+        outOfRange: {
+          color: ['rgba(255,255,255,0.4)']
+        },
+        controller: {
+          inRange: {
+            color: ['#c23531']
+          },
+          outOfRange: {
+            color: ['#999']
+          }
+        }
+      }
+    ],
+    series: series
+  };
+
+  console.log(option)
+  state.chartOne.setOption(option)
+}
+
+
+/**
+ * 充电量,柱状、折线图
+ */
+const buildElectricChart = () => {
+
+  if (state.chartThree) {
+    state.chartThree.dispose();
+  }
+  state.chartThree = markRaw(echarts.init(chartThreeRef.value, state.theme));
+  let {type} = state.formQuery
+  let stationIdList = Object.keys(state.chartData);
+  if (u.isEmptyOrNull(stationIdList)) {
+    Msg.message('未查询到统计数据', 'error')
+    return;
+  }
+  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => type==='day'?k.statDay:k.statMonth);
+  let legends:Array<string> =[];
+  state.stationList.filter((k: any) => stationIdList.includes(k.stationId)).forEach(item=>{
+    legends.push(item.stationName+'-总电量')
+    legends.push(item.stationName+'-平均充电电量')
+    legends.push(item.stationName+'-平均订单电量')
+  })
+
+  let y1Max = 0, y2Max = 0;
+  let series: Array<any> = [];
+  stationIdList.forEach((stationId: string) => {
+    let tmpUserMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.totalPower))
+    y1Max = Math.max(y1Max, tmpUserMax)
+
+    let tmpOrderMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => k.avgOrderElec))
+    y2Max = Math.max(y2Max, tmpOrderMax)
+
     let station = state.stationList.find((k: any) => k.stationId == stationId);
     let {stationName} = station;
     series.push({
-      name: stationName+'-充电人数',
+      name: stationName+'-总电量',
       type: 'bar',
+      barMaxWidth:20,
       symbolSize: 6,
       symbol: 'circle',
       smooth: true,
       itemStyle: { barBorderRadius: 5},
-      tooltip: {
-        trigger:'axis',
-        formatter: ' {a0}  {b}<br />{a} :  {c}个 '
-      },
-      data: state.chartData[stationId].map((k: any) => k.chargeUsers)
+      // tooltip: {
+      //   trigger:'axis',
+      //   formatter: ' {a0}  {b}<br />{a} :  {c}人 '
+      // },
+      data: state.chartData[stationId].map((k: any) => k.totalPower)
     })
 
 
     series.push({
-      name: stationName+'-订单数',
+      name: stationName+'-平均充电电量',
       type: 'line',
       smooth: true,
       yAxisIndex: 1,
-      tooltip: {
-        trigger:'item',
-        formatter: '{a0}    {b}<br />{a} :  {c}个 '
-      },
-      // tooltip: {
-      //   valueFormatter: function (value) {
-      //     console.log(value)
-      //     return value + ' 人';
-      //   }
-      // },
-      data: state.chartData[stationId].map((k: any) => k.validOrders)
+      data: state.chartData[stationId].map((k: any) => k.avgConnectorElec)
     })
 
+
+    series.push({
+      name: stationName+'-平均订单电量',
+      type: 'line',
+      smooth: true,
+      yAxisIndex: 1,
+      data: state.chartData[stationId].map((k: any) => k.avgOrderElec)
+    })
+
+
   });
 
-  y1Max = Math.max(y1Max, 100)
-  y2Max = Math.max(y2Max, 100)
+
+
+  y1Max = Math.max(y1Max, 80)
+  y2Max  =Math.ceil(y2Max +10)
 
   let y1Interval = Math.ceil(y1Max / 5)
   let y2Interval =  Math.ceil(y2Max / 5)
@@ -366,6 +498,7 @@ const buildOrderChart = () => {
 
   let option = {
     tooltip: {
+      show:true,
       trigger: 'axis',
       axisPointer: {
         type: 'cross',
@@ -383,14 +516,12 @@ const buildOrderChart = () => {
       }
     },
     legend: {
-      // data: ['Evaporation', 'Precipitation', 'Temperature']
       data: legends
     },
     xAxis: [
       {
         type: 'category',
         data: xAxis,
-        // data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
         axisPointer: {
           type: 'shadow'
         }
@@ -399,45 +530,171 @@ const buildOrderChart = () => {
     yAxis: [
       {
         type: 'value',
-        name: '人数',
+        name: '电量',
         min: 0,
         max: y1Max,
         interval: y1Interval,
         axisLabel: {
-          formatter: '{value} '
+          formatter: '{value} '
         }
       },
       {
         type: 'value',
-        name: '订单数',
+        name: '平均电量',
         min: 0,
         max: y2Max,
         interval: y2Interval,
         axisLabel: {
-          formatter: '{value} '
+          formatter: '{value} '
         }
       }
     ],
     series: series
   };
-  console.log(option)
-  state.chartOne.setOption(option)
-
-}
+  // console.log(option)
+  state.chartThree.setOption(option)
 
 
-/**
- * 充电量
- */
-const buildElectricChart = () => {
 
 }
 
 
 /**
- * 充电金额
+ * 充电金额  电费+服务费=总费用
  */
 const buildMoneyChart = () => {
+  if (state.chartTwo) {
+    state.chartTwo.dispose();
+  }
+  state.chartTwo = markRaw(echarts.init(chartTwoRef.value, state.theme));
+  let {type} = state.formQuery
+  let stationIdList = Object.keys(state.chartData);
+  if (u.isEmptyOrNull(stationIdList)) {
+    Msg.message('未查询到统计数据', 'error')
+    return;
+  }
+  let xAxis = state.chartData[`${stationIdList[0]}`].map((k: any) => type==='day'?k.statDay:k.statMonth);
+  let legends:Array<string> =[];
+  state.stationList.filter((k: any) => stationIdList.includes(k.stationId)).forEach(item=>{
+    legends.push(item.stationName+'-总费用')
+    legends.push(item.stationName+'-电费')
+    legends.push(item.stationName+'-服务费')
+  })
+
+  let y1Max = 0;
+  let series: Array<any> = [];
+  stationIdList.forEach((stationId: string) => {
+    let tmpUserMax = Math.max(...state.chartData[`${stationId}`].map((k: any) => Math.ceil((k.totalMoney/100))))
+    y1Max = Math.max(y1Max, tmpUserMax)
+
+    let station = state.stationList.find((k: any) => k.stationId == stationId);
+    let {stationName} = station;
+
+    series.push({
+      name: stationName+'-总费用',
+      type: 'bar',
+      barMaxWidth:20,
+      symbolSize: 10,
+      symbol: 'circle',
+      smooth: true,
+      itemStyle: { barBorderRadius: 5},
+      emphasis: {
+        focus: 'series'
+      },
+      tooltip: {
+        formatter: ' {a0}  {b}<br />{a} :  {c}元 '
+      },
+      markPoint: {
+        data: [
+          { type: 'max', name: 'Max' },
+          { type: 'min', name: 'Min' }
+        ]
+      },
+      markLine: {
+        data: [{ type: 'average', name: 'Avg' }]
+      },
+      data: state.chartData[stationId].map((k: any) => (k.totalMoney/100).toFixed(2))
+    })
+
+
+    series.push({
+      name: stationName+'-电费',
+      type: 'bar',
+      barMaxWidth:20,
+      smooth: true,
+      stack: 'Fee'+stationId,
+      markPoint: {
+        data: [
+          { type: 'max', name: 'Max' },
+          { type: 'min', name: 'Min' }
+        ]
+      },
+      data: state.chartData[stationId].map((k: any) =>  (k.elecMoney/100).toFixed(2))
+    })
+
+
+    series.push({
+      name: stationName+'-服务费',
+      type: 'bar',
+      barMaxWidth:20,
+      smooth: true,
+      stack:'Fee'+stationId,
+      markPoint: {
+        data: [
+          { type: 'max', name: 'Max' },
+          { type: 'min', name: 'Min' }
+        ]
+      },
+      data: state.chartData[stationId].map((k: any) => (k.serviceMoney/100).toFixed(2))
+    })
+
+  });
+
+  y1Max = Math.max(y1Max, 1000)+100
+
+  let y1Interval = Math.ceil(y1Max / 5)
+
+
+  let option = {
+    tooltip: {
+      show:true,
+      trigger: 'axis',
+      axisPointer: {
+        type: 'cross',
+        crossStyle: {
+          color: '#999'
+        }
+      }
+    },
+    legend: {
+      data: legends,
+      top:-5
+    },
+    xAxis: [
+      {
+        type: 'category',
+        data: xAxis,
+        axisPointer: {
+          type: 'shadow'
+        }
+      }
+    ],
+    yAxis: [
+      {
+        type: 'value',
+        name: '金额(元)',
+        min: 0,
+        max: y1Max,
+        interval: y1Interval,
+        axisLabel: {
+          formatter: '{value} '
+        }
+      },
+    ],
+    series: series
+  };
+  // console.log(option)
+  state.chartTwo.setOption(option)
 
 }