zhanghua
2023-09-11 f96e393e62b4c7496f7ace44b6aa5abb69ae58df
src/views/intelligentPatrol/trendAnalysis/index.vue
@@ -1,13 +1,384 @@
<template>
  <div>趋势分析</div>
  <div style="height: 95%">
    <div class="trend-title">趋势分析</div>
    <div class="trend-analysis">
      <div class="trend-side">
        <!-- 输入区域 -->
        <div class="trend-input-area">
          <el-form ref="form" :model="search" label-width="6vw">
            <!--          <el-form-item label="类型查询">-->
            <!--            <el-select v-model="search.type" @change="searchList" placeholder="内容信息">-->
            <!--              <el-option v-for="option in categoryOptions" :key="option.value" :value="option.value" :label="option.label" ></el-option>-->
            <!--            </el-select>-->
            <!--          </el-form-item>-->
            <el-form-item class="time-area" label="时间范围">
              <el-date-picker
                @change="searchList"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                v-model="search.timeRange"
                type="datetimerange"
                value-format="yyyy-MM-dd HH:mm:ss"
              >
              </el-date-picker>
            </el-form-item>
          </el-form>
        </div>
        <!-- 数据展示 -->
        <div class="trend-data-show">
          <!-- 点位切换 -->
          <div class="trend-data-header">
            <el-button type="text" @click="tabChange(1)">高发点位</el-button>
            <el-button type="text" @click="tabChange(2)"
              >首次违规点位</el-button
            >
          </div>
          <!-- 对应数据 -->
          <div class="trend-data-main">
            <div
              class="point-item"
              v-for="item in trendAnalysisList"
              :key="item.id"
              @click="pointClick(item)"
            >
              <span class="point-name">{{ item.name }}</span>
              <span>{{ item.count }}</span>
            </div>
          </div>
        </div>
      </div>
      <div class="trend-main">
        <div class="map">
          <MyMap
            :point="point"
            :zoom="zoom"
            :mark="mark"
            @fatherMethod="fatherMethod"
          ></MyMap>
        </div>
      </div>
      <el-dialog
        title="趋势图"
        :visible.sync="echartsDialogVisible"
        :before-close="handleClose"
      >
        <div style="display: flex">
          <div style="height: 500px; width: 500px" id="echarts"></div>
          <div style="height: 500px; width: 500px" id="typeEcharts"></div>
        </div>
      </el-dialog>
    </div>
  </div>
