项目看板开发经验分享(三)——电子车间能源监控看板(渐变色环形进度条、按钮控制展示折线图项、看板表格设计与单击双击事件)

news2024/11/15 4:55:34

系列完结篇,直奔主题

在这里插入图片描述

电子车间能源监控看板展示视频


1、渐变色环形进度条

在这里插入图片描述
在进度条下方直接加svg实现,中间的字体则先隐藏环形进度条默认的文字:show-text="false",再用绝对定位来写进去

                  <div class="ball_bg">
                    <el-progress type="circle" :width="100" :stroke-width="8" :show-text="false" :percentage="loadRate" class="progress"></el-progress>
                    <svg width="100%" height="100%">
                      <defs>
                        <linearGradient id="blue" x1="0%" y1="0%" x2="100%" y2="0%">
                          <stop offset="0%" style="stop-color:rgba(0, 126, 250, 1)" stop-opacity="1" />
                          <stop offset="100%" style="stop-color:rgba(4, 205, 230, 1)" stop-opacity="1" />
                        </linearGradient>
                      </defs>
                    </svg>
                    <div class="value_box">
                      <div class="value">
                        <span>{{ loadRate }}</span>%
                      </div>
                      <div>负荷率</div>
                    </div>
                  </div>

2、折线图表与按钮控制展示项与flex布局

在这里插入图片描述

折线图和flex布局这个在系列第二期讲过,就不多赘述。

主要来讲解用按钮来控制折线图显示哪一项的折线,原理是给按钮组赋值一个数组,激活的按钮就给数组push它的name,然后绘制图表时,使用includes来判断某一项是否展示,若展示,则给图表的seriespush添加该项的配置内容。

HTML:

<div class="line_monitor">
            <groupPlate :title="`${singleMeterName}能耗监控`">
              <div class="content">
                <div class="dimension_box">
                  <div :class="groudDimension.includes('usageAmount')? 'active btn': 'btn'" @click="Setsigledimension('usageAmount', 'groud')">能耗</div>
                  <div :class="groudDimension.includes('output') ? 'active btn' : 'btn'" @click="Setsigledimension('output', 'groud')">产量</div>
                  <div :class="groudDimension.includes('single') ? 'active btn' : 'btn'" @click="Setsigledimension('single', 'groud')">单耗</div>
                  <div :class="`btn ${unitDimension == 'day'?'active':''}`" @click="Setsigledimension('day', 'dimension')"></div>
                  <div :class="`btn ${unitDimension == 'month'?'active':''}`" @click="Setsigledimension('month', 'dimension')"></div>
                  <div :class="`btn ${unitDimension == 'year'?'active':''}`" @click="Setsigledimension('year', 'dimension')"></div>
                </div>
                <groupChart :options="lineOption"></groupChart>
              </div>
            </groupPlate>
          </div>

CSS:

            .line_monitor {
                .content {
                    height: 427px;
                    position: relative;

                    .dimension_box {
                        width: 350px;

                        .btn {
                            width: 50px;
                        }
                    }

                    .group_chart {
                        height: 100%;
                    }
                }
            }

            .active {
                box-shadow: inset 0px 0px 8px 0px #3191cf;
                border-radius: 2px;
            }

JS:

    Setsigledimension(type, groud) {
      if (groud == "groud") {
        if (this.groudDimension.includes(type)) {
          let arr = [];
          this.groudDimension.forEach((item) => {
            if (item != type) {
              arr.push(item);
            }
          });
          this.groudDimension = arr;
          this.setOptionLine();
        } else {
          this.groudDimension.push(type);
        }
        this.getGrouddata();
      } else if (groud == "dimension") {
        this.unitDimension = type;
        this.getGrouddata();
      }
    },
    getGrouddata() {
      if (!this.rankData.length) return;
      let params = {
        dimension: this.unitDimension,
        energyType: 1,
        isOrgData: this.level == 1 ? true : false,
        condition: this.groudDimension,
        meterGroupId: this.meterGroupId || null,

      };
      params.date = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
      params.endDate = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
      let self = this;
      axios.cancel("ogetMeterStationResp");
      if (this.unitDimension == "month") {
        let paramList = [
          params,
          {
            ...params,
            date: moment(new Date())
              .add(-1, "month")
              .format("YYYY-MM-DD HH:mm:ss"),
            endDate: moment(new Date())
              .add(-1, "month")
              .format("YYYY-MM-DD HH:mm:ss"),
          },
        ];
        let leng =
          moment(new Date()).add(-1, "month").endOf("month").format("DD") - 1 >=
            29
            ? 29
            : 28;
        let toleng = moment(new Date()).format("DD") - 0;
        Promise.all(
          paramList.map((i) => {
            return axios.ogetMeterStationResp(i);
          })
        ).then((reslist) => {
          if (reslist[0].data) {
            let arr = [];
            reslist[0].data.body.forEach((item, index) => {
              let item1 = reslist[1].data.body[index];
              let obj = {
                ...item,
                gwYDate: [
                  ...item1.gwYDate.slice(-(leng - toleng + 1)),
                  ...item.gwYDate.slice(0, toleng),
                ],
                outputDate: item1.outputDate && item.outputDate ? [
                  ...item1.outputDate.slice(-(leng - toleng + 1)),
                  ...item.outputDate.slice(0, toleng),
                ] : null,
                singleDate: item1.singleDate && item.singleDate ? [
                  ...item1.singleDate.slice(-(leng - toleng + 1)),
                  ...item.singleDate.slice(0, toleng),
                ] : null,
                xdate: [
                  ...item1.xdate.slice(-(leng - toleng + 1)),
                  ...item.xdate.slice(0, toleng),
                ],
              };
              arr.push(obj);
            });
            self.respData = [...arr];
            self.setOptionLine();
          }
        });
      } else {
        axios.ogetMeterStationResp({ ...params, isInjection: 0 }).then((res) => {
          if (res.data && res.data.body && res.data.body.length) {
            self.respData = res.data.body;
            self.setOptionLine();
          } else {
            this.singleChart_groud ? this.singleChart_groud.clear() : "";
          }
        });
      }
    },
    setOptionLine() {
      let self = this;
      if (!self.groudDimension.length) {
        self.lineOption = {};
        return;
      }
      let series = [];
      if (self.groudDimension.includes("usageAmount")) {
        let gwYDate = self.respData[self.importantIndex].gwYDate ? self.respData[self.importantIndex].gwYDate.map(x => x.toFixed(2)) : [];
        series.push({
          ydata: gwYDate,
          name: "能耗",
          type: 'line',
          color: 'rgb(173, 255, 47)',
        });
      }
      if (self.groudDimension.includes("single")) {
        let singleDate = self.respData[self.importantIndex].singleDate ? self.respData[self.importantIndex].singleDate.map(x => x.toFixed(2)) : [];
        series.push({
          ydata: singleDate,
          name: "单耗",
          type: 'line',
          color: 'rgb(244, 164, 96)',
        });
      }
      if (self.groudDimension.includes("output")) {
        let outputDate = self.respData[self.importantIndex].outputDate ? self.respData[self.importantIndex].outputDate.map(x => x.toFixed(2)) : [];
        series.push({
          ydata: outputDate,
          name: "产量",
          type: 'line',
          color: 'rgb(2, 126, 247)',
        });
      }
      let option = {
        grid: {
          top: '20%',
          right: '5%',
          bottom: '10%',
          left: '10%',
        },
        xAxis: self.respData[self.importantIndex].xdate,
        series: series,
        legend: {
          textStyle: {
            color: '#C0D7FE'
          },
          left: 'right',
          padding: [20, 20, 0, 0]
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            label: {
              backgroundColor: '#6a7985'
            }
          },
        },
      };
      self.singleMeterName = self.respData[self.importantIndex].meterGroupName == '全厂' ? '整体' : self.respData[self.importantIndex].meterGroupName;
      self.lineOption = option
      //   self.setSingleLine(data, "singleChart_groud");
    },

