Sfoglia il codice sorgente

2023-02-16 update

1. agc曲线分析 增加数据导出功能
2. 温度与功率曲线分析  dialog中  增加额定功率, 位置放于subtext中
3. 对风偏差分析  下面两个图表 及其弹出层   Y轴分别加上name 为 频次   m/s
4. 风机绩效榜 功能已完成 光伏功率曲线分析 功能已完成
moccus 2 anni fa
parent
commit
aac35734e4

+ 1 - 1
src/components/Sidebar.vue

@@ -39,7 +39,7 @@
 </template>
 
 <script setup>
-import { computed, warn } from "vue";
+import { computed } from "vue";
 import { useRoute, useRouter } from "vue-router";
 import { useStore } from "vuex";
 const identity = sessionStorage.getItem("identity")

+ 41 - 6
src/pages/dataAnalysis/agcAnalysis/components/table.vue

@@ -1,4 +1,5 @@
 <script setup name="table">
+import {outExportExcel} from '@/utils/exportExcel.js'
 import {ref, computed} from 'vue'
 const props = defineProps({
   height: {
@@ -24,24 +25,58 @@ const props = defineProps({
   loading: {
     type: Boolean,
     default: false,
+  },
+  showSummary:{
+    type: Boolean,
+    default: false,
+  },
+  summaryMethod: {
+    type: Function,
+    default: () => () => {}
   }
 })
 const emits = defineEmits(['export'])
 const funExport = () => {
-  emits('export')
+  const columns = props.column.map(o => {
+    return {
+      ...o,
+      property: o.prop
+    }
+  })
+  let summary = []
+  const summaryObj = {}
+  const tHeader = []
+  const tHeaderKeys = []
+  const tableData = []
+  if(props.showSummary && props.summaryMethod){
+    summary = props.summaryMethod({columns,data: props.data})
+  }
+  for(const key in props.column){
+    tHeader.push(props.column[key].label)
+    tHeaderKeys.push(props.column[key].prop)
+    if(props.showSummary && props.summaryMethod){
+      summaryObj[props.column[key].prop] = summary[key] 
+    }
+  }
+  const exportName = props.tableName
+  tableData.push(...props.data)
+  if(props.showSummary && props.summaryMethod){
+    tableData.push(summaryObj)
+  }
+  outExportExcel(tHeader,tHeaderKeys,tableData,exportName)
 }
 const tableRef = ref('')
 const tableHeight =  computed(() => {
-  return tableRef.value.offsetHeight? tableRef.value.offsetHeight - 12 : 739
+  return tableRef.value.offsetHeight? tableRef.value.offsetHeight - 46 : 705
 })
 </script>
 <template>
   <div ref="tableRef" class="p-[10px]"
     :style="{ height: typeof props.height === 'string' ? props.height : props.height + 'px' }">
-    <!-- <div class="flex justify-between items-center pb-[10px]"> -->
-      <!-- <h3>{{props.tableName}}</h3> -->
-      <!-- <el-button size="small" type="primary" @click="funExport" :disabled="!props.tableId">数据导出</el-button> -->
-    <!-- </div> -->
+    <div class="flex justify-between items-center pb-[10px]">
+      <h3>{{props.tableName}}</h3>
+      <el-button size="small" type="primary" @click="funExport" :disabled="!props.tableId">数据导出</el-button>
+    </div>
     <el-table :data="props.data"
       stripe
       size="small" v-loading="props.loading"

+ 3 - 8
src/pages/dataAnalysis/agcAnalysis/index.vue

@@ -82,12 +82,6 @@ const tableName = ref('')
 const tableColumn = ref([])
 const tableLoading = ref(false)
 const tableData = ref([])
-const funExport = async () => {
-	const a = document.createElement('a')
-	a.href = baseURL + '/power/prepare/download?id=' + tableShowId.value
-	a.download = ''
-	a.click()
-}
 /**tab  */
 const activeTab = ref('1')
 /**chart Data */
@@ -101,8 +95,8 @@ const funChartSelect = async (batch) => {
 /**submit */
 const funSubmit = async (params) => {
 	activeTab.value = '2'
-	tableShowId.value = 1
-	tableName.value = ''
+	tableShowId.value = ''
+	tableName.value = 'AGC曲线分析'
 	tableLoading.value = true
 	const res = await request.get('/agc/deviate', { params: params })
 	tableColumn.value = [
@@ -225,6 +219,7 @@ const funSubmit = async (params) => {
 	]
 	tableData.value = tableArr
 	tableLoading.value = false
+	tableShowId.value = '1'
 
 	
 	// if (res.code === 200) {

+ 2 - 0
src/pages/dataAnalysis/rateAnalysis/index.vue

@@ -290,6 +290,7 @@ const lineyAxis = ref([
 	}
 	},{
 		type: 'value',
+		name: '频次',
 		splitLine: {
 		show: false
 	},
@@ -374,6 +375,7 @@ const scatteryData = ref([
 		axisLine: {
 			show: false
 		},
+		name: 'm/s',
 		splitLine: {
 			show: false
 		},

+ 2 - 2
src/pages/dataAnalysis/tempAnalysis/index.vue

@@ -415,7 +415,7 @@ const funDiaSubmit = async () => {
 							isBrush: false,
 							actCop: shallowRef(barChartCop),
 							title: chart.wt,
-							subtext: '平均功率-额定功率',
+							subtext: `平均功率-额定功率(额定功率=${chart.power.powerproduction}kW)`,
 							xAxis: {
 								...barxAxis,
 								data: Object.keys(chart.res1)
@@ -447,7 +447,7 @@ const funDiaSubmit = async () => {
 							isBrush: false,
 							actCop: shallowRef(lineChartCop),
 							title: chart.wt,
-							subtext: '额定功率温度分析',
+							subtext: `额定功率温度分析(额定功率=${chart.power.powerproduction}kW)`,
 							xAxis: linexAxis,
 							yAxis: lineyAxis,
 							dataset: lineDataSet,

+ 363 - 0
src/pages/dataAnalysis/windAnalysis/components/barLineChart.vue

@@ -0,0 +1,363 @@
+<template>
+  <div class="chart" :id="id"></div>
+</template>
+
+<script>
+import util from "@/helper/util.js";
+import partten from "@/helper/partten.js";
+import * as echarts from "echarts";
+
+export default {
+  name: "multiple-bar-chart",
+  componentName: "multiple-bar-chart",
+  props: {
+    width: {
+      type: String,
+      default: "100%",
+    },
+    height: {
+      type: String,
+      default: "800px",
+    },
+    // 传入数据
+    bardata: {
+      type: Object,
+      default: () => {
+        return {
+          area: [
+            "风场1",
+            "风场2",
+            "风场3",
+            "风场4",
+            "风场5",
+            "风场6",
+            "风场7",
+            "风场8",
+            "风场9",
+          ],
+          legend: [
+            "实际电量",
+            "计划检修损失",
+            "非计划检修损失",
+            "限电损失",
+            "受累损失",
+            "性能损失",
+          ],
+          data: [
+            [1320, 1302, 901, 634, 1390, 1330, 1320, 1000, 500],
+            [320, 302, 301, 334, 390, 330, 320, 100, 50],
+            [320, 302, 301, 334, 390, 330, 320, 100, 50],
+            [1320, 1302, 901, 634, 1390, 1330, 1320, 1000, 500],
+            [320, 302, 301, 334, 390, 330, 320, 100, 50],
+            [320, 302, 301, 334, 390, 330, 320, 100, 50],
+            [1320, 1302, 901, 634, 1390, 1330, 1320, 1000, 500],
+            [320, 302, 301, 334, 390, 330, 320, 100, 50],
+          ],
+        };
+      },
+    },
+    lineData: {
+      type: Array,
+      default: () => [200, 350, 400, 500, 600, 700, 800, 900, 1200],
+    },
+    lineName: {
+      type: String,
+      default: "损失电量",
+    },
+    // 单位
+    units: {
+      type: Array,
+      default: () => ["(万KWh)", "(风速)"],
+    },
+    // 显示 legend
+    showLegend: {
+      type: Boolean,
+      default: true,
+    },
+    // 颜色
+    color: {
+      type: Array,
+      default: () => ["#323E6F", "#e17e23", "#ba3237", "#c531c7", "#ffffff", "#EDEB2F"],
+    },
+    // 每页显示个数
+    pageSize: {
+      type: Number,
+      default: 20,
+    },
+  },
+  data() {
+    return {
+      id: "",
+      chart: null,
+			themeName: 'light',
+      areaData: [],
+    };
+  },
+  computed: {
+    legend() {
+      return this.bardata.legend;
+    },
+    end() {
+      var result = 20;
+      if (this.areaData) {
+        result = parseInt((this.pageSize / this.areaData.length) * 100);
+      }
+      return result;
+    },
+  },
+  methods: {
+    initChart() {
+      let chart = echarts.init(this.$el);
+      let option = {
+        color: this.color,
+        grid: {
+          left: 40,
+          right: 40,
+          bottom: 16,
+          top: 16,
+          containLabel: true,
+        },
+        legend: {
+          show: this.showLegend,
+          data: this.bardata.legend,
+          right: 56,
+          icon: "ract",
+          itemWidth: 8,
+          itemHeight: 8,
+          inactiveColor: this.themeName === "dark"
+              ? partten.getColor("gray")
+              : "#838383",
+          textStyle: {
+            color: this.themeName === "dark"
+              ? partten.getColor("grayl")
+              : "#838383",
+            fontSize: 12,
+          },
+        },
+        tooltip: {
+          trigger: "axis",
+          backgroundColor: this.themeName === "dark"
+              ? "rgba(0,0,0,0.4)"
+              : "rgba(255,255,255,0.5)",
+          borderColor: this.themeName === "dark"
+              ? partten.getColor("gray")
+              : "#838383",
+          textStyle: {
+            color: this.themeName === "dark" ? "#fff" : "#838383",
+            fontSize: util.vh(16),
+          },
+        },
+        dataZoom: [
+          {
+            type: "inside",
+            start: 0,
+            end: this.end,
+            yAxisIndex: [0],
+          },
+          {
+            start: 0,
+            end: this.end,
+						top: 20,
+            bottom: 40,
+            yAxisIndex: [0],
+            backgroundColor: "transparent",
+            // handleIcon: "path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z",
+            handleStyle: {
+              color: this.themeName === "dark"
+              ? partten.getColor("green")
+              : partten.getColor("blue"),
+            },
+            moveHandleSize: 0,
+            // dataBackground: {
+            //   lineStyle: {
+            //     color: partten.getColor("gray"),
+            //   },
+            //   areaStyle: {
+            //     color: partten.getColor("gray"),
+            //   },
+            // },
+            // selectedDataBackground: {
+            //   lineStyle: {
+            //     color: partten.getColor("yellow"),
+            //   },
+            //   areaStyle: {
+            //     color: partten.getColor("yellow"),
+            //   },
+            // },
+            fillerColor: "transparent",
+            textStyle: {
+              color: this.themeName === "dark"
+              ? partten.getColor("grayl")
+              : "#838383",
+            },
+            borderColor: this.themeName === "dark"
+              ? partten.getColor("gray")
+              : "#838383",
+            brushSelect: false,
+          },
+        ],
+        yAxis: [
+          {
+            type: "category",
+            axisLabel: {
+              color: this.themeName === "dark"
+              ? partten.getColor("gray")
+              : "#838383",
+            },
+            inverse: true,
+            // minInterval: 10,
+            // maxInterval: 10,
+            axisLine: {
+              show: false,
+            },
+            axisTick: {
+              show: false,
+            },
+            data: this.areaData,
+          },
+        ],
+        xAxis: [
+          {
+            type: "value",
+						name: '万kWh',
+            axisLabel: {
+              color: this.themeName === "dark"
+              ? partten.getColor("gray")
+              : "#838383",
+							// formatter: "{value}万kWh",
+            },
+            axisLine: {
+              type: "dashed",
+              lineStyle: {
+                color: this.themeName === "dark"
+              ? partten.getColor("gray")
+              : "#838383",
+              },
+              width: 5,
+            },
+            axisTick: {
+              show: false,
+            },
+            splitLine: {
+              lineStyle: {
+                type: "dashed",
+                dashOffset: 10,
+                color: this.themeName === "dark" ? "#5a6162" : "#838383" + 80,
+              },
+            },
+          },
+          {
+            type: "value",
+            name: "",
+            axisLabel: {
+              show: false,
+              // formatter: "{value}万kWh",
+              // color: partten.getColor("gray"),
+            },
+            axisLine: {
+              show: false,
+            },
+            axisTick: {
+              show: false,
+            },
+            splitLine: {
+              show: false,
+            },
+          },
+        ],
+        series: [],
+      };
+
+      if (this.bardata && this.bardata.legend)
+        // bar data
+        for (var i = 0; i < this.bardata.legend.length; i++) {
+          option.series.push({
+            name: this.bardata.legend[i],
+            type: "bar",
+            stack: "总量",
+            barWidth: 16,
+            label: {
+              show: false,
+              position: "insideRight",
+            },
+            data: this.bardata.data[i],
+          });
+        }
+
+      // line data
+      if (this.lineData.length > 0) {
+        option.series.push({
+          name: this.lineName,
+          type: "line",
+          data: this.lineData,
+          smooth: false, //平滑展示
+          xAxisIndex: 1,
+          lineStyle: {
+            color: this.themeName === "dark"
+              ? partten.getColor("green")
+              : partten.getColor("blue"),
+          },
+          itemStyle: {
+            color: this.themeName === "dark"
+              ? partten.getColor("green")
+              : partten.getColor("blue"),
+          },
+        });
+      }
+      chart.setOption(option);
+    },
+  },
+  created() {
+    this.id = "pie-chart-" + util.newGUID();
+    if (this.bardata.area && this.bardata.area.length < this.pageSize) {
+      this.areaData = this.bardata.area;
+      for (let i = this.bardata.area.length; i <= this.pageSize; i++) {
+        this.areaData.push("");
+      }
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.$el.style.width = this.width;
+      this.$el.style.height = this.height;
+      this.initChart();
+    });
+  },
+  updated() {
+    this.$nextTick(() => {
+      this.initChart();
+    });
+  },
+  beforeUpdate(){
+	  this.areaData = this.bardata.area;
+  },
+  beforeUpdate(){
+  	  this.areaData = this.bardata.area;
+  },
+	activated(){
+		this.$nextTick(() => {
+      this.$el.style.width = this.width;
+      this.$el.style.height = this.height;
+      this.initChart();
+    });
+	},
+  watch: {
+    bardata(val) {
+      if (val.area && val.area.length < this.pageSize) {
+        this.areaData = val.area;
+        for (let i = val.area.length; i <= this.pageSize; i++) {
+          this.areaData.push("");
+        }
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+.chart {
+  width: 100%;
+  height: 100%;
+  display: inline-block;
+}
+</style>

+ 17 - 47
src/pages/dataAnalysis/windAnalysis/components/search.vue

@@ -7,7 +7,7 @@ const queryForm = reactive({
 	station: '',
 	lineIds: [],
 	wtIds: [],
-	type: '',
+	type: '1',
 	st: Date.now() - 30 * 24 * 60 * 60 * 1000,
 	et: Date.now(),
 })
@@ -16,10 +16,6 @@ const stationList = ref([])
 const funGetStation = async () => {
 	const res = await request.get("/base/station")
 	stationList.value = res.data
-	if (stationList.value.length) {
-		queryForm.station = stationList.value[0].id
-		funGetWind(queryForm.station)
-	}
 }
 const funStationChange = (stationId) => {
 	if (stationId) {
@@ -28,18 +24,14 @@ const funStationChange = (stationId) => {
 		queryForm.wtIds = []
 		windList.value = []
 	}
+	funSubmit()
 }
 /**项目 */
-const checkAll = ref(true)
 const windList = ref([])
 const funGetWind = async (stationId) => {
 	const res = await request.get("/base/project", {params: { stationId }})
 	windList.value = res.data
-	queryForm.wtIds = res.data.map(o => o.id)
-	checkAll.value = true
-	if (windList.value.length) {
-		funGetLine(queryForm.wtIds)
-	}
+	queryForm.wtIds = []
 }
 const funWindChange = (windArr) => {
 	if (windArr?.length) {
@@ -48,50 +40,29 @@ const funWindChange = (windArr) => {
 		queryForm.lineIds = []
 		lineList.value = []
 	}
-}
-const funCheckAll = () => {
-	checkAll.value = !checkAll.value
-	if(checkAll.value){
-		queryForm.wtIds = windList.value.map(o => o.id)
-	}else{
-		queryForm.wtIds = []
-	}
+	funSubmit()
 }
 /**期次 */
-const checkLineAll = ref(true)
 const lineList = ref([])
 const funGetLine = async (wtIds) => {
 	const res = await request.get("/base/line", {params: { projectId: wtIds.join() }})
 	lineList.value = res.data
-	queryForm.lineIds = res.data.map(o => o.id)
-	checkLineAll.value = true
-}
-const funCheckLineAll = () => {
-	checkLineAll.value = !checkLineAll.value
-	if(checkLineAll.value){
-		queryForm.lineIds = lineList.value.map(o => o.id)
-	}else{
-		queryForm.lineIds = []
-	}
+	queryForm.lineIds = []
 }
 /**导出 */
 const emits = defineEmits(['submit'])
 const funSubmit = async () => {
-	const startDate = new Date(queryForm.st).setHours(0,0,0,0)
-	const endDate = new Date(queryForm.et).setHours(0,0,0,0)
 	const query = {
 		station: queryForm.station,
 		line: queryForm.lineIds.join(),
 		project: queryForm.wtIds.join(),
 		type: '',
-		st: new Date(startDate).getTime(),
-		et: new Date(endDate).getTime(),
+		st: new Date(queryForm.st).formatDate('yyyy-MM-dd'),
+		et: new Date(queryForm.et).formatDate('yyyy-MM-dd'),
 	}
 	emits('submit', query)
 }
 const funType = (type) => {
-	const startDate = new Date(queryForm.st).setHours(0,0,0,0)
-	const endDate = new Date(queryForm.et).setHours(0,0,0,0)
 	queryForm.type = type
 	queryForm.station = ''
 	queryForm.lineIds = []
@@ -101,13 +72,14 @@ const funType = (type) => {
 		line: queryForm.lineIds.join(),
 		project: queryForm.wtIds.join(),
 		type: queryForm.type,
-		st: new Date(startDate).getTime(),
-		et: new Date(endDate).getTime(),
+		st: new Date(queryForm.st).formatDate('yyyy-MM-dd'),
+		et: new Date(queryForm.et).formatDate('yyyy-MM-dd'),
 	}
 	emits('submit',query)
 }
 /**created */
 funGetStation()
+funType('1')
 </script>
 <template>
 	<div class="pl-[20px] flex items-center h-[80px] relative">
@@ -119,30 +91,28 @@ funGetStation()
 				</el-select>
 			</el-form-item>
 			<el-form-item label="期次" class="!mb-0">
-				<el-select multiple class="w-[150px]" clearable v-model="queryForm.wtIds" @change="funWindChange"  @clear="checkAll = false" collapse-tags>
-					<el-option label="全选" :class="{'selected': checkAll}" @click="funCheckAll"></el-option>
+				<el-select multiple class="w-[150px]" clearable v-model="queryForm.wtIds" @change="funWindChange" collapse-tags>
 					<el-option v-for="item in windList" :key="item.id" :label="item.name" :value="item.id"></el-option>
 				</el-select>
 			</el-form-item>
 			<el-form-item label="线路" class="!mb-0">
-				<el-select multiple class="w-[150px]" clearable v-model="queryForm.lineIds" @clear="checkLineAll = false" collapse-tags>
-					<el-option label="全选" :class="{'selected': checkLineAll}" @click="funCheckLineAll"></el-option>
+				<el-select multiple class="w-[150px]" clearable v-model="queryForm.lineIds" @change="funSubmit" collapse-tags>
 					<el-option v-for="item in lineList" :key="item.id" :label="item.name" :value="item.id"></el-option>
 				</el-select>
 			</el-form-item>
 			<el-form-item label="开始时间" class="!mb-0">
-				<el-date-picker type="date" class="!w-[150px]" v-model="queryForm.st"></el-date-picker>
+				<el-date-picker type="date" class="!w-[150px]" v-model="queryForm.st" @change="funSubmit" ></el-date-picker>
 			</el-form-item>
 			<el-form-item label="结束时间" class="!mb-0">
-				<el-date-picker type="date" class="!w-[150px]" v-model="queryForm.et"></el-date-picker>
+				<el-date-picker type="date" class="!w-[150px]" v-model="queryForm.et" @change="funSubmit" ></el-date-picker>
 			</el-form-item>
 			<el-form-item class="!mb-0">
 				<submit-btn v-prevdbclick:5000="funSubmit" desc="执行"></submit-btn>
 			</el-form-item>
 			<el-form-item class="!mb-0">
-				<submit-btn @click="funType('1')" :type="queryForm.type==='1'? 'primary': 'default'" desc="风场"></submit-btn>
-				<submit-btn @click="funType('2')" :type="queryForm.type==='2'? 'primary': 'default'" desc="期次"></submit-btn>
-				<submit-btn @click="funType('3')" :type="queryForm.type==='3'? 'primary': 'default'" desc="集电线路"></submit-btn>
+				<submit-btn @click="funType('1')" :type="queryForm.type==='1'? 'success': 'default'" desc="风场"></submit-btn>
+				<submit-btn @click="funType('2')" :type="queryForm.type==='2'? 'success': 'default'" desc="期次"></submit-btn>
+				<submit-btn @click="funType('3')" :type="queryForm.type==='3'? 'success': 'default'" desc="集电线路"></submit-btn>
 			</el-form-item>
 		</el-form>
 	</div>

+ 39 - 2
src/pages/dataAnalysis/windAnalysis/components/table.vue

@@ -1,4 +1,5 @@
 <script setup name="table">
+import {outExportExcel} from '@/utils/exportExcel.js'
 import {ref, computed} from 'vue'
 const props = defineProps({
   height: {
@@ -24,11 +25,45 @@ const props = defineProps({
   loading: {
     type: Boolean,
     default: false,
+  },
+  showSummary:{
+    type: Boolean,
+    default: false,
+  },
+  summaryMethod: {
+    type: Function,
+    default: () => () => {}
   }
 })
 const emits = defineEmits(['export'])
 const funExport = () => {
-  emits('export')
+  const columns = props.column.map(o => {
+    return {
+      ...o,
+      property: o.prop
+    }
+  })
+  let summary = []
+  const summaryObj = {}
+  const tHeader = []
+  const tHeaderKeys = []
+  const tableData = []
+  if(props.showSummary && props.summaryMethod){
+    summary = props.summaryMethod({columns,data: props.data})
+  }
+  for(const key in props.column){
+    tHeader.push(props.column[key].label)
+    tHeaderKeys.push(props.column[key].prop)
+    if(props.showSummary && props.summaryMethod){
+      summaryObj[props.column[key].prop] = summary[key] 
+    }
+  }
+  const exportName = props.tableName
+  tableData.push(...props.data)
+  if(props.showSummary && props.summaryMethod){
+    tableData.push(summaryObj)
+  }
+  outExportExcel(tHeader,tHeaderKeys,tableData,exportName)
 }
 const tableRef = ref('')
 const tableHeight =  computed(() => {
@@ -40,10 +75,12 @@ const tableHeight =  computed(() => {
     :style="{ height: typeof props.height === 'string' ? props.height : props.height + 'px' }">
     <div class="flex justify-between items-center pb-[10px]">
       <h3>{{props.tableName}}</h3>
-      <!-- <el-button size="small" type="primary" @click="funExport" :disabled="!props.tableId">数据导出</el-button> -->
+      <el-button size="small" type="primary" @click="funExport" :disabled="!props.tableId">数据导出</el-button>
     </div>
     <el-table :data="props.data"
       stripe
+      :show-summary="showSummary"
+      :summary-method="summaryMethod"
       size="small" v-loading="props.loading"
       :max-height="tableHeight"
       :style="{ width: '100%'}">

+ 136 - 124
src/pages/dataAnalysis/windAnalysis/index.vue

@@ -1,8 +1,7 @@
 <script setup name="prepare">
 import searchCop from './components/search.vue'
-import excelCop from '@/components/excel.vue'
-import treeCop from '@/components/tree.vue'
 import tableCop from './components/table.vue'
+import barLineChartCop from './components/barLineChart.vue'
 import { ElMessage } from 'element-plus';
 import { onMounted, ref, onActivated } from 'vue'
 import request from '@/api/axios.js'
@@ -11,124 +10,59 @@ import {baseURL, socketURL} from '@/api/axios.js'
 const treeHeight = ref(window.innerHeight - 260 + 'px') //tree高度
 const excelHeight = ref(window.innerHeight - 260 + 'px') //excel高度
 const tableHeight = ref(window.innerHeight - 260 + 'px')
-/**excel 开始 */
-const excelList = ref([])
-const funExcelChange = async (obj) => { //点击excel项时
-	tableShowId.value = obj.id
-	tableName.value = obj.name
-	tableLoading.value = true
-	const res = await request.get('/power/prepare/show', { params: { id: obj.id } })
-	if(res.code === 200){
-		tableColumn.value = res.data.title.map(o => {
-			return {
-				prop: o.key,
-				label: o.des,
-				width: o.des==='时间'? 100: 80,
-			}
-		})
-		tableData.value = res.data.data
-		tableLoading.value = false
-	}else{
-		tableLoading.value = false
-	}
-}
-/**tree 开始 */
-const treeData = ref([])
-const actTreeNode = ref(null) //当前激活的treeNode
-const funRepeatMap = (arr) => {
-	return arr.map(o => {
-		if (o.children) {
-			const findIndex = o.children.findIndex(p => !!p.type)
-			if (findIndex !== -1) {
-				o.childs = o.children
-				o.children = []
-				if(!actTreeNode.value){ //判断当且仅有process获取tree时 赋值
-					actTreeNode.value = o
-				}
-			}
-		}
-		return {
-			...o,
-			children: o.children?.length ? funRepeatMap(o.children) : []
-		}
-	})
-}
-const funGetTree = async () => {
-	actTreeNode.value = null
-	const res = await request.get("/power/prepare/tree")
-	treeData.value = funRepeatMap(res.data)
-	excelList.value = []
-	if(actTreeNode.value){
-		funCurrentChange({current: actTreeNode.value, currentNode: null})
-		const child = actTreeNode.value.childs[0]
-		const obj = {
-			id: child.id,
-			interval: child.interval,
-			path: child.path,
-			prepareid: child.prepareid,
-			station: child.station,
-			time: child.time,
-			type: child.type,
-			windturbine: child.windturbine,
-			name: child.path.substring(child.path.indexOf(child.station + '_') + (child.station + '_').length)
-		}
-		funExcelChange(obj)
-	}
-}
-const funCurrentChange = ({ current, currentNode }) => {
-	if (current.childs) {
-		excelList.value = current.childs.map(o => {
-			return {
-				id: o.id,
-				interval: o.interval,
-				path: o.path,
-				prepareid: o.prepareid,
-				station: o.station,
-				time: o.time,
-				type: o.type,
-				windturbine: o.windturbine,
-				name: o.path.substring(o.path.indexOf(o.station + '_') + (o.station + '_').length)
-			}
-		})
-	} else {
-		excelList.value = []
-	}
-}
 /**table 开始 */
 const tableShowId = ref('')
-const tableName = ref('')
+const tableName = ref('风机绩效榜')
 const tableColumn = ref([])
 const tableLoading = ref(false)
 const tableData = ref([])
-const funExport = async () => {
-	const a = document.createElement('a')
-	a.href = baseURL + '/power/prepare/download?id=' + tableShowId.value
-	a.download = ''
-	a.click()
-}
-/**submit */
-/**const progress = ref(0)
-const funWebSocket = () => {
-	const webSocket = new WebSocket(`${socketURL}/ws/powerfitting/admin`)
-	webSocket.onerror = () => setTimeout(() => { funWebSocket() }, 2000)
-
-	webSocket.onmessage = (event) => {
-		const message = JSON.parse(event.data)
-		if (message.code === 200) {
-			progress.value = Number(message.data) * 100
-			if (progress.value === 100) {
-				ElMessage.success('数据加载完成')
-				funGetTree()
-				progress.value = 0
+const funSummary = ({columns,data}) => {
+	const sums = []
+	columns.forEach((column, index) => {
+    if (index === 0) {
+      sums[index] = '合计'
+      return
+    }
+    const values = data.map((item) => Number(item[column.property]))
+    if (!values.every((value) => Number.isNaN(value))) {
+      sums[index] = values.reduce((prev, curr) => {
+        const value = Number(curr)
+        if (!Number.isNaN(value)) {
+          return Number((prev + curr).toFixed(2))
+        } else {
+          return Number(prev.toFixed(2))
+        }
+      }, 0)
+    } else {
+      sums[index] = '--'
+    }
+		if(['speed','fnlly'].includes(column.property)){
+			if(!Number.isNaN(sums[index])){
+				sums[index] = Number((sums[index] / data.length).toFixed(2))
 			}
 		}
-	}
+  })
+
+  return sums
 }
-*/
 const funSubmit = async (params) => {
 	tableLoading.value = true
 	tableData.value = []
-	const res = await request.get('/fjjxb/index', { params: params })
+	tableShowId.value = ''
+	barData.value = {
+		area: [],
+		legend: [],
+		data: [],
+	}
+	lineData.value = []
+	const res = await request.get('/fjjxb/index', { params: {
+		station: params.station,
+		line: params.line,
+		project: params.project,
+		type: params.type,
+		st: params.st,
+		et: params.et,
+	} })
 	if (res.code !== 200) { tableLoading.value = false; return false}
 	ElMessage.success(res.msg)
 	tableColumn.value = res.data.title.map(o => {
@@ -136,14 +70,98 @@ const funSubmit = async (params) => {
 			prop: o.key,
 			label: o.des,
 			width: o.des==='时间'? 100: 80,
+			
 		}
 	})
 	tableData.value = res.data.data
+
+	const name = [],
+			data = [],
+			llfdl = [],
+			legend = [
+				"实际电量",
+				"计划检修损失",
+				"非计划检修损失",
+				"限电损失",
+				"受累损失",
+				"性能损失",
+			],
+			data2 = []; //项目列表
+		if (params.station) {
+			let arr = [];
+			let hj = res.data.data.pop();
+			res.data.data.forEach((ele, index) => {
+				arr[ele.id.split('_')[1] - 1] = ele
+			})
+			arr.push(hj);
+			res.data.data = arr;
+		}
+
+		res.data.data.forEach((item, index) => {
+			name.push(item.name);
+			data.push([
+				item.sjfdl,
+				item.jhjx,
+				item.fjhjx,
+				item.xd,
+				item.sl,
+				item.xn,
+			]);
+			llfdl.push(item.llfdl);
+			data2.push({
+				index: index + 1,
+				name: item.name,
+				llfdl: item.llfdl,
+				sjfdl: item.sjfdl,
+				speed: item.speed,
+				fjhjx: item.fjhjx,
+				jhjx: item.jhjx,
+				sl: item.sl,
+				xd: item.xd,
+				xn: item.xn,
+				fnlly: item.fnlly,
+				is_light: false,
+			});
+		});
+		if (data.length > 0) {
+			let arr1 = [];
+			const length = data[0].length;
+			for (var i = 0; i < length; i++) {
+				let arr2 = [];
+				data.forEach((ele) => {
+					arr2.push(ele[i]);
+				});
+				arr1.push(arr2);
+			}
+			lineData.value = llfdl;
+			barData.value = {
+				area: name,
+				legend: legend,
+				data: arr1,
+			};
+		}
+
+
 	tableLoading.value = false
+	tableShowId.value = '1'
 }
+/**barlineChart 开始 */
+const barData = ref({
+	area: [],
+	legend: [],
+	data: [],
+})
+const lineData = ref([])
+const barColor = [
+	"#4b55ae",
+	"#e17e23",
+	"#ba3237",
+	"#c531c7",
+	"#ffffff",
+	"#05bb4c",
+]
+
 /**created */
-// funGetTree()
-// funWebSocket()
 /**mounted */
 onMounted(() => {
 	tableHeight.value = window.innerHeight - 260 + 'px'
@@ -157,7 +175,6 @@ onMounted(() => {
 })
 /**activated */
 onActivated(() => {
-	funGetTree()
 })
 </script>
 <template>
@@ -167,23 +184,18 @@ onActivated(() => {
 		<div class="relative shadow rounded-[6px] shadow-blue-500 px-[10px] pt-[20px] pb-[10px]">
 			<div class="text-[14px] absolute top-[-7px] text-[#838383] left-[20px]">数据展示</div>
 			<el-row :gutter="10">
-				<el-col :span="5">
-					<tree-cop :data="treeData" :height="treeHeight" @currentChange="funCurrentChange" @refresh="funGetTree">
-					</tree-cop>
+				<el-col :span="10" class="shadow rounded-[6px] shadow-blue-500">
+				<bar-line-chart-cop v-if="lineData.length" :height="tableHeight" :bardata="barData" :lineData="lineData"
+						:color="barColor" lineName="理论发电量"></bar-line-chart-cop>
+				<el-empty v-else description="请选择条件"></el-empty>
 				</el-col>
-				<el-col :span="3">
-					<excel-cop :data="excelList" :height="excelHeight" @excelChange="funExcelChange"></excel-cop>
-				</el-col>
-				<el-col :span="16">
+				<el-col :span="14">
 					<div>
-						<table-cop class="" :data="tableData" :column="tableColumn" :loading="tableLoading" :height="tableHeight"
-							:tableId="tableShowId" :tableName="tableName" @export="funExport"></table-cop>
+						<table-cop class="" :data="tableData" :showSummary="true" :summaryMethod="funSummary" :column="tableColumn" :loading="tableLoading" :height="tableHeight"
+							:tableId="tableShowId" :tableName="tableName"></table-cop>
 					</div>
 				</el-col>
 			</el-row>
 		</div>
-
-		<el-progress :percentage="progress" v-if="progress" class="!absolute top-0 right-0 left-0" :indeterminate="false"
-			color="rgb(19,206,102)" :stroke-width="4" :show-text="false" />
 	</div>
 </template>

+ 16 - 5
src/pages/lightAnalysis/glAnalysis/index.vue

@@ -16,11 +16,18 @@ const excelHeight = ref(window.innerHeight - 160 + 'px') //excel高度
 /**excel 开始 */
 const excelList = ref([])
 const excelCheckIds = ref([])
+const excelCheckData = ref([]) //选中后的所有对象数组
 const funExcelChange = async (obj) => { //点击excel项时
 	return false
 }
 const funExcelCheckChange = ({ checkArr, data }) => {   //bug 
-	excelCheckIds.value = checkArr
+	if(!checkArr.length){
+		excelCheckIds.value = []
+		excelCheckData.value = []
+	}else{
+		excelCheckIds.value = checkArr
+		excelCheckData.value = data.filter(o => checkArr.includes(o.id))
+	}
 	funSubmit() // check 后进行操作
 }
 /**tree 开始 */
@@ -47,6 +54,7 @@ const funRepeatMap = (arr) => {
 const funGetTree = async () => {
 	actTreeNode.value = null
 	excelCheckIds.value = []
+	excelCheckData.value = []
 	const res = await request.get("/allfilelist")
 	treeData.value = funRepeatMap(res.data)
 	excelList.value = []
@@ -55,6 +63,8 @@ const funGetTree = async () => {
 	}
 }
 const funCurrentChange = ({ current, currentNode }) => {
+	excelCheckIds.value = []
+	excelCheckData.value = []
 	if (current.childs) {
 		excelList.value = current.childs.map(o => {
 			return {
@@ -96,13 +106,12 @@ const funChartSelect = async (batch) => {
 }
 /**submit */
 const funSubmit = async () => {
-	activeTab.value = '1'
 	if (!excelCheckIds.value.length) {
 		ElMessage.error('请勾选要执行的项')
 		return false
 	}
 	const params = {
-		filelist: excelCheckIds.value.join(',')
+		filelist: excelCheckIds.value.join()
 	}
 	tableShowId.value = '1'
 	tableName.value = params.filelist
@@ -119,13 +128,14 @@ const funSubmit = async () => {
 				width: o.des==='时间'? 100: 80,
 			}
 		})
-		const wtIds = excelCheckIds.value
+		const wtIds = excelCheckData.value.map(o => o.windturbine)
 		const xAxis = []
 		const series = []
 		if(!res.data.data || !wtIds.length){ tableLoading.value = false; return false}
 		for(const index in wtIds){
 			const llgl = []
 			const sjgl = []
+			console.log(wtIds[index],res.data.data[wtIds[index]])
 			for(const o of res.data.data[wtIds[index]]){
 				if(index === '0'){
 					xAxis.push(o.datetime)
@@ -160,6 +170,7 @@ const funSubmit = async () => {
 		xAxisData.value = xAxis
 		seriesData.value = series
 		tableLoading.value = false
+		activeTab.value = '2'
 }
 /**created */
 // funGetTree()
@@ -192,7 +203,7 @@ onActivated(() => {
 					</tree-cop>
 				</el-col>
 				<el-col :span="4">
-					<excel-cop :data="excelList" :height="excelHeight" showCheckbox @excelChange="funExcelChange" @checkChange="funExcelCheckChange"></excel-cop>
+					<excel-cop :data="excelList" :checkIds="excelCheckIds" :height="excelHeight" showCheckbox @excelChange="funExcelChange" @checkChange="funExcelCheckChange"></excel-cop>
 				</el-col>
 				<el-col :span="16">
 					<div class="px-[10px] shadow rounded-[6px] shadow-blue-500 ">