</template>
<script>
export default {
import * as echarts from "echarts";
import basecase from "@/api/operate/basecase";
import { CATEGOTY } from "@/utils/helper";
// import MyMap from "@/components/map";
import MyMap from "@/components/map/leafletMap.vue";
}
export default {
  components: { MyMap },
  created() {
    this.searchList();
  },
  mounted() {
    // this.renderEchart();
  },
  computed: {
    categoryOptions() {
      return CATEGOTY;
    },
  },
  data() {
    return {
      echartsDateList: [],
      echartsDataList: null,
      echartsTypeList: [],
      echartsTypeDataList: null,
      echartsDialogVisible: false,
      search: {
        type: null,
        timeRange: null,
      },
      timeRangeFlag: false,
      trendAnalysisList: [],
      highFlag: true,
      echarts: null,
      pointName: null,
      point: { x: "119.27179890", y: "28.59027084" },
      mark: null,
      zoom: 13,
    };
  },
  methods: {
    fatherMethod() {
      this.echartsDialogVisible = true;
      this.$nextTick(function () {
        this.renderEchart(this.echartsDateList, this.echartsDataList);
      });
    },
    handleClose() {
      this.echartsDialogVisible = false;
    },
    renderEchart(dateTimeList, dataList) {
      if (!this.echarts) {
        this.echarts = echarts.init(document.getElementById("echarts"));
      }
      // 绘制图表
      this.echarts.setOption({
        xAxis: {
          name: "日/周",
          data: dateTimeList,
        },
        yAxis: {
          name: "报警量(次)",
        },
        series: [
          {
            data: dataList,
            type: "line",
            smooth: true,
          },
        ],
      });
      let typeEcharts = echarts.init(document.getElementById("typeEcharts"));
      let option = {
        series: this.echartsTypeDataList.map(function (data, idx) {
          return {
            type: "pie",
            radius: [20, 60],
            left: "center",
            width: 400,
            itemStyle: {
              borderColor: "#fff",
              borderWidth: 1,
            },
            label: {
              alignTo: "edge",
              formatter: "{name|{b}}\n{count|{c} 件}",
              minMargin: 5,
              edgeDistance: 10,
              lineHeight: 15,
              rich: {
                time: {
                  fontSize: 10,
                  color: "#999",
                },
              },
            },
            labelLine: {
              length: 5,
              length2: 0,
              maxSurfaceAngle: 80,
            },
            data: data,
          };
        }),
      };
      let data = [];
      this.echartsTypeDataList.forEach((item) => {
        data.push({
          name: item.name,
          value: item.count,
        });
      });
      typeEcharts.setOption({
        series: [
          {
            type: "pie",
            radius: [20, 60],
            left: "center",
            width: 400,
            itemStyle: {
              borderColor: "#fff",
              borderWidth: 1,
            },
            label: {
              alignTo: "edge",
              formatter: "{name|{b}}\n{value|{c} 件}",
              minMargin: 5,
              edgeDistance: 5,
              lineHeight: 15,
              rich: {
                time: {
                  fontSize: 10,
                  color: "#999",
                },
              },
            },
            labelLine: {
              length: 15,
              length2: 0,
              maxSurfaceAngle: 80,
            },
            data: data,
            // labelLayout: function (params) {
            //   const isLeft = params.labelRect.x < typeEcharts.getWidth() / 2;
            //   const points = params.labelLinePoints;
            //   // Update the end point.
            //   points[2][0] = isLeft
            //     ? params.labelRect.x
            //     : params.labelRect.x + params.labelRect.width;
            //   return {
            //     labelLinePoints: points,
            //   };
            // },
            // data: this.echartsTypeDataList,
          },
        ],
      });
    },
    async searchList() {
      const [startTime, endTime] = this.search.timeRange ?? [null, null];
      const trendAnalysisParam = {
        startTime,
        endTime,
        type: this.search.type,
      };
      this.trendAnalysisList = this.highFlag
        ? await basecase.getTrendAnalysisData(trendAnalysisParam)
        : await basecase.getFirstTrendAnalysisData(trendAnalysisParam);
    },
    tabChange(params) {
      this.highFlag = params === 1;
      this.searchList();
    },
    pointClick(data) {
      this.pointName = data.name;
      this.point = {
        x: data.longitude,
        y: data.latitude,
      };
      this.zoom = 18;
      this.mark = { title: data.address };
      const [startTime, endTime] = this.search.timeRange ?? [null, null];
      basecase
        .getPointTrendAnalysisData({
          pointId: data.id,
          startTime: startTime,
          endTime: endTime,
        })
        .then((res) => {
          // const countList = res.map(item => +item.count);
          this.echartsDataList = [];
          this.echartsDateList = [];
          res.timeList.forEach((item) => {
            this.echartsDataList.push(item.count);
            this.echartsDateList.push(item.dateTime);
          });
          this.echartsTypeDataList = res.typeList;
          // this.echartsTypeDataList = [];
          // this.echartsTypeList = [];
          // res.typeList.forEach((item) => {
          //   this.echartsTypeDataList.push(item.count);
          //   this.echartsTypeList.push(item.name);
          // });
          // this.renderEchart(countList);
        })
        .catch((err) => this.$message.error(err));
    },
  },
};
</script>
<style>
<style lang="scss" scoped>
.trend-title {
  color: #4b9bb7;
  line-height: 40px;
  font-size: 26px;
  text-align: left;
  margin-left: 20px;
}
.trend-analysis {
  height: 100%;
  padding: 10px 0px;
  color: #4b9bb7;
  display: flex;
</style>
  .trend-side {
    width: 30vw;
    text-align: left;
    height: 100%;
    // border: 1px solid #09152f;
    .trend-input-area {
      display: flex;
      flex-direction: column;
      padding: 0 2vw;
      & > span {
        line-height: 40px;
      }
      ::v-deep .el-form {
        .el-form-item__label {
          color: #4b9bb7;
        }
      }
    }
    .trend-data-show {
      width: 100%;
      line-height: 40px;
      .trend-data-header {
        display: flex;
        .el-button {
          flex: 1;
          // border: 2px solid #09152f;
        }
        .el-button + .el-button {
          margin: 0;
        }
      }
      .trend-data-main {
        .point-item {
          display: flex;
          padding: 0 2vw;
          justify-content: space-between;
          .point-name {
            cursor: pointer;
            color: #66b1ff;
          }
        }
      }
    }
  }
  .trend-main {
    flex: 1;
    // border: 1px solid #09152f;
    display: flex;
    margin-left: 20px;
    .trend-main-echarts {
      width: 500px;
      height: 400px;
    }
  }
  // .trend-footer {
  //   ::v-deep .el-range-input {
  //     // background-color: #09152f;
  //   }
  // }
}
.map {
  height: 100%;
  width: 98%;
}
</style>