3、表格设计与单击双击事件

在这里插入图片描述
左边一列的排名在columns里使用render加工:

        {
            title: "排名",
            type: "render",
            prop: "title",
            minWidth: 80,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            display: 'flex',
                            justifyContent: 'center',
                            alignItems: 'center',

                        },
                    },
                    [
                        h('div', {
                            style: {
                                color: params.index < 3 ? "#42EA86" : '#5CE2FF',
                                whiteSpace: "nowrap",
                                background: params.index < 3 ? '#0B2518' : '#011D47',
                                width: '32px',
                                height: '26px',
                                borderTop: params.index < 3 ? '1px solid #2A904C' : '1px solid #0058A4',
                                borderBottom: params.index < 3 ? '1px solid #2A904C' : '1px solid #0058A4',
                            },
                        },
                            params.index + 1),
                    ]

                );
            },
        },

单击事件@rowClick是显示该工厂的数据图表,双击事件@rowDblclick是进入该工厂的下一层子级工厂,需要结合完整代码一并理解,就直接放下面吧


完整代码:

<template>
  <Home :isFullScreen="true">
    <div class="kanban_home_electric" v-loading="loading" element-loading-text="loading..." element-loading-background="rgba(0, 0, 0, 0.5)">
      <div class="kanban__body">
        <!-- 左侧 -->
        <div class="body_left">
          <div class="whole_monitor">
            <groupPlate :title="`电子车间整体监控`">
              <div class="content">
                <div class="card_bg">
                  <div class="ball_bg">
                    <el-progress type="circle" :width="100" :stroke-width="8" :show-text="false" :percentage="loadRate" class="progress"></el-progress>
                    <svg width="100%" height="100%">
                      <defs>
                        <linearGradient id="blue" x1="0%" y1="0%" x2="100%" y2="0%">
                          <stop offset="0%" style="stop-color:rgba(0, 126, 250, 1)" stop-opacity="1" />
                          <stop offset="100%" style="stop-color:rgba(4, 205, 230, 1)" stop-opacity="1" />
                        </linearGradient>
                      </defs>
                    </svg>
                    <div class="value_box">
                      <div class="value">
                        <span>{{ loadRate }}</span>%
                      </div>
                      <div>负荷率</div>
                    </div>
                  </div>
                  <div class="content_left">
                    <div class="content_box" v-for="(item,index) in monitorData.slice(0,3)" :key="index">
                      <img :src="item.img" />
                      <div class="name">{{ item.name }}</div>
                      <div class="value">{{ item.value }}</div>
                    </div>
                  </div>
                  <div class="content_right">
                    <div class="content_box" v-for="(item,index) in monitorData.slice(3,6)" :key="index">
                      <img :src="item.img" />
                      <div class="name">{{ item.name }}</div>
                      <div class="value" :style="`color:${item.color || '#fff'}`">{{ item.value }}</div>
                    </div>
                  </div>
                </div>
              </div>
            </groupPlate>
          </div>
          <div class="whole_trend">
            <groupPlate :title="`电子车间整体用电趋势`">
              <div class="content">
                <div class="dimension_box">
                  <div :class="`btn ${trendDimension == 'day'?'active':''}`" @click="changeTrend('day')"></div>
                  <div :class="`btn ${trendDimension == 'month'?'active':''}`" @click="changeTrend('month')"></div>
                  <div :class="`btn ${trendDimension == 'year'?'active':''}`" @click="changeTrend('year')"></div>
                </div>
                <groupChart :options="trendOption"></groupChart>
              </div>
            </groupPlate>
          </div>
          <div class="whole_alarm">
            <groupPlate :title="`电子车间报警分析`">
              <div class="content">
                <groupTable :columns="alarmColumns" :Serialnumber="false" :data="alarmList" stripe></groupTable>
              </div>
            </groupPlate>
          </div>
        </div>
        <!-- 中间 -->
        <div class="body_center">
          <div class="line_monitor">
            <groupPlate :title="`${singleMeterName}能耗监控`">
              <div class="content">
                <div class="dimension_box">
                  <div :class="groudDimension.includes('usageAmount')? 'active btn': 'btn'" @click="Setsigledimension('usageAmount', 'groud')">能耗</div>
                  <div :class="groudDimension.includes('output') ? 'active btn' : 'btn'" @click="Setsigledimension('output', 'groud')">产量</div>
                  <div :class="groudDimension.includes('single') ? 'active btn' : 'btn'" @click="Setsigledimension('single', 'groud')">单耗</div>
                  <div :class="`btn ${unitDimension == 'day'?'active':''}`" @click="Setsigledimension('day', 'dimension')"></div>
                  <div :class="`btn ${unitDimension == 'month'?'active':''}`" @click="Setsigledimension('month', 'dimension')"></div>
                  <div :class="`btn ${unitDimension == 'year'?'active':''}`" @click="Setsigledimension('year', 'dimension')"></div>
                </div>
                <groupChart :options="lineOption"></groupChart>
              </div>
            </groupPlate>
          </div>
          <div class="line_waste">
            <groupPlate :title="`线体用能浪费监控`">
              <div class="content">
                <div class="dimension_box">
                  <div :class="`btn ${wasteDimension == 'day'?'active':''}`" @click="changeWaste('day')"></div>
                  <div :class="`btn ${wasteDimension == 'month'?'active':''}`" @click="changeWaste('month')"></div>
                  <div :class="`btn ${wasteDimension == 'year'?'active':''}`" @click="changeWaste('year')"></div>
                </div>
                <div class="waste_box" v-for="(item,index) in wasteData" :key="index">
                  <div class="name">{{ item.meterGroupName }}</div>
                  <div class="value">
                    {{ item.wasteUsage }}
                    <span>kwh</span>
                  </div>
                </div>
              </div>
            </groupPlate>
          </div>
        </div>
        <!-- 右侧 -->
        <div class="body_right">
          <div class="whole_rank">
            <groupPlate :title="`电子车间用电排名情况`">
              <div class="content">
                <groupTable :columns="rankColumns" :Serialnumber="false" :data="rankData" stripe @rowClick="rowclick" @rowDblclick="rowDblclick"></groupTable>
                <div class="reset" v-if="this.level != 1" @click="handlerReset()">返回</div>
              </div>
            </groupPlate>
          </div>
          <div class="main_monitor">
            <groupPlate :title="`重点设备能耗监控`">
              <div class="content">
                <groupTable :columns="mainColumns" :Serialnumber="false" :data="wasteData" stripe></groupTable>
              </div>
            </groupPlate>
          </div>
        </div>
      </div>
    </div>
  </Home>
</template>
    <script>
