Riku
2025-07-13 4b275f2093954cc58bbc23e4fc67e67d6fe81c0b
src/model/SatelliteGrid.js
@@ -1,3 +1,4 @@
import { reactive } from 'vue';
import calculate from '@/utils/map/calculate';
import gridMapUtil from '@/utils/map/grid';
import { map, onMapMounted } from '@/utils/map/index_old';
@@ -15,17 +16,16 @@
  }
  gridGroupId;
  // 默认地图网格相关对象
  mapViews;
  gridState;
  gridDataDetail;
  infoMap = new Map();
  // 地图网格对象Map结构,存储对应key下的网格对象、网格坐标信息
  mapViewsMap = new Map();
  // 地图网格对象的参数状态
  gridStateMap = new Map();
  // 网格数据Map结构,存储对应key下的网格监测数据信息
  gridDataDetailMap = new Map();
@@ -273,7 +273,7 @@
      map.remove(lastGridViews);
    }
    map.add(resGridViews);
    // map.setFitView(resGridViews);
    map.setFitView(resGridViews);
    return { resGridViews, pointsRes };
  }
@@ -288,13 +288,20 @@
  // 绘制网格遥感数据值和网格颜色
  drawGrid({
    mapViews,
    gridState,
    data,
    grid = { useCustomColor: false, style: { opacity: 1, zIndex: 11 } },
    grid = {
      useCustomColor: false,
      style: { opacity: 1, zIndex: 11, isMixGridHighlight: false }
    },
    dataTxt = { isShow: false, useCustomColor: false, useColor: false },
    rankTxt = { isShow: false }
  }) {
    // 确定绘制的网格组及其参数对象
    const _mapViews = mapViews ? mapViews : this.mapViews;
    this.gridDataDetail = data;
    const _gridState = gridState ? gridState : this.gridState;
    // 根据网格数据绘制对应的网格
    const { resGridViews, pointsRes } = this.drawColor({
      gridViews: _mapViews.gridViews,
      points: _mapViews.points,
@@ -303,10 +310,17 @@
      customColor: grid.useCustomColor,
      style: grid.style
    });
    // 保存地图网格图形对象和经纬度对象
    _mapViews.lastGridViews = resGridViews;
    _mapViews.lastPoints = pointsRes;
    // 更新网格状态参数
    _gridState.showGrid = true;
    _gridState.showGridCustomColor = false;
    _gridState.gridOpacityValue = grid.style.opacity;
    _gridState.gridZIndex = grid.style.zIndex;
    _gridState.highlightFusionGrid = grid.style.isMixGridHighlight;
    // 数据标记
    // 绘制数据文本
    const { textViews: dtv } = this.drawDataText(
      _mapViews.lastPoints,
      data,
@@ -315,7 +329,12 @@
      dataTxt.useColor
    );
    _mapViews.dataTxt = dtv;
    // 更新数据文本状态参数
    _gridState.showData = dataTxt.isShow;
    _gridState.showDataColor = dataTxt.useColor;
    _gridState.showDataCustomColor = dataTxt.useCustomColor;
    // 绘制排名文本
    const { textViews: rtv } = this.drawRankText(
      _mapViews.lastPoints,
      data,
@@ -323,6 +342,8 @@
      _mapViews.rankLayer
    );
    _mapViews.rankTxt = rtv;
    // 更新排名文本状态参数
    _gridState.showRank = rankTxt.isShow;
    if (dataTxt.isShow) {
      map.add(_mapViews.dataTxt);
@@ -349,13 +370,17 @@
  drawTagGrid({ tag, data, grid, dataTxt, rankTxt, extData }) {
    if (!this.mapViewsMap.has(tag)) {
      const newMapViews = this._createNewMapViews({ extData });
      this.infoMap.set(tag, extData);
      const newGridState = this._createNewGridState({ extData });
      this.mapViewsMap.set(tag, newMapViews);
      map.on('zoomend', newMapViews.mapZoomEvent);
      this.gridStateMap.set(tag, newGridState);
      this.gridDataDetailMap.set(tag, data);
    }
    const _mapViews = this.mapViewsMap.get(tag);
    const _gridState = this.gridStateMap.get(tag);
    this.drawGrid({
      mapViews: _mapViews,
      gridState: _gridState,
      data,
      grid,
      dataTxt,
@@ -363,6 +388,10 @@
    });
  }
  /**
   * 根据标签删除对应的网格,同时移除地图缩放事件等
   * @param {*} tags 网格标签数组
   */
  deleteTagGrid(tags) {
    this.changeVisibility({
      tags,
@@ -371,68 +400,66 @@
      showRankTxt: false
    });
    tags.forEach((t) => {
      const { mapZoomEvent } = this.mapViewsMap.get(t);
      map.off('zoomend', mapZoomEvent);
      this.mapViewsMap.delete(t);
      this.gridDataDetailMap.delete(t);
      this.gridStateMap.delete(t);
    });
  }
  // 调整各类地图覆盖物的可见性
  changeVisibility({ tags = [], showGridViews, showDataTxt, showRankTxt }) {
    let { _mapViewsList } = this._getMapViews(...tags);
    let { _mapViewsList, _gridStateList } = this._getMapViews(...tags);
    if (showGridViews != undefined) {
      if (showGridViews) {
        // map.add(this.mapViews.lastGridViews);
        _mapViewsList.forEach((v) => {
        _mapViewsList.forEach((v, i) => {
          if (v.lastGridViews) {
            map.add(v.lastGridViews);
            v.show = true;
            _gridStateList[i].showGrid = true;
          }
        });
      } else {
        // map.remove(this.mapViews.lastGridViews);
        _mapViewsList.forEach((v) => {
        _mapViewsList.forEach((v, i) => {
          if (v.lastGridViews) {
            map.remove(v.lastGridViews);
            v.show = false;
            _gridStateList[i].showGrid = false;
            _gridStateList[i].showHeatMap = false;
          }
        });
      }
    }
    if (showDataTxt != undefined) {
      if (showDataTxt) {
        // map.add(this.mapViews.dataTxt);
        _mapViewsList.forEach((v) => {
        _mapViewsList.forEach((v, i) => {
          if (v.dataTxt) {
            map.add(v.dataTxt);
            v.show = true;
            _gridStateList[i].showData = true;
          }
        });
      } else {
        // map.remove(this.mapViews.dataTxt);
        _mapViewsList.forEach((v) => {
        _mapViewsList.forEach((v, i) => {
          if (v.dataTxt) {
            map.remove(v.dataTxt);
            v.show = false;
            _gridStateList[i].showData = false;
          }
        });
      }
    }
    if (showRankTxt != undefined) {
      if (showRankTxt) {
        // map.add(this.mapViews.rankTxt);
        _mapViewsList.forEach((v) => {
        _mapViewsList.forEach((v, i) => {
          if (v.rankTxt) {
            map.add(v.rankTxt);
            v.show = true;
            _gridStateList[i].showRank = true;
          }
        });
      } else {
        // map.remove(this.mapViews.rankTxt);
        _mapViewsList.forEach((v) => {
        _mapViewsList.forEach((v, i) => {
          if (v.rankTxt) {
            map.remove(v.rankTxt);
            v.show = false;
            _gridStateList[i].showRank = false;
          }
        });
      }
@@ -440,9 +467,11 @@
  }
  changeGridOpacity({ tag, isOpacity, opacityValue }) {
    let { _mapViewsList } = tag ? this._getMapViews(tag) : this._getMapViews();
    let { _mapViewsList, _gridStateList } = tag
      ? this._getMapViews(tag)
      : this._getMapViews();
    _mapViewsList.forEach((v) => {
    _mapViewsList.forEach((v, i) => {
      if (v.lastGridViews) {
        v.lastGridViews.forEach((e) => {
          e.setOptions({
@@ -454,6 +483,7 @@
                  : 0.7
          });
        });
        _gridStateList[i].gridOpacityValue = opacityValue;
      }
    });
  }
@@ -466,19 +496,26 @@
    zIndex,
    isMixGridHighlight
  }) {
    let { _mapViewsList, _gridDataDetailList } = this._getMapViews(...tags);
    let { _mapViewsList, _gridDataDetailList, _gridStateList } =
      this._getMapViews(...tags);
    if (_mapViewsList.length == _gridDataDetailList.length) {
      _mapViewsList.forEach((v, i) => {
        if (v.lastGridViews) {
          if (useCustomColor != undefined) v.useCustomColor = useCustomColor;
          const lastGridDataDetail = _gridDataDetailList[i];
          if (v.useCustomColor) {
          const _gridState = _gridStateList[i];
          if (useCustomColor != undefined)
            _gridState.showGridCustomColor = useCustomColor;
          if (useCustomColor) {
            gridMapUtil.drawGridColorCustom(
              v.lastGridViews,
              lastGridDataDetail,
              factorName ? factorName : this.selectedFactorType.name
            );
          } else {
            if (opacity != undefined) _gridState.gridOpacityValue = opacity;
            if (zIndex != undefined) _gridState.gridZIndex = zIndex;
            if (isMixGridHighlight != undefined)
              _gridState.highlightFusionGrid = isMixGridHighlight;
            gridMapUtil.drawGridColor(
              v.lastGridViews,
              lastGridDataDetail,
@@ -576,84 +613,6 @@
   * 重叠的网格进行监测数据均值计算并重新计算对应颜色,形成新的一组融合网格
   * @param {Array} tags 需要融合的网格标签,当为空时,默认融合所有网格
   */
  mixGrid({ tags, isMixGridHighlight = true }) {
    tags.sort((a, b) => {
      return a < b ? -1 : 1;
    });
    const mixTag = tags.join('-');
    if (this.mapViewsMap.has(mixTag)) {
      this.changeVisibility({
        tags: [mixTag],
        showGridViews: true
      });
      this.changeGridColor({ tags: [mixTag], isMixGridHighlight });
    } else {
      // const mixMapViews = this._createNewMapViews();
      // 根据标签tag,获取对应多组网格数据
      let { _gridDataDetailList } = this._getMapViews(...tags);
      const _dataMap = new Map();
      // 将每组每个网格数据按照网格编号进行分类,相同网格的数组归集至一起
      _gridDataDetailList.forEach((list) => {
        list.forEach((gdd) => {
          if (!_dataMap.has(gdd.cellId)) {
            _dataMap.set(gdd.cellId, {
              source: [],
              res: {}
            });
          }
          _dataMap.get(gdd.cellId).source.push(gdd);
        });
      });
      // 计算每个网格下的数据均值
      const resGridDataDetail = [];
      _dataMap.forEach((v, k) => {
        let total = 0,
          count = v.source.length;
        v.source.forEach((s) => {
          total += s.pm25;
        });
        v.res = {
          isMixData: true,
          groupId: v.source[0].groupId,
          cellId: v.source[0].cellId,
          pm25: count == 0 ? null : Math.round((total / count) * 10) / 10,
          originData: v.source
        };
        // 数据量超过1个时,表明该网格数据是融合的,展示高亮的样式
        if (count > 1) {
          v.res.gridStyle = {
            strokeWeight: 2,
            strokeColor: '#23dad1'
          };
        }
        resGridDataDetail.push(v.res);
      });
      // 重新按照监测数据排序并标记排名
      resGridDataDetail.sort((a, b) => {
        return b.pm25 - a.pm25;
      });
      resGridDataDetail.forEach((gdd, i) => {
        gdd.rank = i + 1;
      });
      this.drawTagGrid({
        tag: mixTag,
        data: resGridDataDetail,
        grid: {
          style: {
            isMixGridHighlight
          }
        },
        extData: {
          name: `走航融合 - ${mixTag}`,
          type: 1
        }
      });
    }
    return mixTag;
  }
  mixGrid2({ tags, isMixGridHighlight = true, gridDataDetailList }) {
    tags.sort((a, b) => {
      return a < b ? -1 : 1;
@@ -693,110 +652,11 @@
    return mixTag;
  }
  /**
   * 绘制热力图网格
   * @param {string} tag
   */
  drawHeatGrid(tag) {
    if (!this.mapViewsMap.has(tag) || !this.gridDataDetailMap.has(tag)) {
      return;
    }
    const heatTag = `heat-${tag}`;
    if (this.mapViewsMap.has(heatTag)) {
      this.changeVisibility({
        tags: [heatTag],
        showGridViews: true
      });
    } else {
      const _mapViews = this.mapViewsMap.get(tag);
      const _gridDataDetail = this.gridDataDetailMap.get(tag);
      // const groupId = _gridDataDetail[0].groupId;
      // const cellId = _gridDataDetail.cellId;
      const originCellIdList = _gridDataDetail.map((v) => v.cellId);
      let headGridDataDetailList = [];
      const width = 120;
      const height = 90;
      const eachwidth = 10;
      const eachheight = 10;
      const searchLength = 3;
      const _dataMap = new Map();
      _gridDataDetail.forEach((gdd) => {
        const searchRes = this.search(
          gdd,
          width,
          height,
          eachwidth,
          eachheight,
          searchLength
        );
        if (searchRes.find((v) => v.cellId == 1670)) {
          console.log();
        }
        searchRes.forEach((e) => {
          if (originCellIdList.indexOf(e.cellId) == -1) {
            if (!_dataMap.has(e.cellId)) {
              _dataMap.set(e.cellId, {
                source: [],
                res: {}
              });
            }
            _dataMap.get(e.cellId).source.push(e);
          }
        });
      });
      _dataMap.forEach((v, k) => {
        let total = 0,
          count = v.source.length;
        v.source.forEach((s) => {
          total += s.pm25;
        });
        v.res = {
          isHeatData: true,
          groupId: v.source[0].groupId,
          cellId: v.source[0].cellId,
          pm25: count == 0 ? null : Math.round((total / count) * 10) / 10,
          originData: v.source
        };
        headGridDataDetailList.push(v.res);
      });
      headGridDataDetailList = headGridDataDetailList.concat(_gridDataDetail);
      // 重新按照监测数据排序并标记排名
      headGridDataDetailList.sort((a, b) => {
        return b.pm25 - a.pm25;
      });
      headGridDataDetailList.forEach((gdd, i) => {
        gdd.rank = i + 1;
      });
      this.drawTagGrid({
        tag: heatTag,
        data: headGridDataDetailList,
        // grid: {
        //   style: {
        //     isMixGridHighlight:
        //       isMixGridHighlight == undefined ? true : isMixGridHighlight
        //   }
        // },
        extData: {
          name: `走航热力图 - ${heatTag}`,
          type: 2
        }
      });
    }
    return heatTag;
  }
  drawHeatGrid2(tag, headGridDataDetailList) {
    const heatTag = `heat-${tag}`;
    if (this.gridStateMap.has(tag)) {
      this.gridStateMap.get(tag).showHeatMap = true;
    }
    if (this.mapViewsMap.has(heatTag)) {
      this.changeVisibility({
        tags: [heatTag],
@@ -935,12 +795,14 @@
  _getMapViews(...tags) {
    let _mapViewsList = [],
      _gridDataDetailList = [];
      _gridDataDetailList = [],
      _gridStateList = [];
    if (tags.length > 0) {
      tags.forEach((tag) => {
        if (this.mapViewsMap.has(tag) && this.gridDataDetailMap.has(tag)) {
          _mapViewsList.push(this.mapViewsMap.get(tag));
          _gridDataDetailList.push(this.gridDataDetailMap.get(tag));
          _gridStateList.push(this.gridStateMap.get(tag));
        }
      });
    } else {
@@ -950,16 +812,20 @@
      this.gridDataDetailMap.forEach((v) => {
        _gridDataDetailList.push(v);
      });
      if (this.mapViews && this.gridDataDetail) {
      this.gridStateMap.forEach((v) => {
        _gridStateList.push(v);
      });
      if (this.mapViews && this.gridDataDetail && this.gridState) {
        _mapViewsList.push(this.mapViews);
        _gridDataDetailList.push(this.gridDataDetail);
        _gridStateList.push(this.gridState);
      }
    }
    return { _mapViewsList, _gridDataDetailList };
    return { _mapViewsList, _gridDataDetailList, _gridStateList };
  }
  _createNewMapViews({ extData }) {
  _createNewMapViews({ tag, extData }) {
    return {
      gridViews: gridMapUtil.drawPolylines({
        points: this.mapViews.gridPoints,
@@ -968,7 +834,50 @@
      gridPoints: JSON.parse(JSON.stringify(this.mapViews.gridPoints)),
      points: JSON.parse(JSON.stringify(this.mapViews.points)),
      extData,
      show: true
      show: true,
      mapZoomEvent: () => {
        const zoomLevel = map.getZoom();
        if (zoomLevel >= 16.5) {
          this.changeGridOpacity({ tag, opacityValue: 0.1 });
        } else {
          this.changeGridOpacity({ tag, opacityValue: 1 });
        }
        // console.log('mapZoomEvent', map.getZoom());
      }
    };
  }
  _createNewGridState({ extData }) {
    return {
      // 网格名称
      name: extData.name,
      // 网格类型,0:走航网格;1:走航融合网格;2:走航热力图
      type: extData.type,
      // 网格相关参数
      showGrid: true, // 是否显示网格
      showGridCustomColor: false, // 是否显示对比色
      gridOpacityValue: 1, // 网格透明度
      gridZIndex: 11, // 网格z轴高度
      // 排名文本相关参数
      showRank: false, // 排名文本是否显示
      // 数据文本相关参数
      showData: false, // 数据文本是否显示
      showDataColor: false, // 数据文本是否使用对应监测因子的标准颜色
      showDataCustomColor: false, // 数据文本是否使用对应监测因子的对比颜色
      // 是否显示对应热力图
      showHeatMap: false,
      // 如果是融合网格,是否高亮显示重叠网格
      highlightFusionGrid: false,
      // 如果是普通的走航网格,是否显示对应的走航轨迹
      showUnderway: false,
      // 可能的自定义额外数据
      extData
    };
  }
}