<template>
  <div id="noise">
    <div class="side-area">
      <Title text="设备列表"></Title>
      <ShadowContainer class="short-container">
        <div class="monitor-list">
          <div
            :class="['noise-monitor', activeIndex == index ? 'active' : '']"
            v-for="(monitor, index) in noiseMonitors"
            :key="index"
            @click="changeMonitor(monitor, index)"
          >
            <i class="iconfont icon-yangchenzaoyin"></i>
            {{ monitor.device_name }} / {{ monitor.device_no }}
          </div>
        </div>
      </ShadowContainer>
      <Title text="设备总览"></Title>
      <ShadowContainer class="short-container">
        <div
          style="
            display: flex;
            height: 100%;
            flex-wrap: wrap;
            align-items: center;
            justify-content: center;
            flex-direction: column;
          "
        >
          <div style="display: flex">
            <div class="chart-container">
              <div ref="deviceChart" id="device-chart"></div>
              <div class="title">
                <div class="main-title">
                  {{ deviceTotal }}
                </div>
                <div class="sub-title">总数</div>
              </div>
            </div>
            <div class="chart-legends">
              <div
                v-for="(legend, index) in pieChartData"
                :key="index"
                :style="{
                  color: legend.name == '在线总数' ? '#18D7B9' : '#FEBA01',
                }"
              >
                <span
                  class="rect"
                  :style="{
                    background:
                      legend.name == '在线总数' ? '#18D7B9' : '#FEBA01',
                  }"
                ></span>
                {{ legend.name }} {{ legend.value }}
              </div>
            </div>
          </div>
        </div>
      </ShadowContainer>
      <Title text="近30日噪音"></Title>
      <ShadowContainer class="short-container">
        <div
          style="
            display: flex;
            height: 100%;
            flex-wrap: wrap;
            align-items: center;
            justify-content: center;
            flex-direction: column;
          "
        >
          <div style="display: flex">
            <div class="chart-container">
              <div ref="noiseChart" id="noise-chart"></div>
              <div class="title">
                <div class="sub-title">近30日</div>
                <div class="sub-title">噪音情况</div>
              </div>
            </div>
            <div class="chart-legends">
              <div
                v-for="(legend, index) in noiseData"
                :key="index"
                :style="{
                  color: legend.name == '达标' ? '#18D7B9' : '#FF754C',
                }"
              >
                <span
                  class="rect"
                  :style="{
                    background: legend.name == '达标' ? '#18D7B9' : '#FF754C',
                  }"
                ></span>
                {{ legend.name }} {{ legend.value }}天
              </div>
            </div>
          </div>
        </div>
      </ShadowContainer>
    </div>
    <div class="mid-area">
      <Title text="实时监测" type="long"></Title>
      <ShadowContainer
        class="long-container"
        v-loading="loading"
        element-loading-background="rgba(0, 0, 0, 0.8)"
      >
        <div id="stats-container">
          <div class="temp">
            <div class="text">温度/℃</div>
            <div class="value" style="color: #ff6151">
              {{ currentMonitorStatis.temperature }}
            </div>
            <img class="smallcontainer" src="@/assets/noise/temp.png" alt="" />
          </div>
          <div class="humidity">
            <div class="text">湿度/%</div>
            <div class="value" style="color: #22c3ed">
              {{ currentMonitorStatis.humidity }}
            </div>
            <img
              class="smallcontainer"
              src="@/assets/noise/humidity.png"
              alt=""
            />
          </div>
          <div class="windangle">
            <div class="text">风向</div>
            <div class="value" style="color: #cc43b7">
              {{ currentMonitorStatis.wind_direction }}
            </div>
            <img
              class="smallcontainer"
              src="@/assets/noise/windangle.png"
              alt=""
            />
          </div>
          <div class="windspeed">
            <div class="text">风速/m/s</div>
            <div class="value" style="color: #ffc74c">
              {{ currentMonitorStatis.wind_speed }}
            </div>
            <img
              class="smallcontainer"
              src="@/assets/noise/windspeed.png"
              alt=""
            />
          </div>
          <div style="text-align: center; height: 100%; position: relative">
            <img
              src="@/assets/noise/top.png"
              style="height: 20%; vertical-align: top"
              alt=""
            />
            <div class="mid-status">
              <div class="mid-status-container">
                <div>
                  噪音
                  <span class="value">{{ currentMonitorStatis.noise }}</span>
                  <span class="unit">dB</span>
                </div>
                <div>
                  PM2.5
                  <span class="value">{{ currentMonitorStatis.pm25 }}</span
                  ><span class="unit">ug/m³</span>
                </div>
                <div>
                  PM10 <span class="value">{{ currentMonitorStatis.pm10 }}</span
                  ><span class="unit">ug/m³</span>
                </div>
              </div>
            </div>
            <img
              src="@/assets/noise/bottom.png"
              style="height: 40%; vertical-align: top"
              alt=""
            />
          </div>
        </div>
        <div class="filters">
          <div
            :class="['filter', activeType == 'pm25_data' ? 'active' : '']"
            @click="changeType('pm25_data')"
          >
            PM2.5
          </div>
          <div
            :class="['filter', activeType == 'pm10_data' ? 'active' : '']"
            @click="changeType('pm10_data')"
          >
            PM10
          </div>
          <div
            :class="[
              'filter',
              activeType == 'temperature_data' ? 'active' : '',
            ]"
            @click="changeType('temperature_data')"
          >
            温度
          </div>
          <div
            :class="['filter', activeType == 'humidity_data' ? 'active' : '']"
            @click="changeType('humidity_data')"
          >
            湿度
          </div>
          <div
            :class="['filter', activeType == 'noise_data' ? 'active' : '']"
            @click="changeType('noise_data')"
          >
            噪音
          </div>
          <div
            :class="['filter', activeType == 'wind_speed_data' ? 'active' : '']"
            @click="changeType('wind_speed_data')"
          >
            风速
          </div>
        </div>
        <div id="aqi-chart" ref="aqiChart"></div>
      </ShadowContainer>
    </div>
    <div class="side-area">
      <Title text="报警信息"></Title>
      <ShadowContainer class="long-container">
        <div class="warning-table">
          <div class="warning-table-header">
            <div class="warning-table-time">报警时间</div>
            <div class="warning-table-device">设备</div>
            <div class="warning-table-message">报警信息</div>
            <div class="warning-table-status">处理状态</div>
          </div>
          <div
            class="warning-table-list"
            v-infinite-scroll="load"
            :infinite-scroll-distance="1"
            id="table-scroll"
            @mouseenter="clearScroll"
            @mouseleave="reScroll"
          >
            <div
              class="warning-table-column"
              v-for="(column, index) in warnings"
              :key="index"
            >
              <div class="warning-table-time">{{ column.log_time }}</div>
              <div class="warning-table-device">{{ column.device_no }}</div>

              <el-tooltip
                class="item"
                effect="dark"
                :content="column.alarm_content"
                placement="top"
              >
                <div class="warning-table-message">
                  {{ column.alarm_content }}
                </div>
              </el-tooltip>
              <div
                class="warning-table-status"
                :style="{ color: column.status == 1 ? '#FFC74C' : '' }"
              >
                {{ column.status_text }}
              </div>
            </div>
          </div>
        </div>
      </ShadowContainer>
    </div>
  </div>