import ResizeObserver from "resize-observer-polyfill";
import * as echarts from "echarts";
import moment from "moment";
import axios from "../../api/index";
import groupPlate from '../kanban_group/components/group_plate';
import groupChart from '../kanban_group/components/group_chart';
import groupTable from "../kanban_group/components/group_table.vue";
import columns from "./components/columns";
import "moment/locale/zh-cn";
export default {
  name: "kanban_home_electric",
  components: {
    groupPlate,
    groupChart,
    groupTable,
  },
  data() {
    return {
      loading: false,
      searchTime: null,
      // 左侧
      monitorData: [
        {
          img: require('../../assets/homeElectric/icon_link.png'),
          name: '设备接入数',
          value: 335,
        },
        {
          img: require('../../assets/homeElectric/icon_online.png'),
          name: '在线总数',
          value: 329,
        },
        {
          img: require('../../assets/homeElectric/icon_offline.png'),
          name: '离线总数',
          value: 5,
        },
        {
          img: require('../../assets/homeElectric/icon_alarm.png'),
          name: '预警数',
          value: 1,
          color: '#E76746',
        },
        {
          img: require('../../assets/homeElectric/icon_done.png'),
          name: '已处理',
          value: 1,
          color: '#35B45E',
        },
        {
          img: require('../../assets/homeElectric/icon_notyet.png'),
          name: '待处理',
          value: 0,
        },
      ],
      loadRate: 0,
      trendDimension: 'day',
      meterGroupId: null,
      meterGroupName: null,
      trendOption: {},

      alarmList: [],
      // 中间
      groudDimension: ["single", "usageAmount", "output"],
      unitDimension: 'day',
      respData: [],
      singleMeterName: "",
      lineOption: {},
      wasteData: [],
      wasteDimension: 'day',
      // 右侧
      arrow_up: require('../../assets/businessMonitoring/arrow_up.png'),
      arrow_down: require('../../assets/businessMonitoring/arrow_down.png'),
      mainMeterGroupId: null,
      importantIndex: 0,
      rankData: [],
      level: 1,
      rowclickTime: null,
    };
  },
  computed: {
    alarmColumns() {
      return columns.alarmColumns;
    },
    mainColumns() {
      return columns.mainColumns;
    },
    rankColumns() {
      return columns.rankColumns;
    }
  },
  methods: {
    // 每5分钟自动更新
    searchAuto() {
      clearTimeout(this.searchTime);
      this.search();
      let self = this;
      this.searchTime = setTimeout(function () {
        self.searchAuto();
      }, 1000 * 60 * 5);
    },
    search() {
      this.getGroupData();
      this.getMeterGroup();
    },
    getGroupData() {
      axios.getGroupData({ dictLetter: '总负荷' }).then((res) => {
        if (res.data && res.data.body) {
          this.monitorData[0].value = res.data.body.totalCount;
          this.monitorData[1].value = res.data.body.onLineCount;
          this.monitorData[2].value = res.data.body.offLineCount;
          this.monitorData[3].value = res.data.body.alarmsTotal;
          this.monitorData[4].value = res.data.body.handledCount;
          this.monitorData[5].value = res.data.body.unHandledCount;
          this.loadRate = res.data.body.loadRate > 100 ? 100 : res.data.body.loadRate;
          this.alarmList = res.data.body.alarmList;
        }
      })
    },
    getMeterGroup() {
      axios.getMeterGroup({ dictLetter: '总负荷' }).then((res) => {
        if (res.data && res.data.body && res.data.body.length) {
          this.meterGroupId = res.data.body[0].id;
          this.mainMeterGroupId = res.data.body[0].id;
          this.meterGroupName = res.data.body[0].name;
          this.changeTrend(this.trendDimension);
          this.changeWaste(this.wasteDimension);
          this.getRankData(this.meterGroupId);
        }
      })
    },
    changeTrend(dimension) {
      this.trendDimension = dimension;
      let params = {
        energyType: 1,
        condition: ["usageAmount"],
        meterGroupId: this.meterGroupId,
        isOrgData: true,
        isInjection: 0
      }
      let paramList = [
        {
          ...params,
          dimension,
          date: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
          endDate: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
        },
        {
          ...params,
          dimension,
          date: moment(new Date()).add(-1, dimension).format("YYYY-MM-DD HH:mm:ss"),
          endDate: moment(new Date()).add(-1, dimension).format("YYYY-MM-DD HH:mm:ss"),
        },
      ];
      Promise.all(
        paramList.map((i) => {
          return axios.ogetMeterStationResp(i);
        })
      ).then((reslist) => {
        let xAxis = reslist[0].data.body[0].xdate.map(x => { return x.slice(-2) })
        let option = {
          grid: {
            top: '27%',
            right: '3%',
            bottom: '15%',
            left: '13%',
          },
          legend: {
            textStyle: {
              color: '#C0D7FE'
            },
            left: 'right',
            padding: [20, 20, 0, 0]
          },
          xAxis: xAxis,
          series: [
            {
              name: dimension == 'day' ? '本日' : dimension == 'month' ? '本月' : '本年',
              ydata: reslist[0].data.body[0].gwYDate,
              type: 'line',
              color: '#0CC8E6',
              areaColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: '#043953'
                },
                {
                  offset: 1,
                  color: 'rgba(7, 17, 38, 0)'
                }
              ])
            },
            {
              name: dimension == 'day' ? '昨日' : dimension == 'month' ? '上月' : '去年',
              ydata: reslist[1].data.body[0].gwYDate,
              type: 'line',
              color: '#08BA57',
              areaColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: '#04392f'
                },
                {
                  offset: 1,
                  color: 'rgba(7, 17, 38, 0)'
                }
              ])
            },
          ],
        }
        this.trendOption = option;
      })
    },
    changeWaste(dimension) {
      this.wasteDimension = dimension;
      axios.getWasteEnergyData({ parentId: this.meterGroupId, dimension }).then((res) => {
        let arr = [];
        if (res.data && res.data.body && res.data.body.length) {
          arr = res.data.body.map(item => {
            return {
              ...item,
              //   usageAmount: Math.floor(item.usageAmount * 100) / 100
              usageAmount: item.usageAmount.toFixed(2)
            }
          })
        }
        this.wasteData = arr;
      })
    },
    getRankData(meterGroupId) {
      let date = moment(new Date()).format("YYYY-MM-DD");
      let params = {
        date: date,
        dimension: "day",
        dimensionType: "nature",
        energyType: 1,
        groupType: 1,
        level: -1,
        nodeType: "meterGroup",
        parentId: meterGroupId,
      };
      axios.meterGroupRankDayUsage({ params }).then((res) => {
        if (res.data) {
          this.rankData = res.data;
          this.getGrouddata();
        }
      });
    },
    Setsigledimension(type, groud) {
      if (groud == "groud") {
        if (this.groudDimension.includes(type)) {
          let arr = [];
          this.groudDimension.forEach((item) => {
            if (item != type) {
              arr.push(item);
            }
          });
          this.groudDimension = arr;
          this.setOptionLine();
        } else {
          this.groudDimension.push(type);
        }
        this.getGrouddata();
      } else if (groud == "dimension") {
        this.unitDimension = type;
        this.getGrouddata();
      }
    },
    getGrouddata() {
      if (!this.rankData.length) return;
      let params = {
        dimension: this.unitDimension,
        energyType: 1,
        isOrgData: this.level == 1 ? true : false,
        condition: this.groudDimension,
        meterGroupId: this.meterGroupId || null,

      };
      params.date = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
      params.endDate = moment(new Date()).format("YYYY-MM-DD HH:mm:ss");
      let self = this;
      axios.cancel("ogetMeterStationResp");
      if (this.unitDimension == "month") {
        let paramList = [
          params,
          {
            ...params,
            date: moment(new Date())
              .add(-1, "month")
              .format("YYYY-MM-DD HH:mm:ss"),
            endDate: moment(new Date())
              .add(-1, "month")
              .format("YYYY-MM-DD HH:mm:ss"),
          },
        ];
        let leng =
          moment(new Date()).add(-1, "month").endOf("month").format("DD") - 1 >=
            29
            ? 29
            : 28;
        let toleng = moment(new Date()).format("DD") - 0;
        Promise.all(
          paramList.map((i) => {
            return axios.ogetMeterStationResp(i);
          })
        ).then((reslist) => {
          if (reslist[0].data) {
            let arr = [];
            reslist[0].data.body.forEach((item, index) => {
              let item1 = reslist[1].data.body[index];
              let obj = {
                ...item,
                gwYDate: [
                  ...item1.gwYDate.slice(-(leng - toleng + 1)),
                  ...item.gwYDate.slice(0, toleng),
                ],
                outputDate: item1.outputDate && item.outputDate ? [
                  ...item1.outputDate.slice(-(leng - toleng + 1)),
                  ...item.outputDate.slice(0, toleng),
                ] : null,
                singleDate: item1.singleDate && item.singleDate ? [
                  ...item1.singleDate.slice(-(leng - toleng + 1)),
                  ...item.singleDate.slice(0, toleng),
                ] : null,
                xdate: [
                  ...item1.xdate.slice(-(leng - toleng + 1)),
                  ...item.xdate.slice(0, toleng),
                ],
              };
              arr.push(obj);
            });
            self.respData = [...arr];
            self.setOptionLine();
          }
        });
      } else {
        axios.ogetMeterStationResp({ ...params, isInjection: 0 }).then((res) => {
          if (res.data && res.data.body && res.data.body.length) {
            self.respData = res.data.body;
            self.setOptionLine();
          } else {
            this.singleChart_groud ? this.singleChart_groud.clear() : "";
          }
        });
      }
    },
    setOptionLine() {
      let self = this;
      if (!self.groudDimension.length) {
        self.lineOption = {};
        return;
      }
      let series = [];
      if (self.groudDimension.includes("usageAmount")) {
        let gwYDate = self.respData[self.importantIndex].gwYDate ? self.respData[self.importantIndex].gwYDate.map(x => x.toFixed(2)) : [];
        series.push({
          ydata: gwYDate,
          name: "能耗",
          type: 'line',
          color: 'rgb(173, 255, 47)',
        });
      }
      if (self.groudDimension.includes("single")) {
        let singleDate = self.respData[self.importantIndex].singleDate ? self.respData[self.importantIndex].singleDate.map(x => x.toFixed(2)) : [];
        series.push({
          ydata: singleDate,
          name: "单耗",
          type: 'line',
          color: 'rgb(244, 164, 96)',
        });
      }
      if (self.groudDimension.includes("output")) {
        let outputDate = self.respData[self.importantIndex].outputDate ? self.respData[self.importantIndex].outputDate.map(x => x.toFixed(2)) : [];
        series.push({
          ydata: outputDate,
          name: "产量",
          type: 'line',
          color: 'rgb(2, 126, 247)',
        });
      }
      let option = {
        grid: {
          top: '20%',
          right: '5%',
          bottom: '10%',
          left: '10%',
        },
        xAxis: self.respData[self.importantIndex].xdate,
        series: series,
        legend: {
          textStyle: {
            color: '#C0D7FE'
          },
          left: 'right',
          padding: [20, 20, 0, 0]
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            label: {
              backgroundColor: '#6a7985'
            }
          },
        },
      };
      self.singleMeterName = self.respData[self.importantIndex].meterGroupName == '全厂' ? '整体' : self.respData[self.importantIndex].meterGroupName;
      self.lineOption = option
      //   self.setSingleLine(data, "singleChart_groud");
    },
    rowclick(row) {
      clearTimeout(this.rowclickTime);
      let self = this;
      this.rowclickTime = setTimeout(() => {
        self.respData.forEach((item, index) => {
          if (item.meterGroupId == row.nodeId) {
            self.importantIndex = index;
            self.setOptionLine();
          }
        });
      }, 200);
    },
    rowDblclick(row) {
      clearTimeout(this.rowclickTime);
      this.level = -1;
      this.meterGroupId = row.nodeId;
      this.importantIndex = 0;
      this.getRankData(this.meterGroupId);
    },
    handlerReset() {
      this.level = 1;
      this.meterGroupId = this.mainMeterGroupId;
      this.importantIndex = 0;
      this.getRankData(this.mainMeterGroupId);
    }
  },
  mounted() {
    let self = this;
    this.$handleSize();
    this.$store.state.femsStore.kanban_name = "电子车间能源监控看板";
    this.$eventbus.$on("fems_up_orgid", () => {
      this.$nextTick(() => {
        self.searchAuto();
      });
    });
    const viewElem = document.body;
    const resizeObserver = new ResizeObserver(() => {
      this.$handleSize();
    });
    resizeObserver.observe(viewElem);
  },
  beforeDestroy() {
    this.$eventbus.$off("fems_up_orgid");
    clearTimeout(this.searchTime);
    clearTimeout(this.rowclickTime);
  },
};
</script>
<style lang="less">
@import './index.less';
</style>

