cjl
3 days ago ad1aceb23ab49d0cf2a9f561754bd42d0cb45f6a
雷达
1 files added
264 ■■■■■ changed files
src/views/radar/index.vue 264 ●●●●● patch | view | raw | blame | history
src/views/radar/index.vue
New file
@@ -0,0 +1,264 @@
<template>
  <div
    id="chartTableContent"
    style="width: 100%; height: 100%"
  >
  <div class="topSelect">
      <el-input-number
        v-model="high1"
        :min="0"
        :max="15000"
        label="最低高度"
        style="width: 130px; margin-left: 10px"
        controls-position="right"
      ></el-input-number>
      <el-input-number
        v-model="high2"
        :min="0"
        :max="15000"
        label="最高高度"
        style="width: 130px; margin-left: 10px"
        controls-position="right"
      ></el-input-number>
      <component
        :is="dataType"
        ref="picker"
        style="padding-left: 0; margin-left: 20px; width: 160px"
        class="select11"
        @sendPickerChild="showPickerChild"
      />
      <!--查询按钮-->
      <el-button
        class="btn1"
        @click="selectData"
      >
        查询
      </el-button>
    </div>
    <div class="pm-profile">
      <h2 >PM2.5 / PM10 垂直剖面动态演化图</h2>
      <div ref="chart" class="chart-container"></div>
      <div class="controls">
        <p>底部时间轴可拖拽,自动播放</p>
      </div>
    </div>
  </div>
</template>
<script>
import * as echarts from 'echarts'
import HourPicker from '@/components/Form/HourPicker1'
export default {
  name: 'PMProfile',
  components: {
    HourPicker
  },
  props: {
    chartData: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      chart: null,
      dataType: 'HourPicker',
      defaultData: {},
      newData: [],
      high1: 1000,
      high2: 7000,
      timeList: null,
      currentTimeIdx: 0
    };
  },
  watch: {
    select1 (nv, ov) {
      this.unit = 'FiveMinute'
    }
  },
  computed: {
    chartDataResolved() {
      return this.chartData || this.defaultData;
    }
  },
   mounted() {
     const now = new Date();
     const startTime = new Date(now.getTime() - 20 * 60 * 1000);
     const fmt = (d) => {
       const Y = d.getFullYear();
       const M = String(d.getMonth() + 1).padStart(2, '0');
       const D = String(d.getDate()).padStart(2, '0');
       const h = String(d.getHours()).padStart(2, '0');
       const m = String(d.getMinutes()).padStart(2, '0');
       const s = String(d.getSeconds()).padStart(2, '0');
       return `${Y}-${M}-${D} ${h}:${m}:${s}`;
     };
     const defaultVal = [fmt(startTime), fmt(now)];
     this.$refs.picker.value1 = defaultVal;
     this.$nextTick(() => this.selectData());
   },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose();
      this.chart = null;
    }
  },
  methods: {
    initChart() {
      const DATA = this.chartDataResolved;
      const chartEl = this.$refs.chart;
      if (!chartEl) return;
      const chartLib = this.$echarts || echarts;
      if (!chartLib || !chartLib.init) return;
      if (this.chart) {
        this.chart.dispose();
        this.chart = null;
      }
      this.chart = chartLib.init(chartEl);
      console.log(DATA);
      if (!DATA || !DATA.time || !DATA.time.length) {
        console.log(222);
        this.chart.setOption({
          graphic: {
            type: 'text',
            left: 'center',
            top: 'center',
            style: {
              text: '未查询到数据',
              fontSize: 18,
              fill: '#909399'
            }
          }
        });
        return;
      }
      this.timeList = DATA.time;
      this.currentTimeIdx = 0;
      this.chart.setOption({
        baseOption: {
          timeline: {
            axisType: 'category',
            autoPlay: true,
            playInterval: 1000,
            data: DATA.time,
            label: {
              formatter: function (s) { return s.slice(0, 5); }
            },
            checkpointStyle: { borderColor: '#fff', borderWidth: 2 },
            controlStyle: { showNextBtn: true, showPrevBtn: true }
          },
          title: { text: '', left: 'center', top: 0 },
          tooltip: {
            trigger: 'axis',
            formatter: (params) => {
              const time = this.timeList ? this.timeList[this.currentTimeIdx] : '';
              var res = '时间: ' + time + '<br>';
              params.forEach(function (p) {
                res += '<span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:' + p.color + ';margin-right:4px"></span> '
                  + p.seriesName + ': ' + p.value[0] + ' μg/m³ @ ' + p.value[1] + 'm<br>';
              });
              return res;
            }
          },
          legend: { data: ['PM2.5', 'PM10'], top: 35 },
          grid: { top: 60, bottom: 100, left: 50, right: 50 },
          xAxis: { type: 'value', name: '浓度 (μg/m³)', position: 'top', splitLine: { show: true } },
          //yAxis: { type: 'value', name: '高度 (m)',  splitLine: { show: true } },
          yAxis: { type: 'value', name: '高度 (m)', min: this.high1, max: this.high2, splitLine: { show: true } },
          series: [
            {
              name: 'PM2.5', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6,
              lineStyle: { width: 3, color: '#ef4444' }, itemStyle: { color: '#ef4444' },
              areaStyle: { color: 'rgba(239,68,68,0.2)' }, data: []
            },
            {
              name: 'PM10', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6,
              lineStyle: { width: 3, color: '#3b82f6' }, itemStyle: { color: '#3b82f6' },
              areaStyle: { color: 'rgba(59,130,246,0.2)' }, data: []
            }
          ]
        },
        options: DATA.time.map(function (time, idx) {
          return {
            title: { text: '当前时间: ' + time },
            series: [
              { data: DATA.pm25[idx] },
              { data: DATA.pm10[idx] }
            ]
          };
        })
      });
      this.chart.on('timelinechanged', (params) => {
        this.currentTimeIdx = params.currentIndex;
      });
    },
    selectData () {
      this.$request({
        url: '/historyRadar/list',
        method: 'post',
        data: {
          startTime: this.newData[0],
          endTime: this.newData[1],
          high1: this.high1,
          high2: this.high2
        }
      })
        .then((res) => {
          this.defaultData  = res.data
          this.$nextTick(() => this.initChart());
        }).catch((err) => {
        })
    },
    showPickerChild (data) {
      this.newData = data
    }
  }
};
</script>
<style scoped>
.pm-profile {
  width: 100%;
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.pm-profile h2 {
  text-align: center;
  color: #303133;
  margin: 0 0 20px 0;
  font-size: 20px;
}
.chart-container {
  width: 100%;
  height: 600px;
}
.controls {
  text-align: center;
  margin-top: 10px;
  color: #909399;
  font-size: 14px;
}
.controls p {
  margin: 0;
}
.topSelect {
  display: flex;
  margin-bottom: 20px;
  padding: 20px 15px 0 15px;
}
.select11 {
  width: 20% !important;
}
</style>