</template>
<script>
import {
  getDeviceTotalStatus,
  getNearMonthStatis,
  getCurrentMonitorStatis,
  getNoiseDeviceList,
  getTodayAqiLineChartData,
  getWarningMessageList,
} from "@/api/index";
export default {
  name: "Noise",
  data() {
    return {
      pieChartData: [],
      noiseData: [],
      warnings: [],
      noiseMonitors: [],
      classOption: {
        singleHeight: 36,
      },
      currentMonitorStatis: {},
      aqiLineChartData: [],
      activeIndex: 0,
      totalData: {},
      activeType: "pm25_data",
      lineChart: null,
      page: 1,
      loading: false,
      deviceTotal: 0,
      interval1: null,
    };
  },
  computed: {},
  methods: {
    computedPercentage(value, max) {
      return Number(
        Number(Number(Number(value) / Number(max)) * 100).toFixed(2)
      );
    },
    getTime(ts) {
      let date = new Date(ts);
      let year = date.getFullYear();
      let month = date.getMonth() + 1;
      let day = date.getDate();
      month = month > 9 ? month : "0" + month;
      day = day < 10 ? "0" + day : day;
      let today = year + "-" + month + "-" + day;

      let hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
      let min =
        date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
      let sec =
        date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
      return `${today} ${hour}:${min}:${sec}`;
    },
    renderDeviceChart() {
      const pieData = [...this.pieChartData];
      const chart = this.$echarts.init(this.$refs.deviceChart);
      let total = 0;
      pieData.map((item) => {
        total += item.value;
      });
      this.deviceTotal = total;
      const option = {
        tooltip: {
          appendToBody: true,
          trigger: "item",
        },
        series: [
          {
            type: "pie",
            radius: ["58%", "70%"],
            avoidLabelOverlap: false,
            itemStyle: {
              borderRadius: 20,
              borderWidth: 4,
            },
            label: {
              show: false,
              position: "center",
            },

            data: pieData.map((item) => {
              return {
                ...item,
                itemStyle: {
                  color: item.name == "在线总数" ? "#18D7B9" : "#FEBA01",
                },
              };
            }),
          },
        ],
      };
      chart.setOption(option);
      this.$nextTick(() => {
        // 解决echarts图表放大溢出父容器
        const resizeOb = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.$echarts.getInstanceByDom(entry.target).resize();
          }
        });
        resizeOb.observe(document.getElementById("device-chart"));
      });
    },
    renderNoiseChart() {
      const chartData = [...this.noiseData];
      const chart = this.$echarts.init(this.$refs.noiseChart);
      const option = {
        tooltip: {
          appendToBody: true,
          trigger: "item",
        },

        series: [
          {
            type: "pie",
            radius: ["58%", "70%"],
            avoidLabelOverlap: false,
            itemStyle: {
              borderRadius: 20,
              borderWidth: 4,
            },
            label: {
              show: false,
              position: "center",
            },

            data: chartData.map((item) => {
              return {
                ...item,
                itemStyle: {
                  color: item.name == "达标" ? "#18D7B9" : "#FF754C",
                },
              };
            }),
          },
        ],
      };
      chart.setOption(option);
      this.$nextTick(() => {
        // 解决echarts图表放大溢出父容器
        const resizeOb = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.$echarts.getInstanceByDom(entry.target).resize();
          }
        });
        resizeOb.observe(document.getElementById("noise-chart"));
      });
    },
    renderAQIChart() {
      const xAxisData = this.aqiLineChartData.map((item) => {
        return item.hour;
      });
      const yAxisData = this.aqiLineChartData.map((item) => {
        return item.value;
      });
      const chart = this.$echarts.init(this.$refs.aqiChart);
      this.lineChart = chart;
      const option = {
        color: ["#5E97F6"],
        grid: {
          top: 30,
          bottom: 30,
          left: 30,
          right: 30,
        },
        tooltip: {
          appendToBody: true,
          trigger: "axis",
        },
        xAxis: {
          type: "category",
          data: xAxisData,
          axisTick: { show: false },
          axisLabel: {
            fontSize: "12",
            color: "#c6def9",
          },
        },
        yAxis: {
          type: "value",
          axisLabel: {
            fontSize: "12",
            color: "#c6def9",
          },
          splitNumber: 4,
          splitLine: {
            lineStyle: {
              color: "rgba(95, 120, 144, 0.4)",
            },
          },
        },
        series: [
          {
            data: yAxisData,
            type: "line",
            smooth: true,
            areaStyle: {
              color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: "#5E97F6",
                },
                {
                  offset: 1,
                  color: "rgba(0,0,0,0)",
                },
              ]),
            },
          },
        ],
      };
      chart.setOption(option);
      this.$nextTick(() => {
        // 解决echarts图表放大溢出父容器
        const resizeOb = new ResizeObserver((entries) => {
          for (const entry of entries) {
            this.$echarts.getInstanceByDom(entry.target).resize();
          }
        });
        resizeOb.observe(document.getElementById("aqi-chart"));
      });
    },
    formatText(value, text) {
      return String(text);
    },

    getNoiseData() {
      getDeviceTotalStatus({ top_cat: 9 }).then((res) => {
        this.pieChartData = res.data;
        this.renderDeviceChart();
      });
      getNearMonthStatis({
        start_log_time: this.getTime(new Date().getTime() - 2592000000),
        end_log_time: this.getTime(new Date().getTime()),
      }).then((res) => {
        this.noiseData = res.data.noise_data;
        this.renderNoiseChart();
      });
      getTodayAqiLineChartData().then((res) => {
        this.totalData = res.data;
        this.aqiLineChartData = res.data.pm25_data;
        this.$nextTick(() => {
          this.renderAQIChart();
        });
      });
      getNoiseDeviceList({ top_cat: 9 }).then((res) => {
        this.noiseMonitors = res.data;
        if (res.data.length > 0) {
          this.changeMonitor(res.data[0], 0);
        }
      });
    },
    changeMonitor(monitor, index) {
      this.loading = true;
      this.activeIndex = index;
      getCurrentMonitorStatis({ device_id: monitor.id }).then((res) => {
        this.loading = false;
        this.currentMonitorStatis = res.data;
      });
    },
    changeType(type) {
      this.activeType = type;
      this.lineChart.dispose();
      this.aqiLineChartData = this.totalData[`${type}`];
      this.$nextTick(() => {
        this.renderAQIChart();
      });
    },
    load() {
      if (this.warnings.length == this.page * 10) {
        getWarningMessageList({
          page: this.page + 1,
          start_log_time: this.getTime(new Date().getTime() - 2592000000),
          end_log_time: this.getTime(new Date().getTime()),
        }).then((res) => {
          this.page += 1;
          this.warnings = [...this.warnings, ...res.data.data];
        });
      } else if (this.warnings.length == 0) {
        getWarningMessageList({
          start_log_time: this.getTime(new Date().getTime() - 2592000000),
          end_log_time: this.getTime(new Date().getTime()),
          page: 1,
        }).then((res) => {
          this.page = 1;
          this.warnings = res.data.data;
          this.$nextTick(() => {
            const element = document.getElementById("table-scroll");
            this.autoScroll(1, 50, 1500, element);
          });
        });
      }
    },
    autoScroll(stepLength, speed, delay, element) {
      var that = this;
      function start() {
        that.interval1 = setInterval(scrolling, speed);
        element.scrollTop += stepLength;
      }
      function scrolling() {
        var sTop = element.scrollTop;
        element.scrollTop += stepLength;
        if (
          sTop === element.scrollTop ||
          sTop == 0 ||
          element.scrollTop === element.scrollHeight - element.offsetHeight
        ) {
          element.scrollTop = 0;
          clearInterval(that.interval1);
          that.timeout1 = setTimeout(start, delay);
        }
      }
      if (element.offsetHeight !== element.scrollHeight) {
        // 元素内容没有溢出时，不触发
        that.timeout1 = setTimeout(start, delay);
      }
    },
    clearScroll() {
      clearInterval(this.interval1);
      clearTimeout(this.timeout1);
    },
    reScroll() {
      this.$nextTick(() => {
        const element = document.getElementById("table-scroll");
        this.autoScroll(1, 50, 1500, element);
      });
    },
  },
  mounted() {
    this.getNoiseData();
  },
};
</script>
<style lang="less" scoped>
#noise {
  padding: 12px 20px;
  display: flex;
  justify-content: space-between;
  padding-bottom: 0;
  height: calc(100% - 24px);
  .side-area {
    width: 25%;
    min-width: 400px;
  }
  .mid-area {
    width: 50%;
    margin: 0 12px;
  }
}