全体样式index.less

.kanban_home_electric {
    height: 1080px;
    width: 1920px;

    .kanban__body {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: space-between;
        padding: 105px 24px 0;

        .dimension_box {
            position: absolute;
            height: 40px;
            width: 160px;
            top: 8px;
            left: 16px;
            display: flex;
            justify-content: space-around;
            align-items: center;
            z-index: 1000;

            .btn {
                width: 40px;
                height: 28px;
                line-height: 28px;
                text-align: center;
                color: #81e0ff;
                cursor: pointer;
            }

            .active {
                box-shadow: inset 0px 0px 8px 0px #3191cf;
                border-radius: 2px;
            }
        }

        .body_left {
            width: 614px;
            height: 100%;

            .whole_monitor {
                .content {
                    height: 204px;
                    padding: 16px;

                    .card_bg {
                        width: 582px;
                        height: 170px;
                        background-repeat: no-repeat;
                        background-size: 100% 100%;
                        background-image: url(../../assets/homeElectric/card_bg.png);
                        position: relative;

                        .ball_bg {
                            width: 181px;
                            height: 186px;
                            background-repeat: no-repeat;
                            background-size: 100% 100%;
                            background-image: url(../../assets/homeElectric/ball_bg.png);
                            position: absolute;
                            top: 9px;
                            left: 212px;

                            .progress {
                                position: absolute;
                                top: 26px;
                                left: 26px;

                                .el-progress-circle__track {
                                    stroke: #042d5c !important;
                                }

                                svg>path:nth-child(2) {
                                    stroke: url(#blue);
                                }
                            }

                            .value_box {
                                position: absolute;
                                width: 85%;
                                top: 54px;
                                text-align: center;
                                font-size: 14px;

                                .value {
                                    span {
                                        font-size: 22px;
                                    }
                                }
                            }
                        }

                        .content_left {
                            position: absolute;
                            top: 15px;
                            left: 18px;
                            height: 143px;
                            display: flex;
                            flex-direction: column;
                            justify-content: space-between;
                        }

                        .content_right {
                            position: absolute;
                            top: 15px;
                            left: 397px;
                            height: 143px;
                            display: flex;
                            flex-direction: column;
                            justify-content: space-between;
                        }

                        .content_box {
                            display: flex;
                            align-items: center;
                            height: 44px;

                            img {
                                height: 44px;
                                width: 44px;
                            }

                            .name {
                                width: 85px;
                                margin-left: 10px;
                                text-align: left;
                                color: rgba(255, 255, 255, 0.8);
                            }

                            .value {
                                width: 50px;
                                text-align: left;
                                font-weight: bold;
                            }
                        }
                    }
                }
            }

            .whole_trend {
                .content {
                    height: 262px;
                    position: relative;

                    .group_chart {
                        height: 100%;
                    }
                }
            }

            .whole_alarm {
                .content {
                    height: 330px;
                }
            }
        }

        .body_center {
            width: 614px;
            height: 100%;

            .line_monitor {
                .content {
                    height: 427px;
                    position: relative;

                    .dimension_box {
                        width: 350px;

                        .btn {
                            width: 50px;
                        }
                    }

                    .group_chart {
                        height: 100%;
                    }
                }
            }

            .line_waste {
                .content {
                    height: 427px;
                    position: relative;
                    padding-top: 60px;
                    //   overflow: hidden;
                    overflow-y: scroll;
                    display: flex;
                    flex-wrap: wrap;
                    align-content: flex-start;

                    .waste_box {
                        width: 182px;
                        height: 106px;
                        margin: 0 0 16px 15px;
                        background-repeat: no-repeat;
                        background-size: 100% 100%;
                        background-image: url(../../assets/homeElectric/waste_bg.png);

                        .name {
                            margin: 22px 0 16px 0;
                            font-size: 16px;
                            text-align: center;
                        }

                        .value {
                            color: #0cc8e6;
                            font-size: 22px;
                            text-align: center;
                            white-space: nowrap;
                            text-overflow: ellipsis;
                            overflow: hidden;

                            span {
                                font-size: 16px;
                            }
                        }
                    }
                }
            }
        }

        .body_right {
            width: 614px;
            height: 100%;

            .whole_rank {
                .content {
                    height: 427px;
                    position: relative;

                    .reset {
                        position: absolute;
                        width: 40px;
                        height: 28px;
                        top: -36px;
                        right: 38px;
                        line-height: 28px;
                        text-align: center;
                        color: #81e0ff;
                        border-radius: 3px;
                        cursor: pointer;
                        z-index: 11;
                        border: 1px solid #3191cf;
                        background-color: rgba(22, 45, 85, 0.1);

                        &:hover {
                            color: #0094ff;
                            border: 1px solid #0094ff;
                        }
                    }
                }
            }

            .main_monitor {
                .content {
                    height: 427px;
                }
            }
        }
    }
}

group_plate组件:

<template>
  <div class="plate">
    <div class="group_title">{{title}}</div>
    <div class="plate_cont">
      <slot></slot>
    </div>
    <div class="shape shape-top-left"></div>
    <div class="shape shape-top-right"></div>
    <div class="shape shape-bottom-left"></div>
    <div class="shape shape-bottom-right"></div>
  </div>
</template>
  <script>
export default {
  name: "plate",
  props: {
    title: {
      type: String,
      default: () => "",
    },
  },
};
  </script>
  <style lang="less">
.plate {
  position: relative;
  margin-bottom: 16px;
  margin-top: 0 !important;
  // font-size: 1.4vh;
  .group_title {
    font-size: 16px;
    text-align: center;
    color: #5bdfff;
    width: 100%;
    height: 40px;
    line-height: 40px;
    background-image: url(./../../../assets/businessMonitoring/panel_title.png);
    background-repeat: no-repeat;
    background-size: 100% 100%;
  }
}
</style>
  

group_chart组件

<template>
  <div class="group_chart" ref="group_chart"></div>
</template>
  <script>
import * as echarts from 'echarts';

export default {
  name: 'group_chart',
  props: {
    options: {
      type: Object,
      default: () => ({
        xAxis: [],
        yAxisName: '',
        series: [],
      }),
    },
  },
  data() {
    return {
      group_chart: null,
    };
  },
  methods: {
    // 绘制电用能折线图
    getOption() {
      if (this.group_chart) {
        this.group_chart.dispose();
        this.group_chart.clear();
      }
      if (!this.options.series || !this.options.series.length) return;
      let series = [];
      this.options.series.forEach(item => {
        if (item.type == 'line') {
          let obj = {
            name: item.name,
            data: item.ydata || [],
            type: item.type,
            symbolSize: 6,
            smooth: true,
            itemStyle: {
              normal: {
                color: item.color || "#0CC8E6",
              },
            },
            lineStyle: {
              normal: {
                width: 2,
                color: item.color || "#0CC8E6",
              },
            },
            areaStyle: item.areaColor ? {
              normal: {
                //右,下,左,上
                color: item.areaColor || new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  {
                    offset: 0,
                    color: '#043953'
                  },
                  {
                    offset: 1,
                    color: 'rgba(7, 17, 38, 0)'
                  }
                ])
              }
            } : null,
          };
          series.push(obj);
        } else if (item.type == 'bar') {
          let obj = {
            name: item.name,
            data: item.ydata || [],
            type: item.type,
            barWidth: 10,
            itemStyle: {
              barBorderRadius: 10,
              color: item.areaColor || new echarts.graphic.LinearGradient(0, 0, 1, 0, [{
                offset: 0, color: '#007EFA'
              }, {
                offset: 1, color: '#04CDE6'
              }])
            }
          };
          series.push(obj);
        }
      });

      let options = {
        grid: this.options.grid || {
          top: '15%',
          right: '3%',
          bottom: '15%',
          left: '10%',
        },
        legend: this.options.legend || {
          textStyle: {
            color: '#C0D7FE'
          },
          padding: [15, 0, 0, 0]
        },
        tooltip: this.options.tooltip || {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            label: {
              backgroundColor: '#6a7985'
            }
          },
          formatter: function (params) {
            if (params.length == 2) {
              return params[0].name + '<br>' + params[0].marker + `${params[0].seriesName}` + params[0].data + '<br>' + params[1].marker + `${params[1].seriesName}` + params[1].data;
            } else if (params.length == 1) {
              return params[0].name + '<br>' + params[0].marker + `${params[0].seriesName}` + params[0].data
            } else {
              return null;
            }
          }
        },
        xAxis: {
          type: 'category',
          boundaryGap: ['2%', '2%'],
          axisTick: {
            alignWithLabel: true
          },
          axisLine: {
            onZero: false,
            lineStyle: { color: '#2D4866' }
          },
          axisLabel: {
            color: '#A8BADA',
          },
          data: this.options.xAxis,
        },
        yAxis: {
          type: 'value',
          name: this.options.yAxisName || '',
          nameTextStyle: {
            padding: [0, 0, 0, -20],
            color: '#A8BADA',

          },
          axisLabel: {
            color: '#A8BADA'
          },
          splitLine: {
            lineStyle: { color: '#061e3f', type: 'solid' }
          },
        },
        series,
      };

      this.group_chart = echarts.init(this.$refs.group_chart);
      this.group_chart.setOption(options, true);
    },
  },
  mounted() {
    this.getOption();
  },
  watch: {
    options: {
      handler() {
        this.getOption();
      },
      deep: true,
    },
  },
};

  </script>
  <style lang="less">
