Browse Source

功率曲线拟合模块完成

Koishi 3 years ago
parent
commit
04d6613950

+ 3 - 1
src/components/chart/scatter/current-scatter-chart.vue

@@ -324,7 +324,9 @@ export default {
   updated() {
     let myChart = echarts.init(document.getElementById(this.id));
     myChart.dispose();
-    this.initChart();
+    this.$nextTick(() => {
+      this.initChart();
+    });
   },
   unmounted() {
     window.removeEventListener("resize", this.resize);

+ 5 - 0
src/router/index.js

@@ -509,6 +509,11 @@ const routes = [{
 	component: () => import( /* webpackChunkName: "powerCurve" */ "../views/powerCurve/index.vue"),
 },
 {
+	path: "/totalCurve", // 功率曲线拟合
+	name: "totalCurve",
+	component: () => import( /* webpackChunkName: "powerCurve" */ "../views/totalCurve/index.vue"),
+},
+{
 	path: "/health/nxfx/phdffx", // 偏航对风分析
 	name: "phdffx",
 	component: () => import( /* webpackChunkName: "malfunctionStatistics" */ "../views/windAnalysis/phdffx.vue"),

+ 5 - 0
src/views/layout/Menu.vue

@@ -1003,6 +1003,11 @@ export default {
                   path: "/others/performance",
                 },
                 {
+                  text: "功率曲线拟合",
+                  icon: "svg-matrix",
+                  path: "/totalCurve",
+                },
+                {
                   text: "性能预警综合分析",
                   icon: "svg-matrix",
                   path: "/others/analysis",

+ 389 - 0
src/views/totalCurve/chart.vue

@@ -0,0 +1,389 @@
+<template>
+  <div class="totalCurveChartBox">
+    <div class="l">
+      <el-tree
+        accordion
+        :data="treeData"
+        :props="{
+          children: 'children',
+          label: 'windturbineid',
+        }"
+        @node-click="nodeClick"
+      />
+    </div>
+    <div class="r">
+      <CurrentScatterChart
+        width="100%"
+        height="600px"
+        chartTitle="可框选折线散点图"
+        :xAxisData="xAxisData"
+        :yAxisData="{ splitLine: { show: false } }"
+        :seriesData="seriesData"
+        :showLegend="true"
+        :brushSelected="true"
+        @getSelected="getSelected"
+      />
+    </div>
+    <el-dialog
+      top="100px"
+      :title="
+        '框选详情' + (tableData.length ? ' (' + tableData.length + '条)' : '')
+      "
+      custom-class="modal"
+      v-model="showDialog"
+      width="80%"
+      @closed="
+        (res) => {
+          showDialog = false;
+          tableData = [];
+          gzlx = '';
+          gzItem = null;
+        }
+      "
+    >
+      <el-table
+        :data="tableData"
+        style="width: 100%; height: 600px; overflow-y: scroll"
+        height="250"
+        border
+      >
+        <el-table-column
+          prop="sj"
+          label="时间"
+          width="200px"
+          align="center"
+        ></el-table-column>
+        <el-table-column
+          prop="fs"
+          label="风速(m/s)"
+          sortable
+          align="center"
+        ></el-table-column>
+        <el-table-column
+          prop="gl"
+          label="功率(kw)"
+          sortable
+          align="center"
+        ></el-table-column>
+      </el-table>
+      <template #footer>
+        <span class="dialog-footer">
+          <span class="gzlxTitle" :class="!gzlx ? 'twinkle' : ''"
+            >故障类型:</span
+          >
+          <el-select
+            style="width: 150px"
+            v-model="gzlx"
+            clearable
+            placeholder="请选择"
+            popper-class="select"
+            @change="gzlxChange"
+          >
+            <el-option
+              v-for="item in gzlxArray"
+              :key="item.id"
+              :value="item._index"
+              :label="item.faulttype"
+            >
+            </el-option>
+          </el-select>
+          <el-button
+            class="btn green"
+            type="success"
+            style="margin-left: 12px"
+            @click="save"
+            :disabled="!gzlx && !gzItem"
+          >
+            保存
+          </el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import CurrentScatterChart from "../../components/chart/scatter/current-scatter-chart.vue";
+import axios from "axios";
+export default {
+  components: {
+    CurrentScatterChart,
+  },
+  data() {
+    return {
+      treeData: [],
+      xAxisData: [],
+      seriesData: [],
+      station: "",
+      wtId: "",
+      time: "",
+      showDialog: false,
+      tableData: [],
+      gzlx: "",
+      gzlxArray: [],
+      gzItem: null,
+    };
+  },
+  created() {
+    this.getTree();
+    this.getGzlx();
+  },
+  methods: {
+    // 选择故障类型
+    gzlxChange(idx) {
+      let gzItem = this.gzlxArray.find((ele) => {
+        return ele._index === idx;
+      });
+      this.gzItem = gzItem;
+    },
+    // 获取树形数据
+    getTree() {
+      const that = this;
+      that.API.requestData({
+        method: "GET",
+        baseURL: "http://192.168.1.18:9002/",
+        subUrl: "powercurve/tree",
+        success(res) {
+          that.treeData = res.data;
+          const getFirstTreeData = that.getFirstTreeData(res.data[0]);
+          that.station = getFirstTreeData.stationen;
+          that.wtId = getFirstTreeData.windturbineid;
+          that.time = getFirstTreeData.time;
+          that.getChartData();
+        },
+      });
+    },
+
+    // 获取树形数据
+    getGzlx() {
+      const that = this;
+      that.API.requestData({
+        method: "GET",
+        baseURL: "http://192.168.1.18:9002/",
+        subUrl: "know/fault/type/all",
+        success(res) {
+          res.data.forEach((ele, index) => {
+            ele._index = index;
+          });
+          that.gzlxArray = res.data;
+        },
+      });
+    },
+
+    // 树形结构点击处理
+    nodeClick(res) {
+      if (!res.children) {
+        this.station = res.stationen;
+        this.wtId = res.windturbineid;
+        this.time = res.time;
+        this.getChartData();
+      }
+    },
+
+    // 获取树状结构内第一个节点内的第一条数据
+    getFirstTreeData(treeData) {
+      if (treeData?.children) {
+        return this.getFirstTreeData(treeData.children[0]);
+      } else {
+        return treeData;
+      }
+    },
+
+    // 获取图表数据
+    getChartData() {
+      const that = this;
+      that.API.requestData({
+        method: "POST",
+        baseURL: "http://192.168.1.18:9002/",
+        subUrl: "scatter/list",
+        data: {
+          station: that.station,
+          wtId: that.wtId,
+          time: that.time,
+        },
+        success(res) {
+          if (
+            !res.data.lineactual?.length &&
+            !res.data.lineoptimal?.length &&
+            !res.data.scatter?.length
+          ) {
+            that.BASE.showMsg({
+              type: "success",
+              msg: "所选风机暂无图表数据,请更换风机后尝试",
+            });
+          }
+          let sjgl = [];
+          let zygl = [];
+          let fsgl = [];
+          let xAxisData = [];
+
+          res.data.lineactual.forEach((ele, index) => {
+            sjgl.push(ele[1]);
+            xAxisData.push(index);
+          });
+
+          res.data.lineoptimal.forEach((ele) => {
+            zygl.push(ele[1]);
+          });
+
+          res.data.scatter.forEach((ele) => {
+            if (ele[1] >= 0) fsgl.push(ele);
+          });
+
+          that.seriesData = [
+            {
+              name: "风速功率",
+              type: "effectScatter",
+              showEffectOn: "emphasis",
+              symbolSize: 5,
+              data: fsgl,
+              xAxisIndex: 1,
+            },
+            {
+              name: "实际功率",
+              type: "line",
+              symbol: "circle", //设定为实心点
+              symbolSize: 0, //设定实心点的大小
+              smooth: true, //这个是把线变成曲线
+              data: sjgl,
+              itemStyle: {
+                normal: {
+                  color: "#05bb4c",
+                  lineStyle: {
+                    color: "#05bb4c",
+                  },
+                },
+              },
+              xAxisIndex: 0,
+            },
+            {
+              name: "最优功率",
+              type: "line",
+              symbol: "circle", //设定为实心点
+              symbolSize: 0, //设定实心点的大小
+              smooth: true, //这个是把线变成曲线
+              data: zygl,
+              itemStyle: {
+                normal: {
+                  color: "#f8de5b",
+                  lineStyle: {
+                    color: "#f8de5b",
+                  },
+                },
+              },
+              xAxisIndex: 0,
+            },
+          ];
+
+          that.xAxisData = xAxisData;
+        },
+      });
+    },
+
+    // 获取图表框选结果
+    getSelected(res) {
+      const seriesIndex = res[0]?.selected[0]?.seriesIndex;
+      const selected = res[0]?.selected[0]?.dataIndex;
+      if (selected?.length) {
+        let tableData = [];
+        selected?.forEach((seleIndex) => {
+          const item = this.seriesData[seriesIndex].data[seleIndex];
+          tableData.push({
+            fs: item[0],
+            gl: item[1],
+            sj: item[2],
+          });
+        });
+        this.tableData = tableData;
+        this.showDialog = true;
+      }
+    },
+
+    // 保存
+    save() {
+      const that = this;
+      let data = [];
+      that.tableData.forEach((ele) => {
+        data.push({
+          tag: "0",
+          windturbineid: that.wtId,
+          faulttype: that.gzItem.faulttype,
+          faultcode: that.gzItem.faultcode,
+          starttime: ele.sj,
+          stationen: that.station,
+          category: "1",
+        });
+      });
+
+      this.BASE.showLoading();
+
+      axios({
+        method: "post",
+        url: "http://192.168.1.18:9002/case/fault/insert",
+        data,
+        header: {
+          "Content-Type": "application/json",
+        },
+      }).then((res) => {
+        if (res.data.code === 200) {
+          that.showDialog = false;
+          that.BASE.showMsg({
+            type: "success",
+            msg: "保存成功",
+          });
+          that.closeLoading();
+        }
+      });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.totalCurveChartBox {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  justify-content: start;
+  align-content: center;
+
+  .l,
+  .r {
+    width: 20%;
+    height: 100%;
+  }
+
+  .r {
+    width: 80%;
+  }
+
+  .gzlxTitle {
+    color: rgb(179, 189, 192);
+    transition: 0.2s;
+  }
+
+  .gzlxTitle.twinkle {
+    animation: twinkle 0.75s infinite;
+  }
+
+  @keyframes twinkle {
+    0% {
+      color: rgb(179, 189, 192);
+    }
+    50% {
+      color: #f25656;
+    }
+    100% {
+      color: rgb(179, 189, 192);
+    }
+  }
+}
+</style>
+
+<style lang="less">
+.totalCurveChartBox {
+  .el-dialog__body {
+    max-height: 620px;
+    overflow: hidden;
+  }
+}
+</style>

+ 519 - 0
src/views/totalCurve/dataDispose.vue

@@ -0,0 +1,519 @@
+<template>
+  <div class="dataDisposeBox">
+    <div class="query mg-b-8">
+      <div class="query-items">
+        <div class="query-item">
+          <div class="lable">场站:</div>
+          <div class="search-input">
+            <el-select
+              v-model="changzhan"
+              placeholder="请选择"
+              popper-class="select"
+              @change="
+                () => {
+                  getFengji();
+                }
+              "
+            >
+              <el-option
+                v-for="item in changzhanArray"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="query-item">
+          <div class="lable">风机:</div>
+          <div class="search-input">
+            <el-select
+              v-model="fengji"
+              clearable
+              placeholder="请选择"
+              popper-class="select"
+              multiple
+              collapse-tags
+            >
+              <el-option
+                v-for="item in fengjiArray"
+                :key="item.id"
+                :value="item.id"
+                :label="item.name"
+              >
+              </el-option>
+            </el-select>
+          </div>
+        </div>
+        <div class="query-item">
+          <div class="lable">时间:</div>
+          <div class="search-input">
+            <el-date-picker
+              v-model="date"
+              type="month"
+              value-format="YYYY-MM"
+              placeholder="请选择"
+              popper-class="date-select"
+            >
+            </el-date-picker>
+          </div>
+        </div>
+        <div class="query-actions" style="margin-left: 0px">
+          <button class="btn green" @click="apply">数据预处理</button>
+        </div>
+      </div>
+    </div>
+    <div class="query mg-b-8">
+      <div class="query-items">
+        <div class="query-item">
+          <div class="lable">筛选条件:</div>
+        </div>
+        <div class="query-item">
+          <el-checkbox-group v-model="checkList">
+            <el-checkbox label="connected" size="small">并网</el-checkbox>
+            <el-checkbox label="correct" size="small">合理值</el-checkbox>
+            <el-checkbox label="connected10" size="small"
+              >并网十分钟</el-checkbox
+            >
+            <el-checkbox label="prestop10" size="small"
+              >停机前十分钟</el-checkbox
+            >
+            <el-checkbox label="levels" size="small">欠符合等级</el-checkbox>
+            <el-select
+              v-model="qfhdj"
+              placeholder=" "
+              size="small"
+              style="width: 100px; margin-left: 12px"
+              clearable
+              @change="selectChange"
+            >
+              <el-option
+                v-for="item in qfhdjArray"
+                :key="item.id"
+                :label="item.label"
+                :value="item.id"
+              />
+            </el-select>
+          </el-checkbox-group>
+        </div>
+        <div class="query-item">
+          <div class="lable">间隔:</div>
+          <el-select
+            v-model="jg"
+            placeholder="请选择"
+            size="small"
+            style="width: 100px; margin-left: 12px"
+          >
+            <el-option
+              v-for="item in jgArray"
+              :key="item.id"
+              :label="item.label"
+              :value="item.id"
+            />
+          </el-select>
+        </div>
+      </div>
+    </div>
+    <div class="dataBox">
+      <div class="l">
+        <el-tree
+          accordion
+          :data="treeData"
+          :props="{
+            children: 'children',
+            label: 'windturbineid',
+          }"
+          @node-click="nodeClick"
+        />
+      </div>
+      <div class="r">
+        <el-table
+          :data="tableData"
+          style="width: 100%; height: 85%; overflow-y: scroll"
+          height="250"
+          border
+        >
+          <el-table-column
+            prop="time"
+            label="时间"
+            width="200px"
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="windturbineid"
+            label="风机"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="power"
+            label="风机功率"
+            width="200px"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="speed"
+            label="风机风速"
+            width="200px"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="rotate"
+            label="风机发电机转速"
+            width="200px"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="status"
+            label="风机状态"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="quantity"
+            label="风机电量"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="curveoffset"
+            label="欠发状态"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="direction"
+            label="风向"
+            width="200px"
+            sortable
+            align="center"
+          ></el-table-column>
+          <el-table-column
+            prop="angle"
+            label="对风角度"
+            width="200px"
+            sortable
+            align="center"
+          ></el-table-column>
+        </el-table>
+        <el-pagination
+          v-model:currentPage="currentPage"
+          v-model:page-size="pageSize"
+          :page-sizes="[500, 1000, 2000]"
+          :small="small"
+          :background="false"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="tableTotal"
+          @size-change="changeTableSize"
+          @current-change="changeCurrentPage"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from "axios";
+export default {
+  components: {},
+  data() {
+    return {
+      treeData: [],
+      changzhan: "",
+      changzhanArray: [],
+      fengji: [],
+      fengjiArray: [],
+      date: new Date().formatDate("yyyy-MM"),
+      checkList: [],
+      qfhdj: "2",
+      qfhdjArray: [
+        {
+          id: "1",
+          label: "1",
+        },
+        {
+          id: "2",
+          label: "2",
+        },
+        {
+          id: "3",
+          label: "3",
+        },
+        {
+          id: "4",
+          label: "4",
+        },
+        {
+          id: "5",
+          label: "5",
+        },
+      ],
+      jg: "300",
+      jgArray: [
+        {
+          id: "1",
+          label: "1秒钟",
+        },
+        {
+          id: "60",
+          label: "1分钟",
+        },
+        {
+          id: "300",
+          label: "5分钟",
+        },
+        {
+          id: "900",
+          label: "15分钟",
+        },
+      ],
+      tableData: [],
+      currentPage: 1,
+      pageSize: 500,
+      tableTotal: 0,
+    };
+  },
+  created() {
+    this.getChangeZhan();
+    this.getTree();
+  },
+  methods: {
+    // 数据预处理
+    apply() {
+      let stationen = this.changzhan;
+      let windturbineid = this.fengji;
+      let time = this.date;
+
+      let connected = false;
+      let correct = false;
+      let connected10 = false;
+      let prestop10 = false;
+      let levels = null;
+
+      let intervals = ~~this.jg;
+
+      let params = {
+        stationen,
+        windturbineid,
+        time,
+        connected,
+        correct,
+        connected10,
+        prestop10,
+        levels,
+        intervals,
+      };
+
+      this.checkList.forEach((ele) => {
+        for (let key in params) {
+          if (key === ele && ele !== "levels") {
+            params[key] = true;
+          }
+          if (ele === "levels") {
+            params.levels = ~~this.qfhdj || null;
+          }
+        }
+      });
+
+      if (!params.windturbineid) {
+        this.BASE.showMsg({
+          msg: "风机不可为空",
+        });
+      } else if (!params.time) {
+        this.BASE.showMsg({
+          msg: "时间不可为空",
+        });
+      } else {
+        this.sendData(params);
+      }
+    },
+
+    // 发送数据预处理数据
+    sendData(data) {
+      const that = this;
+      axios({
+        method: "post",
+        url: "http://192.168.1.18:9002/scatter/preprocess",
+        data,
+        header: {
+          "Content-Type": "application/json",
+        },
+      }).then((res) => {
+        if (res.data.code === 200) {
+          that.BASE.showMsg({
+            type: "success",
+            msg: "数据已提交,请稍后刷新页面查看",
+          });
+        }
+      });
+    },
+
+    // 获取树形数据
+    getTree() {
+      const that = this;
+      that.API.requestData({
+        method: "GET",
+        baseURL: "http://192.168.1.18:9002/",
+        subUrl: "powercurve/tree",
+        success(res) {
+          that.treeData = res.data;
+        },
+      });
+    },
+
+    // 获取场站列表
+    getChangeZhan() {
+      const that = this;
+      that.API.requestData({
+        method: "GET",
+        baseURL: "http://10.155.32.4:9001/",
+        subUrl: "benchmarking/wplist",
+        success(res) {
+          that.changzhanArray = res.data;
+          that.changzhan = res.data[0].id;
+          that.getFengji();
+        },
+      });
+    },
+
+    // 获取风机列表
+    getFengji(fjId) {
+      const that = this;
+      that.API.requestData({
+        method: "GET",
+        baseURL: "http://10.155.32.4:9001/",
+        subUrl: "benchmarking/wtList",
+        data: {
+          wpid: that.changzhan,
+        },
+        success(res) {
+          that.fengjiArray = res.data;
+          that.fengji = fjId?.split(",") || [res.data[0].id];
+          if (fjId) that.getTableData();
+        },
+      });
+    },
+
+    // 欠符合等级 checkbox 勾选逻辑修改
+    selectChange(res) {
+      let resultIndex = 0;
+      const result = this.checkList.some((ele, index) => {
+        if (ele === "levels") {
+          resultIndex = index;
+        }
+        return ele === "levels";
+      });
+      if (res) {
+        if (!result) {
+          this.checkList.push("levels");
+        }
+      } else {
+        if (result) {
+          this.checkList.splice(resultIndex, 1);
+        }
+      }
+    },
+
+    // 获取表格数据
+    getTableData() {
+      const that = this;
+      that.API.requestData({
+        method: "GET",
+        baseURL: "http://192.168.1.18:9002/",
+        subUrl: "powercurve/list",
+        data: {
+          station: that.changzhan,
+          wtid: that.fengji,
+          time: that.date,
+          pagenum: that.currentPage,
+          pagesize: that.pageSize,
+        },
+        success(res) {
+          that.tableData = res.data.list;
+          that.tableTotal = res.data.total;
+        },
+      });
+    },
+
+    // 修改分页每页显示数量
+    changeTableSize(res) {
+      this.pageSize = res;
+      this.currentPage = 1;
+      this.getTableData();
+    },
+
+    // 修改分页当前页数
+    changeCurrentPage(res) {
+      this.currentPage = res;
+      this.getTableData();
+    },
+
+    // 树形结构点击处理
+    nodeClick(res) {
+      if (!res.children) {
+        this.changzhan = res.stationen;
+        let checkList = [];
+        if (res.connected) checkList.push("connected");
+        if (res.correct) checkList.push("correct");
+        if (res.connected10) checkList.push("connected10");
+        if (res.prestop10) checkList.push("prestop10");
+        if (res.levels) {
+          checkList.push("levels");
+          this.qfhdj = String(res.levels);
+        } else {
+          this.qfhdj = "";
+        }
+        this.date = res.time;
+        this.jg = String(res.intervals);
+        this.checkList = checkList;
+        this.getFengji(res.windturbineid);
+      }
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.dataDisposeBox {
+  height: 100%;
+  .dataBox {
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+    width: 100%;
+    height: 100%;
+
+    .l {
+      width: 20%;
+      height: 100%;
+      .el-tree {
+        height: 100%;
+      }
+    }
+    .r {
+      width: 80%;
+      height: 100%;
+    }
+  }
+}
+</style>
+<style lang="less">
+.dataDisposeBox {
+  .el-checkbox__input {
+    display: inline-block;
+  }
+  .el-checkbox__inner {
+    position: absolute;
+    top: calc(50% - 7px);
+  }
+  .el-checkbox__label {
+    height: 100%;
+    display: flex;
+    justify-content: start;
+    align-items: center;
+  }
+}
+</style>

+ 75 - 0
src/views/totalCurve/index.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="totalCurveBox">
+    <el-tabs type="border-card" v-model="activeTab">
+      <el-tab-pane label="数据预处理" name="dataDispose">
+        <DataDispose />
+      </el-tab-pane>
+      <el-tab-pane label="功率曲线拟合" name="totalCurve">
+        <Chart v-if="activeTab === 'totalCurve'" />
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script>
+import DataDispose from "./dataDispose.vue";
+import Chart from "./chart.vue";
+
+export default {
+  components: {
+    DataDispose,
+    Chart,
+  },
+  data() {
+    return {
+      activeTab: "dataDispose",
+    };
+  },
+  created() {},
+  methods: {},
+};
+</script>
+<style lang="less" scoped>
+.totalCurveBox {
+  width: 100%;
+  height: 100%;
+  .el-tabs {
+    width: 100%;
+    height: 100%;
+    background: rgb(4, 12, 11);
+    border-color: #333;
+  }
+}
+</style>
+
+<style lang="less">
+.totalCurveBox {
+  .el-tabs--border-card > .el-tabs__header {
+    background: rgb(4, 12, 11);
+  }
+
+  .el-tabs--border-card > .el-tabs__content {
+    height: 96%;
+  }
+
+  .el-tab-pane {
+    height: 100%;
+  }
+
+  .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
+    color: rgb(5, 187, 76);
+    background: linear-gradient(
+      to top,
+      rgba(5, 187, 76, 0.5),
+      rgba(5, 187, 76, 0)
+    );
+    border: 0.093vh solid #05bb4c;
+  }
+
+  .el-tabs--border-card
+    > .el-tabs__header
+    .el-tabs__item:not(.is-disabled):hover {
+    color: rgb(5, 187, 76);
+  }
+}
+</style>