#device-chart,
#noise-chart {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  background: url("@/assets/chart.png") no-repeat;
  background-size: 50% 50%;
  background-position: center center;
}
.i-type {
  display: flex;
  font-size: 14px;
  color: #c6def9;
  padding: 3px;
  .slider {
    width: 70%;
    vertical-align: top;
  }
  .i-type-name,
  .i-type-count {
    width: 15%;
    vertical-align: top;
    line-height: 30px;
    text-align: right;
    span {
      font-size: 16px;
    }
  }
  .i-type-count {
    width: 12%;
  }
  .i-type-name {
    padding-right: 12px;
  }
}
.el-progress {
  padding: 12px 0;
}
#aqi-chart {
  width: 100%;
  height: calc(100% / 3 - 44px);
}
.monitor {
  display: flex;
  justify-content: space-between;
  .lt-status,
  .rt-status {
    width: 20%;
    text-align: center;
  }
}
.el-divider {
  opacity: 0.3;
  background: #7e8ed4;
}
::v-deep .el-progress-circle__track {
  stroke: #183c6b;
}
::v-deep .el-progress__text {
  font-size: 16px;
  color: #c6def9 !important;
}
::v-deep .el-progress-circle {
  width: 88px !important;
  height: 88px !important;
}
.rt-single-status {
  display: flex;
  padding: 7px 0;
  .left-des {
    text-align: center;
    width: 64px;
    div {
      margin-bottom: 12px;
      font-size: 16px;
      color: #22c3ed;
    }
  }
  img {
    width: 40px;
    vertical-align: top;
  }
  .rt-value {
    width: calc(100% - 64px);
    font-size: 12px;
    color: #c6def9;
    opacity: 0.8;
    line-height: 72px;
    span {
      font-size: 26px;
      margin-right: 12px;
    }
  }
}
.status-unit {
  font-size: 16px;
  color: #c6def9;
  text-align: center;
}
::v-deep .el-divider--horizontal {
  margin: 16px 0;
}
.mid-aqi {
  width: 60%;
}
.aqi-background {
  height: 100%;
  background: url("@/assets/noise/img_bj.png") no-repeat;
  background-size: 80%;
  background-position: 50% 15%;
  zoom: 1.2;
}
#aqi-quality-chart {
  width: 100%;
  height: 300px;
}
.aqi-level {
  transform: translateY(-80px);
}
.aqi-level-line {
  width: 80%;
  margin: 0 auto;
  display: flex;
  margin-bottom: 12px;
  & > div {
    width: calc(100% / 6);
    height: 12px;
  }
  & > div:first-child {
    border-top-left-radius: 6px;
    border-bottom-left-radius: 6px;
  }
  & > div:last-child {
    border-top-right-radius: 6px;
    border-bottom-right-radius: 6px;
  }
}
.aqi-level-text {
  width: 80%;
  display: flex;
  margin: 0 auto;
  font-size: 14px;
  color: #c6def9;
  opacity: 0.8;
  & > div {
    width: calc(100% / 6);
    height: 12px;
    text-align: center;
  }
}
.warn-title {
  border-left: 2px solid;
  padding-left: 12px;
  font-size: 14px;
  color: #c6def9;
  display: flex;
  justify-content: space-between;
  margin-bottom: 18px;
  &:nth-child(3n-2) {
    border-color: #fd175d;
  }
  &:nth-child(3n-1) {
    border-color: #ab75ff;
  }
  &:nth-child(3n) {
    border-color: #ffbb37;
  }
  .warn-text {
    width: 60%;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }
  .warn-time {
    width: 40%;
    text-align: right;
  }
}
.monitor-list {
  height: 220px;
  overflow-y: auto;
}
.noise-monitor {
  padding: 16px;
  background: rgba(44, 96, 162, 0.2);
  font-size: 14px;
  color: #c6def9;
  margin-bottom: 10px;
  img {
    width: 20px;
    vertical-align: top;
  }
  &:last-child {
    margin-bottom: 0;
  }
  &:hover {
    background: rgba(44, 96, 162, 0.5);
    color: #27acfb;
  }
  &.active {
    background: rgba(44, 96, 162, 0.5);
    color: #27acfb;
  }
}
.warp {
  width: 100%;
  height: 180px;
  overflow: hidden;
}
.overflowed {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

.warning-table {
  font-size: 14px;
  text-align: center;
  color: #c6def9;
  height: 100%;
  .warning-table-list {
    height: calc(100% - 50px);
    overflow-y: auto;
  }
  .warning-table-header {
    background: rgba(44, 96, 162, 0.2);
    display: flex;
    padding: 12px 0;
    font-weight: bold;
  }
  .warning-table-column {
    padding: 12px 0;
    background: rgba(44, 96, 162, 0.05);
    display: flex;
    &:nth-child(2n) {
      background: rgba(44, 96, 162, 0.1);
    }
    &:hover {
      background: rgba(44, 96, 162, 0.5);
    }
    .warning-table-message {
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }
  }
  .warning-table-time {
    width: 30%;
  }
  .warning-table-device,
  .warning-table-status {
    width: 20%;
  }
  .warning-table-message {
    width: 30%;
  }
}
#stats-container {
  position: relative;
  margin: 0 auto;
  max-width: 840px;
  height: calc(100% / 3 * 2);
  .text {
    color: #ffffff;
    font-size: 16px;
    text-align: center;
  }
  .value {
    font-size: 24px;
    text-align: center;
  }
  .temp {
    position: absolute;
    left: 11%;
    top: 20%;
    transform: translateX(-50%);
  }
  .humidity {
    position: absolute;
    left: 11%;
    bottom: 20%;
    transform: translateX(-50%);
  }
  .windangle {
    position: absolute;
    right: 11%;
    top: 20%;
    transform: translateX(50%);
  }
  .windspeed {
    position: absolute;
    right: 11%;
    bottom: 20%;
    transform: translateX(50%);
  }
  .mid-status {
    position: relative;
    height: calc(40% - 28px);
    font-size: 20px;
    text-align: center;
    color: #c6def9;
    border: 14px solid #888;
    width: 50%;
    margin: 0 auto;
    background: #081f3b;
    .mid-status-container {
      position: absolute;
      width: 95%;
      left: 50%;
      top: 50%;
      transform: translateX(-50%) translateY(-50%);
      line-height: 56px;
      white-space: nowrap;
      & > div {
        border-bottom: 2px solid #114e70;

        margin: 0 auto;
        &:last-child {
          border-bottom: none;
        }
      }
    }
    .unit {
      font-size: 14px;
      margin-left: 6px;
    }
    .value {
      font-size: 24px;
      margin-left: 12px;
    }
    img {
      vertical-align: top;
    }
  }
}
.filters {
  display: flex;
  justify-content: space-between;
  padding-top: 10px;
  border-top: 4px solid #114e70;
  .filter {
    font-size: 14px;
    color: rgba(198, 222, 249, 1);
    width: 120px;
    padding: 6px;
    text-align: center;
    cursor: pointer;
    background: linear-gradient(
      90deg,
      rgba(8, 36, 71, 0) 0%,
      rgba(39, 172, 251, 0.19) 49%,
      rgba(9, 37, 71, 0) 100%
    );
    &.active {
      color: #16c0ff;
    }
  }
}
::v-deep .el-loading-mask {
  position: absolute !important;
}
.short-container {
  height: calc(33% - 108px);
}
.long-container {
  height: calc(100% - 108px);
}

.chart-legends {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  width: calc(100% - 250px);
  & > div {
    padding: 0 20px;
    font-size: 14px;
    line-height: 36px;
    width: 100%;
    text-align: left;
  }
  .rect {
    width: 8px;
    height: 8px;
    display: inline-block;
    vertical-align: middle;
  }
}

.chart-container {
  position: relative;
  width: 250px;
  height: 250px;
  .title {
    position: absolute;
    top: 50%;
    left: 50%;
    text-align: center;
    transform: translateX(-50%) translateY(-50%);
    .main-title {
      font-size: 30px;
      font-weight: bold;
      color: #00fcff;
    }
    .sub-title {
      font-size: 16px;
      font-weight: bold;
      color: rgba(255, 255, 255, 0.7);
    }
  }
}
.smallcontainer {
  width: 100px !important;
  height: inherit !important;
  transform: translateY(-50%);
  vertical-align: top;
}
</style>