.group_chart {
  width: 100%;
  height: 90%;
}
</style>
  

group_table组件

<template>
  <div class="vexTable" ref="vexTable">
    <el-table
      :data="tableData"
      style="width: 100%"
      size="mini"
      @select="onSelect"
      :span-method="SpanMethod"
      border
      :stripe="stripe"
      :show-overflow-tooltip="true"
      :height="height || tableheight"
      ref="multipleTable"
      @row-click="rowClick"
      @row-dblclick="rowDblclick"
      :show-summary="showSummary"
    >
      <el-table-column type="selection" width="55" v-if="selection" fixed="left" :resizable="false" :selectable="selectable"></el-table-column>
      <el-table-column type="selection" width="55" v-if="showchoice" fixed="left" :resizable="false">
        <template slot-scope="scope">
          <div style="text-align: center">
            <span class="choice" :style="`background:${
                  choice.id && scope.row.id == choice.id
                    ? 'rgb(79, 165, 255)'
                    : ''
                }`"></span>
          </div>
        </template>
      </el-table-column>
      <el-table-column type="index" width="55" v-if="Serialnumber" fixed="left" :resizable="false"></el-table-column>
      <el-table-column
        :prop="item.prop"
        :width="item.width || colums_width || ''"
        :label="item.label || item.title"
        :show-overflow-tooltip="item.tooltip"
        :min-width="item.minWidth"
        :resizable="item.resizable || false"
        v-for="(item, index) in columns"
        :key="index"
        :fixed="item.fixed || winFixed || false"
      >
        <template slot-scope="scope">
          <div style="overflow: hidden">
            <renderFunction v-if="item.type == 'render'" :render="item.render" :row="scope.row" :index="scope.$index" :column="item"></renderFunction>
            <div v-else-if="item.type === 'index'">{{ scope.$index + 1 }}</div>
            <div v-else-if="item.type === 'input'">
              <el-input v-model="scope.row[item.prop]" size="mini"></el-input>
            </div>
            <div v-else-if="item.type === 'searchMore'">
              <el-input v-model="scope.row[item.prop]" type="input" size="mini" v-if="item.type == 'searchMore'" :disabled="item.disabled" style="margintop: 6px">
                <el-button slot="append" icon="el-icon-search" @click="searchMore(scope.row[item.key], scope.$index)"></el-button>
              </el-input>
            </div>
            <el-tooltip v-else-if="item.type === 'tooltip'" class="item" effect="dark" :content="item.content(scope.row[item.prop])" placement="top-start">
              <!-- <div>{{scope.row[item.prop]}}</div> -->
              <renderFunction :render="item.render" :row="scope.row" :index="scope.$index" :column="item"></renderFunction>
            </el-tooltip>
            <div v-else style="text-align: center">{{ scope.row[item.prop] }}</div>
          </div>
        </template>
        <el-table-column
          :prop="items.prop"
          :width="items.width || colums_width || ''"
          :label="items.label || items.title"
          :show-overflow-tooltip="items.tooltip"
          :min-width="items.minWidth"
          :resizable="items.resizable || false"
          v-for="(items, index) in item.children"
          :key="index"
          :fixed="items.fixed || winFixed || false"
        >
          <template slot-scope="scope">
            <div style="overflow: hidden">
              <renderFunction v-if="items.type == 'render'" :render="items.render" :row="scope.row" :index="scope.$index" :column="items"></renderFunction>
              <div v-else-if="items.type === 'index'">{{ scope.$index + 1 }}</div>
              <div v-else-if="items.type === 'input'">
                <el-input v-model="scope.row[items.prop]" size="mini"></el-input>
              </div>
              <div v-else-if="items.type === 'searchMore'">
                <el-input v-model="scope.row[items.prop]" type="input" size="mini" v-if="items.type == 'searchMore'" :disabled="items.disabled" style="margintop: 6px">
                  <el-button slot="append" icon="el-icon-search" @click="searchMore(scope.row[items.key], scope.$index)"></el-button>
                </el-input>
              </div>
              <div v-else style="text-align: center">{{ scope.row[items.prop] }}</div>
            </div>
          </template>
        </el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>
  <script>
import renderFunction from "../../../components/renderFunction";
import ResizeObserver from "resize-observer-polyfill";

export default {
  components: { renderFunction },
  props: {
    Serialnumber: {
      type: Boolean,
      default: () => true,
    },
    columns: {
      type: Array,
      default: () => [],
    },
    data: {
      type: Array,
      default: () => [],
    },
    colums_width: {
      type: Number,
      default: () => 0,
    },
    selection: {
      type: Boolean,
      default: () => false,
    },
    showchoice: {
      type: Boolean,
      default: () => false,
    },
    ruleForm: {
      type: Object,
      default: () => ({}),
    },
    options: {
      type: Object,
      default: () => ({}),
    },
    height: {
      type: Number,
      default: () => 0,
    },
    winFixed: {
      type: String,
      default: () => "",
    },
    columnIndex: {
      type: Number,
      default: () => 1,
    },
    selectable: {
      type: Function,
      default: (row, index) => {
        return true;
      },
    },
    stripe: {
      type: Boolean,
      default: () => false,
    },
    showSummary: {
      type: Boolean,
      default: () => false,
    },
  },
  data() {
    return {
      tableData: [],
      choice: {},
      newcolumns: [],
      tableWidth: 100,
      tableheight: 0,
    };
  },
  watch: {
    data: {
      handler() {
        this.setData();
      },
      deep: true,
    },
    columns: {
      handler() {
        this.newcolumns = [];
        this.setnewcolumns(this.columns);
      },
      deep: true,
    },
    newcolumns: {
      handler() {
        this.setData();
      },
      deep: true,
    },
    $route: {
      handler() {
        this.setData();
      },
      deep: true,
    },
  },
  mounted() {
    this.setnewcolumns(this.columns);
    this.setData();
    let self = this;
    let resizeFinsh = true;
    const viewElem = this.$refs.vexTable;
    const resizeObserver = new ResizeObserver(() => {
      if (resizeFinsh) {
        setTimeout(function () {
          if (
            self.$refs.vexTable &&
            (self.$refs.vexTable.offsetWidth != self.tableWidth ||
              self.$refs.vexTable.offsetHeight != self.offsetHeight)
          ) {
            self.tableWidth = self.$refs.vexTable.offsetWidth;
            self.tableheight = self.$refs.vexTable.offsetHeight;
            self.setData();
          }
          resizeFinsh = true;
        }, 50);
        resizeFinsh = false;
      }
    });
    resizeObserver.observe(viewElem);
  },
  methods: {
    setData() {
      // this.tableData = JSON.parse(JSON.stringify(this.data));
      this.tableData = this.data;
      this.$refs.multipleTable.doLayout();
    },
    setnewcolumns(list) {
      list.forEach((item) => {
        if (!item.children || !item.children.length) {
          this.newcolumns.push(item);
        } else {
          this.setnewcolumns(item.children);
        }
      });
    },
    addComit(row, item) {
      this.$emit("addComit", row, item);
    },
    onSelect(data) {
      this.$emit("onSelect", data);
    },
    SpanMethod({ row, columnIndex }) {
      const thisColumn = this.newcolumns[columnIndex - this.columnIndex];
      if (thisColumn && thisColumn.merge) {
        return {
          rowspan: row[thisColumn.rowspan],
          colspan: 1,
        };
      }
      return {
        rowspan: 1,
        colspan: 1,
      };
    },
    handler(row, item, index, rowIndex) {
      this.$emit("handlerAdd", {
        row,
        item,
        index,
        rowIndex,
      });
    },
    searchMore(item, index, rowIndex) {
      this.$emit("searchMore", { item, index, rowIndex });
    },
    selectChange(item, option, row) {
      if (item.labelProp) {
        const arr = option.filter((i) => i.paramValue === row[item.prop]);
        if (arr.length) {
          row[item.labelProp] = arr[0].paramDesc;
        }
      }
      this.$emit("selectChange", { item, option, row });
    },
    emitTable() {
      return this.tableData;
    },
    rowClick(data, row) {
      this.$emit("rowClick", data);
      if (this.showchoice) {
        this.choice = data;
        this.$refs.multipleTable.clearSelection();
        this.$emit("onSelect", data);
      }
    },
    rowDblclick(data) {
      if (this.showchoice) {
        this.choice = data;
        this.$refs.multipleTable.clearSelection();
      }
      this.$emit("rowDblclick", data);
    },
    clearSelection() {
      this.$refs.multipleTable.clearSelection();
      this.$emit("onSelect", {});
    },
  },
};
  </script>
  <style lang="less">
// .fems-layout .vexTable .el-table--mini td,
// .fems-wuxi-layout .vexTable .el-table--mini td,
// .fems-layout .vexTable .el-table--mini th,
// .fems-wuxi-layout .vexTable .el-table--mini th {
//   padding: 0.45vh 0 !important;
// }
.vexTable {
  width: 100%;
  height: 100%;

  .el-table__header .cell {
    text-align: center;
  }
  .choice {
    display: inline-block;
    width: 15px;
    height: 15px;
    border: 1px solid #ccc;
  }
  .el-table__body-wrapper,
  .el-textarea__inner {
    // &::-webkit-scrollbar-thumb {
    // background: blue;
    // }
    &::-webkit-scrollbar-thumb:hover {
      background: rgb(24, 144, 255);
    }
    &::-webkit-scrollbar {
      width: 6px;
      height: 6px;
    }
  }
  .col_add {
    height: 100%;
    .el-icon-plus {
      border: 1px solid #ccc;
      cursor: pointer;
    }
  }
  .areaMore {
    display: flex;
    .btn {
      width: 30px;
      text-align: center;
      .el-icon-s-order {
        display: inline-block;
        width: 20px;
        height: 20px;
        border: 1px solid #ccc;
        border-radius: 5px;
        color: #ccc;
        line-height: 20px;
        &:hover {
          color: blue;
          border: 1px solid blue;
        }
      }
    }
    .area {
      flex: 1;
    }
  }
}
.newKanbanTable {
  .el-table__header .cell {
    text-align: center;
  }
  .choice {
    display: inline-block;
    width: 15px;
    height: 15px;
    border: 1px solid #ccc;
  }
  .el-table__body-wrapper,
  .el-textarea__inner {
    &::-webkit-scrollbar-thumb {
      background-color: rgb(14, 44, 82);
    }
    &::-webkit-scrollbar-track-piece {
      background-color: rgb(5, 13, 43);
    }
    &::-webkit-scrollbar-thumb:hover {
      background: rgb(24, 144, 255);
    }
    &::-webkit-scrollbar {
      width: 0.5vh;
      height: 0.5vh;
    }
  }

  .el-table,
  .el-table__expanded-cell,
  .el-table th,
  .el-table tr {
    background: none;
    border: none;
    font-size: 16px;
    .cell {
      font-size: 1.2vh;
      padding: 0 5px 0 5px;
      white-space: nowrap;
      text-align: center;
      cursor: pointer;
    }
  }
  .el-table--mini td,
  .el-table--mini th {
    padding: 0.6vh 0;
  }
  .el-table th .cell {
    color: #fff;
    line-height: 2.6vh;
  }
  .el-table__cell {
    border: none;
  }
  .el-table td {
    border: none;
    .cell {
      line-height: 2.6vh;
      color: rgba(255, 255, 255, 0.7);
    }
  }
  .el-table::before,
  .el-table::after {
    background: none;
  }
  .el-table--enable-row-hover .el-table__body tr:hover > td {
    background-color: rgb(17, 40, 83);
  }
  .el-table .el-table__body .el-table__row--striped td {
    background: rgb(10, 30, 56);
  }
  .el-table .el-table__body .hover-row td {
    background: rgb(10, 30, 56);
  }
  .el-table .el-table__fixed-right::before {
    background-color: rgba(0, 0, 0, 0);
  }
  .el-table--striped .el-table__body tr.el-table__row--striped.current-row td,
  .el-table__body tr.current-row > td {
    background-color: rgb(8, 40, 83);
  }
  .has-gutter {
    background-color: rgb(10, 30, 56);
    th .cell {
      color: #bfd6ff;
    }
  }
  .el-table__fixed-right-patch {
    background-color: rgba(0, 0, 0, 0);
    border-color: rgba(0, 0, 0, 0);
  }
  .el-table--border th.gutter:last-of-type {
    border-bottom: 1px solid #16347b;
    border-bottom-width: 1px;
  }
}
</style>
  

为了减少单文件代码行数而单独封装的columns.js文件

let arrow_up = require('../../../assets/businessMonitoring/arrow_up.png');
let arrow_down = require('../../../assets/businessMonitoring/arrow_down.png');

const columns = {
    alarmColumns: [
        {
            title: "节点名称",
            type: "render",
            prop: "title",
            minWidth: 150,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.meterName
                );
            },
        },
        {
            title: "报警类型",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.alarmTypeName
                );
            },
        },
        {
            title: "日期",
            type: "render",
            prop: "title",
            minWidth: 130,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.startTime.slice(0, 10)
                );
            },
        },
        {
            title: "责任人",
            type: "render",
            prop: "title",
            minWidth: 80,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.userMipName
                );
            },
        },
        {
            title: "状态",
            type: "render",
            prop: "title",
            minWidth: 80,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: params.row.handleStatus ? '#35B45E' : '#E76746',
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.handleStatus ? '已处理' : '未处理'
                );
            },
        },
    ],
    mainColumns: [
        {
            title: "排名",
            type: "render",
            prop: "title",
            minWidth: 80,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            display: 'flex',
                            justifyContent: 'center',
                            alignItems: 'center',

                        },
                    },
                    [
                        h('div', {
                            style: {
                                color: params.index < 3 ? "#42EA86" : '#5CE2FF',
                                whiteSpace: "nowrap",
                                background: params.index < 3 ? '#0B2518' : '#011D47',
                                width: '32px',
                                height: '26px',
                                borderTop: params.index < 3 ? '1px solid #2A904C' : '1px solid #0058A4',
                                borderBottom: params.index < 3 ? '1px solid #2A904C' : '1px solid #0058A4',
                            },
                        },
                            params.index + 1),
                    ]

                );
            },
        },
        {
            title: "设备名称",
            type: "render",
            prop: "title",
            minWidth: 150,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.meterGroupName
                );
            },
        },
        {
            title: "开工用能",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.usageAmount
                );
            },
        },
        {
            title: "闲时用能",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.wasteUsage
                );
            },
        },
        {
            title: "闲时用能占比",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: params.row.usageRate < 0 ? '#35B45E' : '#E76746',
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.usageRate + '%'
                );
            },
        },
    ],
    rankColumns: [
        {
            title: "排名",
            type: "render",
            prop: "title",
            minWidth: 80,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            display: 'flex',
                            justifyContent: 'center',
                            alignItems: 'center',

                        },
                    },
                    [
                        h('div', {
                            style: {
                                color: params.index < 3 ? "#42EA86" : '#5CE2FF',
                                whiteSpace: "nowrap",
                                background: params.index < 3 ? '#0B2518' : '#011D47',
                                width: '32px',
                                height: '26px',
                                borderTop: params.index < 3 ? '1px solid #2A904C' : '1px solid #0058A4',
                                borderBottom: params.index < 3 ? '1px solid #2A904C' : '1px solid #0058A4',
                            },
                        },
                            params.index + 1),
                    ]

                );
            },
        },
        {
            title: "产线名称",
            type: "render",
            prop: "title",
            minWidth: 150,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    params.row.deviceName
                );
            },
        },
        {
            title: "电量(万kW·h)",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                return h(
                    "div",
                    {
                        style: {
                            color: "#fff",
                            whiteSpace: "nowrap",
                        },
                    },
                    (params.row.electricity * 10000).toFixed(0) / 10000
                );
            },
        },
        {
            title: "日环比",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                if (params.row.momData) {
                    return h(
                        "div", {
                        style: {
                            display: 'flex',
                            justifyContent: 'center',
                            alignItems: 'center',
                        }
                    },
                        [h('img', {
                            domProps: {
                                align: 'center',
                                src: params.row.momData > 0
                                    ? arrow_up
                                    : arrow_down,
                            },
                            style: {
                                width: '14px',
                                height: '14px',
                                margin: '0 4px',
                            }
                        })
                            , h('span', {
                                style: {
                                    color:
                                        params.row.momData > 0
                                            ? "#E76746"
                                            : "#35B45E",
                                },
                            },
                                params.row.momData + "%"),
                        ]
                    );
                } else {
                    return h(
                        "div", {
                        style: {
                            color: "#fff",
                        }
                    },
                        '0%'
                    );
                }
            },
        },
        {
            title: "日同比",
            type: "render",
            prop: "title",
            minWidth: 100,
            render: (h, params) => {
                if (params.row.yoyData) {
                    return h(
                        "div", {
                        style: {
                            display: 'flex',
                            justifyContent: 'center',
                            alignItems: 'center',
                        }
                    },
                        [h('img', {
                            domProps: {
                                align: 'center',
                                src: params.row.yoyData > 0
                                    ? arrow_up
                                    : arrow_down,
                            },
                            style: {
                                width: '14px',
                                height: '14px',
                                margin: '0 4px',
                            }
                        })
                            , h('span', {
                                style: {
                                    color:
                                        params.row.yoyData > 0
                                            ? "#E76746"
                                            : "#35B45E",
                                },
                            },
                                params.row.yoyData + "%"),
                        ]
                    );
                } else {
                    return h(
                        "div", {
                        style: {
                            color: "#fff",
                        }
                    },
                        '0%'
                    );
                }
            },
        },
    ],
}
export default columns;

那么总算是赶在离职前的最后一天把项目看板开发经验系列肝完了,希望其中的思路能帮助到接触看板开发的你~

之后随缘更新番外篇吧,感谢支持,THX

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/188326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RestTemplate 以及 WebClient 调用第三方接口使用总结

title: RestTemplate 以及 WebClient 调用第三方接口使用总结 date: 2023-01-31 16:51:29 tags: 开发技术及框架 categories:开发技术及框架 cover: https://cover.png feature: false 1. RestTemplate 1.1 引入依赖 RestTemplate 在 spring-boot-starter-web 包下 <dep…

HashMap和HashSet

目录 1、认识 HashMap 和 HashSet 2、哈希表 2.1 什么是哈希表 2.2 哈希冲突 2.2.1 概念 2.2.2 设计合理哈希函数 - 避免冲突 2.2.3 调节负载因子 - 避免冲突 2.2.4 Java中解决哈希冲突 - 开散列/哈希桶 3、HashMap 的部分源码解读 3.1 HashMap 的构造方法 3.2 Hash…

使用CURL快速访问MemFire Cloud应用

“超能力”数据库&#xff5e;拿来即用&#xff0c;应用开发人员再也不用为撰写API而发愁。MemFire Cloud 为开发者提供了简单易用的云数据库&#xff08;表编辑器、自动生成API、SQL编辑器、备份恢复、托管运维&#xff09;&#xff0c;很大地降低开发者的使用门槛。 使用curl…

服装行业2023开年现状速递/服装行业的风险及应对方式/有这些特征的服装企业更容易翻身

在刚刚过去的春节假期里&#xff0c;我们经历了近3年最热闹的一次长假&#xff0c;几乎每天都能在街上看到熙熙攘攘的人流。消费者逛街热情呈“井喷式暴涨”&#xff0c;实体店店主的钱包也跟着鼓起来不少&#xff0c;但年后是否能延续这种旺象&#xff1f;服装行业即将迎来全面…

跨境智星速卖通使用常见问题

跨境智星速卖通使用常见问题 Q&#xff1a;如何使用跨境智星批量注册速卖通买家号&#xff1f;需要准备哪些资料 A&#xff1a;需要将注册信息导入到软件里&#xff0c;需要准备邮箱&#xff08;pop/imap协议&#xff09;&#xff0c;IP&#xff0c;地址等信息&#xff0c;将这…

实战excel

实战excel一、Excel数据格式1.1单元格数据类型1.2 数字1.3 文本1.4 日期1.5 单元格格式二、Excel的快捷操作2.1、快捷键大全2.1.1、文件相关2.1.2、通用快捷键2.1.3、表格选择2.1.4、单元格编辑2.1.5、Excel格式化2.1.6、Excel公式2.2 自动插入求和公式2.3 自动进行列差异比对2…

【C++、数据结构】手撕红黑树

文章目录&#x1f4d6; 前言1. 红黑树的概念⚡&#x1f300; 1.2 红黑树的特性&#xff1a;&#x1f300; 1.3 与AVL树的相比&#xff1a;2. 结点的定义&#x1f31f;⭐2.1 Key模型 和 Key_Value模型的引入&#xff1a;&#x1f3c1;2.1.1 K模型&#x1f3c1;2.1.2 KV模型⭐2.2…

架构演进之路

架构设计: 一&#xff1a;如何分层。 1 为什么要分层&#xff1a;分而治之&#xff0c;各施其职&#xff0c;有条不紊。 常见的分层 计算机osi七层&#xff0c;mvc模型分层&#xff0c;领域模型分层。2 单系统分层模型演进 浏览器-->servlrt-->javabean-->db-->渲染…

unity组件LineRenderer

这是一个好玩的组件 主要作用划线&#xff0c;像水果忍者中的刀光&#xff0c;还有一些涂鸦的小游戏&#xff0c;包括让鼠标划线然后让对象进行跟踪导航也可通过此插件完成 附注&#xff1a;unity版本建议使用稳定一些的版本&#xff0c;有些api可能已经发生变化&#xff0c;…

【数据结构初阶】第四篇——双向链表

链表介绍 初始化链表 销毁链表 打印双向链表 查找数据 增加结点 头插 尾插 在指定位置插入 删除结点 头删 尾删 删除指定位置 链表判空 获取链表中元素个数 顺序表和链表对比 存取方式 逻辑结构与物理结构 时间性能 空间性能 链表介绍 本章讲的是带头双向链…

回溯算法秒杀所有排列-组合-子集问题

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 78. 子集 90. 子集 II 77. 组合 39. 组合总和 40. 组合总和 II 47. 全排列 II&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f…

上海亚商投顾:A股两市震荡走弱 北证50指数大涨5.8%

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。市场情绪沪指今日震荡调整&#xff0c;创业板指午后一度跌近1.5%&#xff0c;黄白二线分化明显&#xff0c;题材概念表现活跃…

Redis快速入门

Redis快速入门&#xff0c;分两个客户端&#xff1a;Jedis和SpringDataRedis 使用Jdedis 1、引入依赖 <!--jedis--> <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version>…

python算法面试题

这是我年前做技术面试官&#xff0c;搜集的面试题&#xff0c;从python基础-机器学习-NLP-CV-深度学习框架-Linux-yolo都有一些题目。针对不同方向的应试者问相应方向的问题。 基本上都是面试八股文&#xff0c;收集记录一下&#xff0c;以后自己也会用的到。 面试题 python基…

深入理解mysql的内核查询成本计算

MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…

过年回家,你是否也努力的给别人解释软件开发是干啥滴?

这个年就这样&#xff0c;在喜气洋洋的气氛中&#xff0c;在我们依依不舍的留恋中&#xff0c;从我们身边溜走了。这次回家又碰见了亲戚们不厌其烦的问我&#xff0c;你做什么工作呐&#xff1f;于是就有了我以下生动的解释 目录 打字的 帮助传话&#xff0c;帮助卖东西 皮…

易点易动打通固定资产采购,为企业实现降本增效

企业为什么要实现采购和资产管理的连接&#xff1f; 随着科技的发展&#xff0c;企业的办公工具越来越多&#xff0c;各类办公软件数不胜数。随之而来的是数据的不连通&#xff0c;员工需要穿梭在各个办公软件&#xff0c;重复导入导出数据&#xff0c;无形中没有提升办公效率…

三维电子沙盘数字沙盘开发教程第3课

三维电子沙盘数字沙盘开发教程第3课下面介绍矢量图层的控制显示&#xff1a;上代码foreach(string key in gis3d.SetFile.Biao.Keys)// gis3d.SetFile.Biao 该对象里存储了所有矢量层的信息{gis3d.SetFile.Biao[key].Show true; //是否显示标签gis3d.SetFile.Biao[key].ShowTe…

1.Weisfeiler-Lehman Algorithm

文章目录1.图同构介绍2.Weisfeiler-Lehman Algorithm3.后话参考资料欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; Weisfeiler-Lehman Algorithm是美国的数学家Boris Weisfeiler在1968年发表的论文the reduction of a graph to a canonic…

Flask WebSocket学习笔记

WebSocket简介&#xff1a;WebSocket是一种全新的协议&#xff0c;随着HTML5的不断完善&#xff0c;越来越多的现代浏览器开始全面支持WebSocket技术了&#xff0c;它将TCP的Socket&#xff08;套接字&#xff09;应用在了webpage上&#xff0c;从而使通信双方建立起一个保持在…