feiyu02
2025-03-28 aa75a9d46ee325f0a92e42f733aabb1f92103aeb
走航融合模块完成
已修改17个文件
已添加3个文件
1238 ■■■■ 文件已修改
src/api/gridApi.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/common/CheckButton.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/grid/GridSearch.vue 166 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list/DescriptionsList.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list/DescriptionsListItem.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/FactorLegend.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/FactorRadio.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constant/radio-options/options-jingan.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/constant/radio-options/options.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/model/GridDataDetail.js 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/model/Legend.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/model/SatelliteGrid.js 216 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/grid.js 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/historymode/HistoryMode.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realtimemode/RealtimeMode.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/underwaymix/UnderwayMixMode.vue 427 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/underwaymix/component/GridStyleTool.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/gridApi.js
@@ -150,6 +150,16 @@
    });
  },
  mixUnderwayGridData(groupId, dataIdList) {
    return $http
      .post(`air/satellite/product/underway/mix`, dataIdList, {
        params: {
          groupId
        }
      })
      .then((res) => res.data);
  },
  buildUnderwayHeatmap(groupId, gridDataDetailList, searchLength) {
    return $http
      .post(
@@ -158,7 +168,7 @@
        {
          params: {
            groupId: groupId,
            searchLength: 4
            searchLength: searchLength
          }
        }
      )
src/api/index.js
@@ -1,7 +1,7 @@
import axios from 'axios';
import { ElMessage } from 'element-plus';
const debug = false;
const debug = true;
let ip1 = 'http://47.100.191.150:9029/';
// console.log(import.meta.env);
@@ -10,8 +10,8 @@
}
if (debug) {
  // ip1 = 'http://192.168.0.110:8084/';
  ip1 = 'http://locahost:8084/';
  ip1 = 'http://192.168.0.110:8084/';
  // ip1 = 'http://locahost:8084/';
}
const $http = axios.create({
src/components.d.ts
@@ -17,6 +17,8 @@
    CoreMenu: typeof import('./components/core/CoreMenu.vue')['default']
    DataSummary: typeof import('./components/monitor/DataSummary.vue')['default']
    DataTable: typeof import('./components/monitor/DataTable.vue')['default']
    DescriptionsList: typeof import('./components/list/DescriptionsList.vue')['default']
    DescriptionsListItem: typeof import('./components/list/DescriptionsListItem.vue')['default']
    DeviceCreate: typeof import('./components/device/DeviceCreate.vue')['default']
    DeviceManage: typeof import('./components/device/DeviceManage.vue')['default']
    ElButton: typeof import('element-plus/es')['ElButton']
@@ -49,6 +51,8 @@
    ElSwitch: typeof import('element-plus/es')['ElSwitch']
    ElTable: typeof import('element-plus/es')['ElTable']
    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
    ElTabPane: typeof import('element-plus/es')['ElTabPane']
    ElTabs: typeof import('element-plus/es')['ElTabs']
    ElText: typeof import('element-plus/es')['ElText']
    FactorCheckbox: typeof import('./components/monitor/FactorCheckbox.vue')['default']
    FactorLegend: typeof import('./components/monitor/FactorLegend.vue')['default']
src/components/common/CheckButton.vue
@@ -4,17 +4,33 @@
    {{ checkValue ? activeText : inactiveText }}
  </el-button> -->
  <el-checkbox
    v-model="checkValue"
    ref="checkboxRef"
    :disabled="loading"
    :model-value="modelValue"
    @update:model-value="(e) => emits('update:modelValue', e)"
    @change="handleChange"
    border
    size="small"
    >{{ activeText }}</el-checkbox
  >
    <template #default>
      <el-space>
        <el-icon v-if="loading" class="is-loading" color="#00fff2"><Loading /></el-icon>
        {{ activeText }}
      </el-space>
    </template>
  </el-checkbox>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
// import $ from 'jquery';
const props = defineProps({
  modelValue: {
    type: Boolean
  },
  loading: {
    type: Boolean
  },
  defaultValue: {
    type: Boolean
  },
@@ -28,8 +44,9 @@
  }
});
const emits = defineEmits(['change']);
const emits = defineEmits(['change', 'update:modelValue']);
const checkboxRef = ref();
const checkValue = ref(false);
watch(
@@ -42,6 +59,44 @@
  { immediate: true }
);
watch(
  () => props.loading,
  (nV, oV) => {
    if (nV != oV) {
      // setTimeout(() => {
      //   const e1 = checkboxRef.value.$el.querySelector('.el-checkbox__input');
      //   console.log(e1);
      //   // e1.classList.toggle('is-disabled');
      //   e1.classList.toggle('checkbox__input_none');
      //   const e2 = checkboxRef.value.$el.querySelector('.el-checkbox__label');
      //   console.log(e2);
      //   e2.classList.toggle('checkbox__label_nopadding');
      // }, 500);
      // if (props.id) {
      //   console.log(
      //     checkboxRef.value.$el.querySelector('.el-checkbox__input').classList
      //   );
      //   console.log(
      //     checkboxRef.value.$el.querySelector('.el-checkbox__label').classList
      //   );
      // }
    }
  }
);
onMounted(() => {
  if (props.id) {
    console.log(
      checkboxRef.value.$el.querySelector('.el-checkbox__input').classList
    );
    console.log(
      checkboxRef.value.$el.querySelector('.el-checkbox__label').classList
    );
  }
});
function handleChange(value) {
  emits('change', value);
}
@@ -49,6 +104,7 @@
<style scoped>
.el-checkbox {
  --el-checkbox-text-color: white;
  /*--main-color: #00fff2;*/
  --main-color: #23dad1;
  --el-checkbox-checked-text-color: var(--main-color);
  --el-checkbox-checked-input-border-color: var(--main-color);
@@ -65,4 +121,12 @@
.el-checkbox__input.is-disabled + span.el-checkbox__label {
  color: var(--el-color-primary);
}
:deep(.checkbox__input_none) {
  display: none !important;
}
:deep(.checkbox__label_nopadding) {
  padding-left: 0px;
}
</style>
src/components/grid/GridSearch.vue
@@ -7,31 +7,117 @@
    width="300px"
  >
    <template #default>
      <el-form
        :inline="false"
        ref="formRef"
        label-position="right"
        label-width="100px"
      <div v-if="data">
        <DescriptionsList>
          <DescriptionsListItem
            label="网格编号"
            :content="data.gridCell.cellIndex"
          />
          <DescriptionsListItem
            label="经纬度"
            :content="data.gridCell.longitude + ', ' + data.gridCell.latitude"
          />
          <DescriptionsListItem label="四至范围" content="/" />
        </DescriptionsList>
        <el-tabs v-model="activeName" >
          <el-tab-pane label="网格数据" name="first">
            <DescriptionsList>
              <DescriptionsListItem
                label="VOC"
                :content="data.gridDataDetail.voc + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="H2S"
                :content="data.gridDataDetail.h2s + ' Î¼g/m³'"
              />
              <!-- <DescriptionsListItem label="NO" :content="data.gridDataDetail.no + ' Î¼g/m³'" /> -->
              <DescriptionsListItem
                label="NO2"
                :content="data.gridDataDetail.no2 + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="CO"
                :content="data.gridDataDetail.co + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="SO2"
                :content="data.gridDataDetail.so2 + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="O3"
                :content="data.gridDataDetail.o3 + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="PM25"
                :content="data.gridDataDetail.pm25 + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="PM10"
                :content="data.gridDataDetail.pm10 + ' Î¼g/m³'"
              />
              <DescriptionsListItem
                label="温度"
                :content="data.gridDataDetail.temperature + ' â„ƒ'"
              />
              <DescriptionsListItem
                label="湿度"
                :content="data.gridDataDetail.humidity + ' %'"
              />
              <DescriptionsListItem
                label="风速"
                :content="data.gridDataDetail.windSpeed + ' m/s'"
              />
              <DescriptionsListItem
                label="风向"
                :content="data.gridDataDetail.windDirection + ' Â°'"
              />
            </DescriptionsList>
          </el-tab-pane>
          <template v-if="data.gridDataDetail.mixData">
            <el-tab-pane
              v-for="(d, i) in data.gridDataDetail.originDataList"
              :key="i"
              :label="d.dataId"
              :name="`origin-${i}`"
      >
        <el-form-item label="网格编号:">
          <div>
            {{ data.cellIndex }}
              <DescriptionsList>
                <DescriptionsListItem label="VOC" :content="d.voc + ' Î¼g/m³'" />
                <DescriptionsListItem label="H2S" :content="d.h2s + ' Î¼g/m³'" />
                <!-- <DescriptionsListItem label="NO" :content="d.no + ' Î¼g/m³'" /> -->
                <DescriptionsListItem label="NO2" :content="d.no2 + ' Î¼g/m³'" />
                <DescriptionsListItem label="CO" :content="d.co + ' Î¼g/m³'" />
                <DescriptionsListItem label="SO2" :content="d.so2 + ' Î¼g/m³'" />
                <DescriptionsListItem label="O3" :content="d.o3 + ' Î¼g/m³'" />
                <DescriptionsListItem
                  label="PM25"
                  :content="d.pm25 + ' Î¼g/m³'"
                />
                <DescriptionsListItem
                  label="PM10"
                  :content="d.pm10 + ' Î¼g/m³'"
                />
                <DescriptionsListItem
                  label="温度"
                  :content="d.temperature + ' â„ƒ'"
                />
                <DescriptionsListItem
                  label="湿度"
                  :content="d.humidity + ' %'"
                />
                <DescriptionsListItem
                  label="风速"
                  :content="d.windSpeed + ' m/s'"
                />
                <DescriptionsListItem
                  label="风向"
                  :content="d.windDirection + ' Â°'"
                />
              </DescriptionsList>
            </el-tab-pane>
          </template>
        </el-tabs>
          </div>
        </el-form-item>
        <el-form-item label="经纬度:">
          <div>
            {{ data.longitude + ', ' + data.latitude }}
          </div>
        </el-form-item>
        <el-form-item label="PM2.5:">
          <div>
            {{ data.pm25 + ' Î¼g/m³' }}
          </div>
        </el-form-item>
        <el-form-item label="四至范围:">
          <div>/</div>
        </el-form-item>
      </el-form>
    </template>
    <template #footer> </template>
  </CardDialog>
@@ -44,21 +130,27 @@
const dialogVisible = ref(false);
const activeName = ref('first');
const data = computed(() => {
  if (gridStore.selectedGridCellAndDataDetail) {
    // const { gridCell, gridDataDetail } =
    //   gridStore.selectedGridCellAndDataDetail;
    // const res = [];
    // // å¦‚果网格数据为融合数据,则需要同步展示出原始数据
    // if (gridDataDetail.mixData) {
    // }
    return {
      cellIndex: gridStore.selectedGridCellAndDataDetail.gridCell.cellIndex,
      longitude: gridStore.selectedGridCellAndDataDetail.gridCell.longitude,
      latitude: gridStore.selectedGridCellAndDataDetail.gridCell.latitude,
      pm25: gridStore.selectedGridCellAndDataDetail.gridDataDetail.pm25
      gridCell: gridStore.selectedGridCellAndDataDetail.gridCell,
      gridDataDetail: gridStore.selectedGridCellAndDataDetail.gridDataDetail,
      extData: gridStore.selectedGridCellAndDataDetail.extData
    };
    // console.log(gridStore.selectedGridCellAndDataDetail);
    // return undefined;
    // return gridStore.selectedGridCellAndDataDetail;
  } else {
    return {
      cellIndex: '/',
      longitude: '/',
      latitude: '/',
      pm25: '/'
    };
    return undefined;
  }
});
@@ -72,3 +164,11 @@
  { deep: true }
);
</script>
<style scoped>
:deep(.el-tabs__item){
  color: rgba(221, 221, 221, 0.806);
}
:deep(.is-active){
  color: #f0ff1d;
}
</style>
src/components/list/DescriptionsList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
<template>
  <div class="title-wrapper">
    <div v-if="title" class="fy-h2">{{ title }}</div>
    <slot name="extra"></slot>
  </div>
  <table>
    <tbody>
      <slot></slot>
    </tbody>
  </table>
</template>
<script>
export default {
  props: {
    title: String
  }
};
</script>
<style scoped>
.title-wrapper {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
table {
  width: 100%;
}
</style>
src/components/list/DescriptionsListItem.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
<template>
  <tr>
    <td v-if="label" class="td-1">{{ label }}</td>
    <td v-else class="td-1"><slot name="label"></slot></td>
    <td v-if="content" class="td-2">{{ content }}</td>
    <td v-else class="td-2"><slot name="content"></slot></td>
  </tr>
</template>
<script>
export default {
  props: {
    label: String,
    content: String
  }
};
</script>
<style scoped>
tr {
  font-size: var(--el-font-size-small);
}
td {
  border: 1px solid rgba(255, 255, 255, 0.616);
  padding: 2px 6px;
}
.td-1 {
  width: 68px;
  background-color: var(--bg-color-2);
  color: white;
}
.td-2 {
  color: white;
  /* background-color: var(--el-fill-color-light); */
}
</style>
src/components/monitor/FactorLegend.vue
@@ -128,11 +128,12 @@
          ', ' +
          color[3] +
          ')';
        const { scale = 1, unit = '' } = factorUnit[name];
        legendList.push({
          color: bgColor,
          min: r[0],
          max: nextR ? nextR[0] : undefined,
          unit: factorUnit[name] ? factorUnit[name].unit : ''
          min: r[0] * scale,
          max: nextR ? nextR[0] * scale : undefined,
          unit: unit
        });
      }
src/components/monitor/FactorRadio.vue
@@ -26,7 +26,7 @@
  emits: ['change'],
  data() {
    return {
      radio: defaultOptions(TYPE0)
      radio: defaultOptions(TYPE0).value
    };
  },
  computed: {
@@ -43,7 +43,8 @@
  },
  methods: {
    handleChange(value) {
      this.$emit('change', value);
      const item = this.options.find((v) => v.value == value);
      this.$emit('change', item.value, item);
      // todo åœ°å›¾3d图像切换展示监测因子
    }
  }
src/constant/radio-options/options-jingan.js
@@ -31,4 +31,4 @@
];
// é»˜è®¤é€‰é¡¹ PM2.5
export const default1 = option1[3].value;
export const default1 = option1[3];
src/constant/radio-options/options.js
@@ -46,7 +46,7 @@
];
// é»˜è®¤é€‰é¡¹ PM2.5
export const default1 = option1[5].value;
export const default1 = option1[5];
export const option2 = [
  {
@@ -77,4 +77,4 @@
];
// é»˜è®¤é€‰é¡¹ æ¸©åº¦
export const default2 = option2[0].value;
export const default2 = option2[0];
src/main.js
@@ -1,5 +1,5 @@
import './assets/main.css';
import './lib/jquery-3.5.1.min';
// import './lib/jquery-3.5.1.min';
import { createApp } from 'vue';
import { createPinia } from 'pinia';
src/model/GridDataDetail.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
function getGridDataDetailFactorValue(gdd, factorName) {
  let value;
  switch (factorName) {
    case 'VOC':
      value = gdd.voc;
      break;
    case 'H2S':
      value = gdd.h2s;
      break;
    case 'NO':
      value = gdd.no;
      break;
    case 'NO2':
      value = gdd.no2;
      break;
    case 'CO':
      value = gdd.co;
      break;
    case 'SO2':
      value = gdd.so2;
      break;
    case 'O3':
      value = gdd.o3;
      break;
    case 'PM25':
      value = gdd.pm25;
      break;
    case 'PM10':
      value = gdd.pm10;
      break;
    case 'TEMPERATURE':
      value = gdd.temperature;
      break;
    case 'HUMIDITY':
      value = gdd.humidity;
      break;
    case 'WIND_SPEED':
      value = gdd.windSpeed;
      break;
    case 'WIND_DIRECTION':
      value = gdd.windDirection;
      break;
    default:
      value = gdd.pm25;
      break;
  }
  return Math.round(value * 10) / 10;
}
export { getGridDataDetailFactorValue };
src/model/Legend.js
@@ -10,7 +10,7 @@
  _legend_r: {
    NO: [0, 100, 200, 700, 1200, 2340],
    NO2: [0, 100, 200, 700, 1200, 2340],
    CO: [0, 5, 10, 35, 60, 90],
    CO: [0, 5000, 10000, 35000, 60000, 90000],
    H2S: [0, 150, 500, 650, 800, 1600],
    SO2: [0, 150, 500, 650, 800, 1600],
    O3: [0, 160, 200, 300, 400, 800],
@@ -164,10 +164,6 @@
    //   }
    //   max = parseInt(key)
    // }
    if (name == 'CO') {
      min *= 1000;
      max *= 1000;
    }
    return [min, max];
  },
@@ -223,9 +219,6 @@
    for (let i = 0; i < range.length; i++) {
      const d = range[i];
      let d1 = d;
      if (name == 'CO') {
        d1 *= 1000;
      }
      if (data >= d1) {
        selected = i;
      } else {
@@ -262,9 +255,6 @@
    for (let i = 0; i < range.length; i++) {
      const d = range[i];
      let d1 = d;
      if (name == 'CO') {
        d1 *= 1000;
      }
      if (data >= d1) {
        selected = i;
      } else {
src/model/SatelliteGrid.js
@@ -1,7 +1,10 @@
import calculate from '@/utils/map/calculate';
import gridMapUtil from '@/utils/map/grid';
import { map, onMapMounted } from '@/utils/map/index_old';
import { useCloned } from '@vueuse/core';
import { getGridDataDetailFactorValue } from '@/model/GridDataDetail';
import { useGridStore } from '@/stores/grid-info';
const gridStore = useGridStore();
/**
 * å«æ˜Ÿé¥æµ‹ç½‘格管理
@@ -10,6 +13,9 @@
  constructor(name) {
    this.name = name;
  }
  gridGroupId;
  // é»˜è®¤åœ°å›¾ç½‘格相关对象
  mapViews;
@@ -28,6 +34,14 @@
  firstEvent;
  events = new Map();
  selectedFactorType;
  setShowFactorType(e) {
    this.selectedFactorType = e;
    this.changeGridColor({ factorName: e.name });
    this.changeText({ factorName: e.name });
  }
  // ç»˜åˆ¶åŒºåŽ¿è¾¹ç•Œ
  drawDistrict(districtName, isNew) {
@@ -132,8 +146,7 @@
    const data = gridDataDetail.map((v, i) => {
      return {
        lnglat_GD: points[i],
        // data: v.pm25 ? (v.pm25 + 'μg/m³') : ''
        data: v.pm25 ? v.pm25 : ''
        data: getGridDataDetailFactorValue(v, this.selectedFactorType.name)
      };
    });
    // return gridMapUtil.drawGridTextLabel(data, textViews, labelsLayer, 'bottom');
@@ -143,8 +156,54 @@
      anchor: 'top-center',
      type: 'data',
      isCustomColor,
      useColor
      useColor,
      factorName: this.selectedFactorType.name
    });
  }
  changeText({ tags = [], factorName, isCustomColor, useColor, type }) {
    let { _mapViewsList, _gridDataDetailList } = this._getMapViews(...tags);
    if (_mapViewsList.length == _gridDataDetailList.length) {
      _mapViewsList.forEach((v, i) => {
        if (v.dataTxt) {
          let dataList = [];
          if (type == 'data' || type == undefined) {
            dataList.push({
              type: 'data',
              data: _gridDataDetailList[i].map((v) => {
                return {
                  data: getGridDataDetailFactorValue(
                    v,
                    factorName ? factorName : this.selectedFactorType.name
                  )
                };
              })
            });
          }
          if (type == 'rank' || type == undefined) {
            dataList.push({
              type: 'rank',
              data: _gridDataDetailList[i].map((v) => {
                return {
                  data: v.rank ? v.rank : ''
                };
              })
            });
          }
          dataList.forEach((d) => {
            gridMapUtil.changeGridText({
              points: d.data,
              textViews: d.type == 'data' ? v.dataTxt : v.rankTxt,
              type: d.type,
              isCustomColor,
              useColor,
              factorName: factorName ? factorName : this.selectedFactorType.name
            });
          });
        }
      });
    }
  }
  // ç»˜åˆ¶ç›‘测数据排名文本
@@ -152,8 +211,7 @@
    const data = gridDataDetail.map((v, i) => {
      return {
        lnglat_GD: points[i],
        // data: v.pm25 ? ('排名: ' + v.rank) : ''
        data: v.pm25 ? v.rank : ''
        data: v.rank ? v.rank : ''
      };
    });
    // return gridMapUtil.drawGridTextLabel(data, textViews, labelsLayer, 'top');
@@ -161,7 +219,8 @@
      points: data,
      textViews,
      anchor: 'bottom-center',
      type: 'rank'
      type: 'rank',
      factorName: this.selectedFactorType.name
    });
  }
@@ -196,12 +255,16 @@
    // æ ¹æ®ç»˜åˆ¶é¢œè‰²æ–¹å¼ç»˜åˆ¶ç½‘æ ¼
    let resGridViews;
    if (customColor) {
      resGridViews = gridMapUtil.drawGridColorCustom(res, gridDataDetail);
      resGridViews = gridMapUtil.drawGridColorCustom(
        res,
        gridDataDetail,
        this.selectedFactorType.name
      );
    } else {
      resGridViews = gridMapUtil.drawGridColor(
        res,
        gridDataDetail,
        'PM25',
        this.selectedFactorType.name,
        style
      );
    }
@@ -301,7 +364,12 @@
  }
  deleteTagGrid(tags) {
    this.changeVisibility({ tags, showGridViews: false });
    this.changeVisibility({
      tags,
      showGridViews: false,
      showDataTxt: false,
      showRankTxt: false
    });
    tags.forEach((t) => {
      this.mapViewsMap.delete(t);
      this.gridDataDetailMap.delete(t);
@@ -316,12 +384,18 @@
      if (showGridViews) {
        // map.add(this.mapViews.lastGridViews);
        _mapViewsList.forEach((v) => {
          if (v.lastGridViews) map.add(v.lastGridViews);
          if (v.lastGridViews) {
            map.add(v.lastGridViews);
            v.show = true;
          }
        });
      } else {
        // map.remove(this.mapViews.lastGridViews);
        _mapViewsList.forEach((v) => {
          if (v.lastGridViews) map.remove(v.lastGridViews);
          if (v.lastGridViews) {
            map.remove(v.lastGridViews);
            v.show = false;
          }
        });
      }
    }
@@ -329,12 +403,18 @@
      if (showDataTxt) {
        // map.add(this.mapViews.dataTxt);
        _mapViewsList.forEach((v) => {
          if (v.dataTxt) map.add(v.dataTxt);
          if (v.dataTxt) {
            map.add(v.dataTxt);
            v.show = true;
          }
        });
      } else {
        // map.remove(this.mapViews.dataTxt);
        _mapViewsList.forEach((v) => {
          if (v.dataTxt) map.remove(v.dataTxt);
          if (v.dataTxt) {
            map.remove(v.dataTxt);
            v.show = false;
          }
        });
      }
    }
@@ -342,12 +422,18 @@
      if (showRankTxt) {
        // map.add(this.mapViews.rankTxt);
        _mapViewsList.forEach((v) => {
          if (v.rankTxt) map.add(v.rankTxt);
          if (v.rankTxt) {
            map.add(v.rankTxt);
            v.show = true;
          }
        });
      } else {
        // map.remove(this.mapViews.rankTxt);
        _mapViewsList.forEach((v) => {
          if (v.rankTxt) map.remove(v.rankTxt);
          if (v.rankTxt) {
            map.remove(v.rankTxt);
            v.show = false;
          }
        });
      }
    }
@@ -373,27 +459,30 @@
  }
  changeGridColor({
    tag,
    tags = [],
    factorName,
    useCustomColor,
    opacity,
    zIndex,
    isMixGridHighlight
  }) {
    let { _mapViewsList, _gridDataDetailList } = this._getMapViews(tag);
    let { _mapViewsList, _gridDataDetailList } = 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 (useCustomColor) {
          if (v.useCustomColor) {
            gridMapUtil.drawGridColorCustom(
              v.lastGridViews,
              lastGridDataDetail
              lastGridDataDetail,
              factorName ? factorName : this.selectedFactorType.name
            );
          } else {
            gridMapUtil.drawGridColor(
              v.lastGridViews,
              lastGridDataDetail,
              'PM25',
              factorName ? factorName : this.selectedFactorType.name,
              { opacity, zIndex, isMixGridHighlight }
            );
          }
@@ -428,9 +517,41 @@
          (v) => v.cellId == cellIndex
        );
        polygon.on(name, (e) => {
          event(gridCell, gridDataDetail);
          event({ gridCell, gridDataDetail, polygon, extData: v.extData });
        });
      });
    });
  }
  setDefaultGridClickEvent(tags) {
    this.setGridEvent(
      tags,
      'click',
      ({ gridCell, gridDataDetail, extData }) => {
        gridStore.selectedGridCellAndDataDetail = {
          gridCell,
          gridDataDetail,
          extData
        };
      }
    );
    //鼠标移入事件
    this.setGridEvent(tags, 'mouseover', ({ polygon }) => {
      const ext = polygon.getExtData();
      const originOption = polygon.getOptions();
      ext.originOption = originOption;
      polygon.setOptions({
        strokeWeight: 2,
        strokeColor: 'red'
      });
      polygon.setExtData(ext);
    });
    //鼠标移出事件
    this.setGridEvent(tags, 'mouseout', ({ polygon }) => {
      const ext = polygon.getExtData();
      polygon.setOptions(ext.originOption);
    });
  }
@@ -455,7 +576,7 @@
   * é‡å çš„网格进行监测数据均值计算并重新计算对应颜色,形成新的一组融合网格
   * @param {Array} tags éœ€è¦èžåˆçš„网格标签,当为空时,默认融合所有网格
   */
  mixGrid(tags, isMixGridHighlight) {
  mixGrid({ tags, isMixGridHighlight = true }) {
    tags.sort((a, b) => {
      return a < b ? -1 : 1;
    });
@@ -465,7 +586,7 @@
        tags: [mixTag],
        showGridViews: true
      });
      this.changeGridColor({ tag: mixTag, isMixGridHighlight });
      this.changeGridColor({ tags: [mixTag], isMixGridHighlight });
    } else {
      // const mixMapViews = this._createNewMapViews();
      // æ ¹æ®æ ‡ç­¾tag,获取对应多组网格数据
@@ -502,7 +623,7 @@
        if (count > 1) {
          v.res.gridStyle = {
            strokeWeight: 2,
            strokeColor: 'blue'
            strokeColor: '#23dad1'
          };
        }
        resGridDataDetail.push(v.res);
@@ -520,8 +641,46 @@
        data: resGridDataDetail,
        grid: {
          style: {
            isMixGridHighlight:
              isMixGridHighlight == undefined ? true : isMixGridHighlight
            isMixGridHighlight
          }
        },
        extData: {
          name: `走航融合 - ${mixTag}`,
          type: 1
        }
      });
    }
    return mixTag;
  }
  mixGrid2({ tags, isMixGridHighlight = true, gridDataDetailList }) {
    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 {
      gridDataDetailList.forEach((gdd) => {
        // ç½‘格数据是融合的,展示高亮的样式
        if (gdd.mixData) {
          gdd.gridStyle = {
            strokeWeight: 2,
            strokeColor: '#23dad1'
          };
        }
      });
      this.drawTagGrid({
        tag: mixTag,
        data: gridDataDetailList,
        grid: {
          style: {
            isMixGridHighlight
          }
        },
        extData: {
@@ -808,7 +967,8 @@
      }),
      gridPoints: JSON.parse(JSON.stringify(this.mapViews.gridPoints)),
      points: JSON.parse(JSON.stringify(this.mapViews.points)),
      extData
      extData,
      show: true
    };
  }
}
src/utils/map/grid.js
@@ -4,6 +4,7 @@
import { map } from './index_old';
import calculate from './calculate';
import { Legend } from '@/model/Legend';
import { getGridDataDetailFactorValue } from '@/model/GridDataDetail';
import { getHexColor, getColorBetweenTwoColors } from '../color';
/**
@@ -80,11 +81,7 @@
  });
}
/**
 * æ–‡æœ¬æ ‡è®°
 * å¯ä¿®æ”¹position
 */
function textMaker({ position, text, anchor, type, color }) {
function textMakerStyle({ type, color }) {
  let style = {};
  if (type == 'data') {
    style = {
@@ -111,6 +108,15 @@
      'margin-bottom': '4px'
    };
  }
  return style;
}
/**
 * æ–‡æœ¬æ ‡è®°
 * å¯ä¿®æ”¹position
 */
function textMaker({ position, text, anchor, type, color }) {
  let style = textMakerStyle({ type, color });
  // eslint-disable-next-line no-undef
  return new AMap.Text({
    text: text,
@@ -280,11 +286,19 @@
    return gridViews;
  },
  drawGridText({ points, textViews, anchor, type, isCustomColor, useColor }) {
  drawGridText({
    points,
    textViews,
    anchor,
    type,
    isCustomColor,
    useColor,
    factorName = 'PM25'
  }) {
    let colorList = [];
    if (useColor) {
      colorList = calGridColor({
        factorName: 'PM25',
        factorName,
        data: points.map((p) => p.data),
        isCustomColor: isCustomColor
      });
@@ -305,6 +319,33 @@
    });
    // map.add(_textViews);
    return { textViews: _textViews };
  },
  changeGridText({
    points,
    textViews,
    type,
    isCustomColor,
    useColor,
    factorName = 'PM25'
  }) {
    let colorList = [];
    if (useColor) {
      colorList = calGridColor({
        factorName,
        data: points.map((p) => p.data),
        isCustomColor: isCustomColor
      });
    }
    if (textViews) {
      textViews.forEach((t, i) => {
        t.setText(points[i].data);
        t.setStyle(
          textMakerStyle({ type, color: useColor ? colorList[i] : 'white' })
        );
      });
    }
    return { textViews };
  },
  drawGridTextLabel(points, textViews, labelsLayer, direction) {
@@ -359,11 +400,11 @@
    const res = [];
    // éåŽ†å«æ˜Ÿé¥æµ‹æ•°æ®æ•°ç»„
    gridDataDetail.forEach((d, i) => {
      if (d.pm25) {
      const data = getGridDataDetailFactorValue(d, factorName);
      if (data) {
        const grid = gridViews[i];
        // æ ¹æ®é¥æµ‹æ•°æ®è®¡ç®—网格颜色
        const data = d.pm25;
        const { color, nextColor, range, nextRange } =
          Legend.getStandardColorAndNext(factorName, data);
        const ratio = (data - range) / (nextRange - range);
@@ -401,26 +442,26 @@
    return res;
  },
  drawGridColorCustom(gridViews, gridDataDetail) {
  drawGridColorCustom(gridViews, gridDataDetail, factorName) {
    var max, min;
    gridDataDetail.forEach((t) => {
      if (!t.pm25) return;
      if (!max || t.pm25 > max) {
        max = t.pm25;
      const data = getGridDataDetailFactorValue(t, factorName);
      if (!data) return;
      if (!max || data > max) {
        max = data;
      }
      if (!min || t.pm25 < min) {
        min = t.pm25;
      if (!min || data < min) {
        min = data;
      }
    });
    const res = [];
    // éåŽ†å«æ˜Ÿé¥æµ‹æ•°æ®æ•°ç»„
    gridDataDetail.forEach((d, i) => {
      if (d.pm25) {
      const data = getGridDataDetailFactorValue(d, factorName);
      if (data) {
        const grid = gridViews[i];
        // æ ¹æ®é¥æµ‹æ•°æ®è®¡ç®—网格颜色
        const data = d.pm25;
        const { color, nextColor, range, nextRange } =
          Legend.getCustomColorAndNext(data, min, max);
        const ratio = (data - range) / (nextRange - range);
@@ -431,7 +472,7 @@
          ratio
        );
        grid.setOptions({
          fillColor: _color, //多边形填充颜色
          fillColor: _color //多边形填充颜色
          // fillOpacity: style.opacity ? style.opacity : color[3] == 0 ? 0 : 1
        });
src/views/historymode/HistoryMode.vue
@@ -81,7 +81,7 @@
      // ç›‘测设备编号
      deviceCode: '',
      // ç›‘测因子的类型编号
      factorType: defaultOptions(TYPE0),
      factorType: defaultOptions(TYPE0).value,
      // ç›‘测数据
      factorDatas: new FactorDatas(),
      // å†³å®šç»˜åˆ¶3D图形时是否与原图像合并
src/views/realtimemode/RealtimeMode.vue
@@ -56,7 +56,7 @@
      deviceType: TYPE0,
      deviceCode: '',
      // ç›‘测因子的类型编号
      factorType: defaultOptions(TYPE0),
      factorType: defaultOptions(TYPE0).value,
      // æ–°èŽ·å–çš„ç›‘æµ‹æ•°æ®
      factorDatas: new FactorDatas(),
      // å…¨éƒ¨ç›‘测数据
src/views/underwaymix/UnderwayMixMode.vue
@@ -1,48 +1,20 @@
<template>
  <!-- <div class="p-events-none m-t-2"> -->
  <el-row justify="space-between">
  <el-row class="m-t-2">
    <FactorRadio @change="handleFactorTypeChange"></FactorRadio>
  </el-row>
  <el-row class="m-t-2" justify="space-between">
    <el-row class="wrap">
      <el-col span="2">
        <el-row>
        <!-- <el-row> -->
          <BaseCard v-show="show" size="medium" direction="left">
            <template #content>
              <el-row>
            <!-- <el-row>
                <el-form :inline="true">
                  <!-- <el-form-item label="走航融合">
                    <el-select
                      v-model="selectedfusionData"
                      multiple
                      clearable
                      @change="handleChange"
                      placeholder="选择任务"
                      size="small"
                      style="width: 160px"
                      :loading="fusionLoading"
                    >
                      <el-option
                        v-for="(s, i) in fusionDataList"
                        :key="i"
                        :label="s.mixDataId"
                        :value="i"
                      />
                    </el-select>
                  </el-form-item> -->
                  <!-- <el-form-item>
                    <el-button
                      type="primary"
                      class="el-button-custom"
                      size="small"
                      :disabled="
                        !gridCellList || selectedfusionData.length == 0
                      "
                      @click="handleFusionClick"
                    >
                      {{ '叠加走航' }}
                    </el-button>
                  </el-form-item> -->
                </el-form>
              </el-row>
              <el-row class="m-t-8" justify="space-between">
              </el-row> -->
            <el-row justify="space-between">
                <span>融合分析</span>
              </el-row>
              <el-form :inline="false">
@@ -58,8 +30,8 @@
                    <el-option
                      v-for="(v, i) in timeSectionList"
                      :key="i"
                      :label="v"
                      :value="v"
                    :label="v.label"
                    :value="v.value"
                    />
                  </el-select>
                </el-form-item>
@@ -75,8 +47,8 @@
                    <el-option
                      v-for="(v, i) in zoneList"
                      :key="i"
                      :label="v"
                      :value="v"
                    :label="v.label"
                    :value="v.value"
                    />
                  </el-select>
                </el-form-item>
@@ -92,31 +64,32 @@
                    <el-option
                      v-for="(v, i) in pollutionDegreeList"
                      :key="i"
                      :label="v"
                      :value="v"
                    :label="v.label"
                    :value="v.value"
                    />
                  </el-select>
                </el-form-item>
              </el-form>
              <div v-if="!gridCellList">
            <el-space v-if="!gridCellList">
                <el-icon class="is-loading"><Loading /></el-icon>
                ç½‘格信息加载中...
              </div>
              <el-text type="info">网格信息加载中...</el-text>
            </el-space>
              <el-table
                ref="tableRef"
                :data="showFusionDataList"
                table-layout="fixed"
                size="default"
              size="small"
                :show-overflow-tooltip="true"
                border
                height="50vh"
              height="45vh"
                row-class-name="t-row-normal"
                cell-class-name="t-cell"
                header-row-class-name="t-header-row"
                header-cell-class-name="t-header-cell"
                :highlight-current-row="false"
                @row-click="handleRowClick"
                @selection-change="handleSelectionChange"
              @select="handleSelectionChange"
              @select-all="handleSelectionChange"
              >
                <el-table-column width="40" v-if="!gridCellList">
                  <template #default>
@@ -128,7 +101,11 @@
                  type="selection"
                  :selectable="selectable"
                  width="40"
                />
              >
                <!-- <template #header>
                <span>选择</span>
              </template> -->
              </el-table-column>
                <!-- <el-table-column
                  type="index"
                  label="序号"
@@ -139,7 +116,7 @@
                  label="时间"
                  align="center"
                  :formatter="timeFormatter"
                  width="120"
                width="100"
                />
                <el-table-column
                  prop="missionCode"
@@ -172,26 +149,34 @@
                >
                  {{ '叠加走航' }}
                </el-button> -->
                <CheckButton
              <el-button
                type="primary"
                class="el-button-custom"
                size="small"
                @click="handleMixClick"
              >
                {{ '融合分析' }}
              </el-button>
              <!-- <CheckButton
                  active-text="融合分析"
                  :default-value="false"
                  @change="handleMixClick"
                >
                </CheckButton>
              </CheckButton> -->
              </el-space>
            </template>
            <template #footer> </template>
          </BaseCard>
        </el-row>
        <!-- </el-row> -->
      </el-col>
      <el-col span="2">
        <el-row>
        <!-- <el-row> -->
          <CardButton
            name="走航融合"
            direction="right"
            @click="() => (show = !show)"
          ></CardButton>
        </el-row>
        <!-- </el-row> -->
      </el-col>
    </el-row>
    <GridStyleTool
@@ -204,12 +189,16 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch, computed } from 'vue';
import { ref, toRaw, onMounted, onUnmounted, watch, computed } from 'vue';
import moment from 'moment';
import gridApi from '@/api/gridApi';
import { SatelliteGrid } from '@/model/SatelliteGrid';
import GridStyleTool from './component/GridStyleTool.vue';
import { useGridStore } from '@/stores/grid-info';
import { TYPE0 } from '@/constant/device-type';
import { defaultOptions } from '@/constant/radio-options';
import { useMessageBox } from '@/composables/messageBox';
import { useCloned } from '@vueuse/core';
const gridStore = useGridStore();
@@ -225,6 +214,16 @@
});
const show = ref(true);
// ç›‘测因子的类型编号
const factorType = ref(defaultOptions(TYPE0));
satelliteGrid.setShowFactorType(toRaw(factorType.value));
function handleFactorTypeChange(e, item) {
  factorType.value = item;
  console.log(toRaw(factorType.value));
  satelliteGrid.setShowFactorType(toRaw(factorType.value));
}
const mission = ref(undefined);
const gridCellList = ref(undefined);
@@ -233,7 +232,7 @@
const fusionLoading = ref(false);
const fusionDataList = ref([]);
const selectedfusionData = ref([]);
const tableRef = ref()
const tableRef = ref();
const selectable = (row) => gridCellList.value;
const gridDataDetailMap = new Map();
@@ -248,10 +247,11 @@
    const hour = moment(e.dayTimePeriodStart).hour();
    const t = e.dayTimePeriod;
    const option = {
      label: `${t} ${moment(e.dayTimePeriodStart).format('HH:mm')} - ${moment(e.dayTimePeriodEnd).format('HH:mm')}`,
      value: t,
      index: hour
    };
    if (res.indexOf(option) == -1) {
    if (!res.find((v) => v.label == option.label)) {
      res.push(option);
    }
  });
@@ -269,7 +269,8 @@
  res = res.map((v) => {
    const count = rMap.get(v.value);
    return `${v.value} (${count})`;
    v.label = `${v.label} (${count ? count : 0})`;
    return v;
  });
  return res;
});
@@ -278,8 +279,12 @@
  let res = [];
  fusionDataList.value.forEach((e) => {
    const t = e.zone;
    if (res.indexOf(t) == -1) {
      res.push(t);
    const option = {
      label: t,
      value: t
    };
    if (!res.find((v) => v.label == option.label)) {
      res.push(option);
    }
  });
  const rMap = new Map();
@@ -291,8 +296,9 @@
  });
  res = res.map((v) => {
    const count = rMap.get(v);
    return `${v} (${count})`;
    const count = rMap.get(v.value);
    v.label = `${v.label} (${count ? count : 0})`;
    return v;
  });
  return res;
});
@@ -302,10 +308,11 @@
  fusionDataList.value.forEach((e) => {
    const t = e.pollutionDegree;
    const option = {
      label: t,
      value: t,
      index: e.pollutionDegreeIndex
    };
    if (res.indexOf(option) == -1) {
    if (!res.find((v) => v.label == option.label)) {
      res.push(option);
    }
  });
@@ -322,7 +329,8 @@
  res = res.map((v) => {
    const count = rMap.get(v.value);
    return `${v.value} (${count})`;
    v.label = `${v.label} (${count ? count : 0})`;
    return v;
  });
  return res;
});
@@ -395,45 +403,32 @@
// }
function prepareGrid(gridInfo) {
  satelliteGrid.gridPrepare(gridInfo, (polygon) => {
    //鼠标移入事件
    polygon.on('mouseover', () => {
      polygon.setOptions({
        //修改多边形属性的方法
        strokeWeight: 2,
        strokeColor: 'red'
      });
    });
    //鼠标移出事件
    polygon.on('mouseout', () => {
      polygon.setOptions({
        strokeWeight: 1,
        strokeColor: 'white'
      });
    });
  });
  // satelliteGrid.setGridEvent('click', (gridCell, gridDataDetail) => {
  //   // const polygon = e.target
  //   // const { gridCell } = polygon.getExtData();
  //   // const cellIndex = gridCell.cellIndex;
  //   gridStore.selectedGridCellAndDataDetail = {
  //     gridCell,
  //     gridDataDetail
  //   };
  satelliteGrid.gridPrepare(gridInfo, function (polygon) {
    // const originOption = polygon.getOptions();
    // //鼠标移入事件
    // polygon.on('mouseover', () => {
    //   polygon.setOptions({
    //     //修改多边形属性的方法
    //     strokeWeight: 2,
    //     strokeColor: 'red'
  // });
    // });
    // //鼠标移出事件
    // polygon.on('mouseout', () => {
    //   // polygon.setOptions({
    //   //   strokeWeight: originOption.strokeWeight,
    //   //   strokeColor: originOption.strokeColor
    //   // });
    //   polygon.setOptions(originOption);
    // });
  });
}
// watch(mission, (nV, oV) => {
//   if (nV != oV) {
//     checkUnderwayFusionResult();
//     search(nV);
//   }
// });
watch(
  () => props.groupId,
  (nV, oV) => {
    if (nV != oV) {
      satelliteGrid.gridGroupId = nV;
      gridApi.fetchGridCell(nV).then((res) => {
        gridCellList.value = res.data;
        prepareGrid(gridCellList.value);
@@ -468,66 +463,9 @@
            type: 0
          }
        });
        satelliteGrid.setGridEvent(
          [d.id],
          'click',
          (gridCell, gridDataDetail) => {
            gridStore.selectedGridCellAndDataDetail = {
              gridCell,
              gridDataDetail
            };
          }
        );
        gridCtrls.value = [satelliteGrid];
        // gridCtrls.value = Array.from(satelliteGrid.mapViewsMap);
        // console.log(gridCtrls.value);
      });
    }
  });
}
let mixTag;
function handleMixClick() {
  mixActive.value = !mixActive.value;
  const tags = selectedfusionData.value.map((v) => v.id);
  satelliteGrid.changeVisibility({
    showGridViews: false,
    showDataTxt: false,
    showRankTxt: false
  });
  if (mixActive.value) {
    mixTag = satelliteGrid.mixGrid(tags);
    satelliteGrid.setGridEvent(
      [mixTag],
      'click',
      (gridCell, gridDataDetail) => {
        gridStore.selectedGridCellAndDataDetail = {
          gridCell,
          gridDataDetail
        };
      }
    );
    gridCtrls.value = [satelliteGrid];
  } else {
    satelliteGrid.changeVisibility({
      tags,
      showGridViews: true
    });
  }
}
let heatTag;
function handleHeatMapClick() {
  heatActive.value = !heatActive.value;
  satelliteGrid.changeVisibility({
    showGridViews: false,
    showDataTxt: false,
    showRankTxt: false
  });
  if (heatActive.value) {
    // heatTag = satelliteGrid.drawHeatGrid(mixTag);
        satelliteGrid.setDefaultGridClickEvent([d.id]);
    // satelliteGrid.setGridEvent(
    //   [heatTag],
        //   [d.id],
    //   'click',
    //   (gridCell, gridDataDetail) => {
    //     gridStore.selectedGridCellAndDataDetail = {
@@ -536,21 +474,59 @@
    //     };
    //   }
    // );
    // gridCtrls.value = [satelliteGrid];
    const data = satelliteGrid.gridDataDetailMap.get(mixTag);
    gridApi.buildUnderwayHeatmap(3, data, 10).then((res) => {
      heatTag = satelliteGrid.drawHeatGrid2(mixTag, res.data);
      satelliteGrid.setGridEvent(
        [heatTag],
        'click',
        (gridCell, gridDataDetail) => {
          gridStore.selectedGridCellAndDataDetail = {
            gridCell,
            gridDataDetail
          };
        gridCtrls.value = [satelliteGrid];
      });
        }
      );
  });
}
let mixTag;
function handleMixClick() {
  // mixActive.value = !mixActive.value;
  const tags = selectedfusionData.value.map((v) => v.id);
  satelliteGrid.changeVisibility({
    showGridViews: false,
    showDataTxt: false,
    showRankTxt: false
  });
  // if (mixActive.value) {
  gridApi.mixUnderwayGridData(props.groupId, tags).then((res) => {
    mixTag = satelliteGrid.mixGrid2({ tags, gridDataDetailList: res.data });
    satelliteGrid.setDefaultGridClickEvent([mixTag]);
    gridCtrls.value = [satelliteGrid];
  });
  // satelliteGrid.setGridEvent([mixTag], 'click', (gridCell, gridDataDetail) => {
  //   gridStore.selectedGridCellAndDataDetail = {
  //     gridCell,
  //     gridDataDetail
  //   };
  // });
  // gridCtrls.value = [satelliteGrid];
  // } else {
  // satelliteGrid.changeVisibility({
  //   tags,
  //   showGridViews: true
  // });
  // }
}
let heatTag;
const heatMapSearchLength = 4;
function handleHeatMapClick() {
  heatActive.value = !heatActive.value;
  satelliteGrid.changeVisibility({
    showGridViews: false,
    showDataTxt: false,
    showRankTxt: false
  });
  if (heatActive.value) {
    const data = satelliteGrid.gridDataDetailMap.get(mixTag);
    gridApi
      .buildUnderwayHeatmap(props.groupId, data, heatMapSearchLength)
      .then((res) => {
        heatTag = satelliteGrid.drawHeatGrid2(mixTag, res.data);
        satelliteGrid.setDefaultGridClickEvent([heatTag]);
      gridCtrls.value = [satelliteGrid];
    });
  } else {
@@ -578,17 +554,18 @@
  console.log(res);
}
function handleUnderwayClick({ isShow, dataId }) {
function handleUnderwayClick({ isShow, dataId, done }) {
  underwayVisible.value = !underwayVisible.value;
  if (isShow) {
    draw(dataId);
    draw(dataId).finally(() => done());
  } else {
    const d = fusionDataList.value.find((v) => v.id == dataId);
    const mission = missionStore.missionList.find((v) => {
      return v.missionCode == d.mixDataId;
    });
    mapLine.hideLine(mission.missionCode);
    done();
  }
}
function handleFusionDelete(index, tag) {
@@ -596,18 +573,31 @@
  if (f) {
    // const i = selectedfusionData.value.indexOf(f);
    // selectedfusionData.value.splice(i, 1);
    tableRef.value.toggleRowSelection(f, false)
    tableRef.value.toggleRowSelection(f, false);
  }
}
function handleSelectionChange(val) {
  console.log(val);
  const deleted = selectedfusionData.value.filter((v) => {
    return val.indexOf(v) == -1;
    return !val.find((t) => t.id == v.id);
  });
  const deletedIdList = deleted.map((d) => d.id);
  const added = val.filter((v) => {
    return selectedfusionData.value.indexOf(v) == -1;
    return !selectedfusionData.value.find((t) => t.id == v.id);
  });
  if (val.length > 4) {
    useMessageBox({
      confirmMsg: '最多允许同时展示4次走航记录',
      confirmTitle: '走航记录选择过多警告'
    });
    added.forEach((a) => {
      tableRef.value.toggleRowSelection(a, false);
    });
    return;
  }
  // const addedIdList = added.map(d=>d.id)
  if (deletedIdList.length > 0) {
@@ -618,6 +608,29 @@
  added.forEach((i) => {
    const d = i;
    if (gridDataDetailMap.has(d.id)) {
      const gdd = gridDataDetailMap.get(d.id);
      satelliteGrid.drawTagGrid({
        tag: d.id,
        data: gdd,
        extData: {
          name: `走航网格 - ${d.mixDataId}`,
          type: 0
        }
      });
      satelliteGrid.setDefaultGridClickEvent([d.id]);
      // satelliteGrid.setGridEvent(
      //   [d.id],
      //   'click',
      //   (gridCell, gridDataDetail) => {
      //     gridStore.selectedGridCellAndDataDetail = {
      //       gridCell,
      //       gridDataDetail
      //     };
      //   }
      // );
      gridCtrls.value = [satelliteGrid];
    } else {
    gridApi.fetchGridDataDetail(d.id, d.groupId).then((res) => {
      gridDataDetailMap.set(d.id, res.data);
      const gdd = res.data;
@@ -629,21 +642,23 @@
          type: 0
        }
      });
      satelliteGrid.setGridEvent(
        [d.id],
        'click',
        (gridCell, gridDataDetail) => {
          gridStore.selectedGridCellAndDataDetail = {
            gridCell,
            gridDataDetail
          };
        }
      );
        satelliteGrid.setDefaultGridClickEvent([d.id]);
        // satelliteGrid.setGridEvent(
        //   [d.id],
        //   'click',
        //   (gridCell, gridDataDetail) => {
        //     gridStore.selectedGridCellAndDataDetail = {
        //       gridCell,
        //       gridDataDetail
        //     };
        //   }
        // );
      gridCtrls.value = [satelliteGrid];
    });
    }
  });
  selectedfusionData.value = val;
  selectedfusionData.value = useCloned(val).cloned.value;
}
/**走航轨迹*******************************************************************/
@@ -673,8 +688,6 @@
const drawMode = ref(0);
// ç›‘测数据
const factorDataMap = new Map();
// pm2.5
const factorType = 6;
function fetchMission() {
  missionLoading.value = true;
@@ -698,30 +711,7 @@
}
function draw(dataId) {
  if (isUnmounted.value) return;
  // selectedfusionData.value.forEach((i) => {
  //   const d = fusionDataList.value[i];
  //   const mission = missionStore.missionList.find((v) => {
  //     return v.missionCode == d.mixDataId;
  //   });
  //   if (factorDataMap.has(mission.missionCode)) {
  //     const fd = factorDataMap.get(mission.missionCode);
  //     drawLine(mission.missionCode, fd);
  //   } else {
  //     search(mission).then((res) => {
  //       const fd = new FactorDatas();
  //       fd.setData(res.data, drawMode.value, () => {
  //         fd.refreshHeight(factorType.value);
  //         factorDataMap.set(mission.missionCode, fd);
  //         drawLine(mission.missionCode, fd);
  //       });
  //     });
  //   }
  // });
  if (isUnmounted.value) return Promise.resolve();
  const d = fusionDataList.value.find((v) => v.id == dataId);
  const mission = missionStore.missionList.find((v) => {
    return v.missionCode == d.mixDataId;
@@ -729,12 +719,13 @@
  if (factorDataMap.has(mission.missionCode)) {
    const fd = factorDataMap.get(mission.missionCode);
    drawLine(mission.missionCode, fd);
    fd.refreshHeight(factorType.value.value);
    return Promise.resolve(drawLine(mission.missionCode, fd));
  } else {
    search(mission).then((res) => {
    return search(mission).then((res) => {
      const fd = new FactorDatas();
      fd.setData(res.data, drawMode.value, () => {
        fd.refreshHeight(factorType.value);
        fd.refreshHeight(factorType.value.value);
        factorDataMap.set(mission.missionCode, fd);
        drawLine(mission.missionCode, fd);
      });
@@ -744,9 +735,9 @@
function drawLine(missionCode, fd) {
  // åˆ·æ–°å›¾ä¾‹
  const factor = fd.factor[factorType];
  const factor = fd.factor[factorType.value.value];
  sector.clearSector();
  fd.refreshHeight(factorType);
  fd.refreshHeight(factorType.value.value);
  mapLine.drawTagLine(missionCode, fd, factor);
}
</script>
src/views/underwaymix/component/GridStyleTool.vue
@@ -28,6 +28,7 @@
                    type="primary"
                    icon="Close"
                    circle
                    size="small"
                    @click="handleCloseClick(i, t, value)"
                  />
                  <!-- <el-icon><Close /></el-icon> -->
@@ -37,14 +38,25 @@
                <!-- <el-text>{{ g.name }}</el-text> -->
                <!-- <div class="m-t-8">网格要素</div> -->
                <el-row class="m-t-8" justify="space-between">
                  <!-- <el-button
                    type="primary"
                    class="el-button-custom"
                    size="small"
                    @click="gridLoading = !gridLoading"
                  >
                    {{ '融合分析' }}
                  </el-button> -->
                  <CheckButton
                    :loading="gridLoading"
                    v-model="value.show"
                    active-text="显示网格"
                    inactive-text="隐藏网格"
                    :default-value="true"
                    @change="(e) => handleGridClick(e, i, value)"
                  >
                  </CheckButton>
                  <CheckButton
                    :loading="rankLoading"
                    v-model="value.showRank"
                    active-text="显示排名"
                    inactive-text="隐藏排名"
                    :default-value="false"
@@ -52,6 +64,8 @@
                  >
                  </CheckButton>
                  <CheckButton
                    :loading="dataLoading"
                    v-model="value.showData"
                    active-text="显示数据"
                    inactive-text="隐藏数据"
                    :default-value="false"
@@ -61,6 +75,8 @@
                </el-row>
                <el-row class="m-t-8" justify="space-between">
                  <CheckButton
                    :loading="colorLoading"
                    v-model="value.showCustomColor"
                    active-text="绘制对比色"
                    inactive-text="绘制标准色"
                    :default-value="false"
@@ -68,6 +84,8 @@
                  >
                  </CheckButton>
                  <CheckButton
                    :loading="heatMapLoading"
                    v-model="value.showHeatMap"
                    active-text="风险热力图"
                    inactive-text="风险热力图"
                    :default-value="false"
@@ -75,7 +93,9 @@
                  >
                  </CheckButton>
                  <CheckButton
                    :loading="underwayLoading"
                    v-if="value.extData.type == 0"
                    v-model="value.showUnderway"
                    active-text="显示走航轨迹"
                    inactive-text="隐藏走航轨迹"
                    :default-value="false"
@@ -83,7 +103,9 @@
                  >
                  </CheckButton>
                  <CheckButton
                    :loading="highlightLoading"
                    v-if="value.extData.type == 1"
                    v-model="value.highlightFusionGrid"
                    active-text="高亮融合网格"
                    :default-value="true"
                    @change="(e) => handleHighlightGridClick(e, i, value)"
@@ -140,6 +162,14 @@
  }
});
const gridLoading = ref(false);
const rankLoading = ref(false);
const dataLoading = ref(false);
const colorLoading = ref(false);
const heatMapLoading = ref(false);
const underwayLoading = ref(false);
const highlightLoading = ref(false);
const emits = defineEmits(['showUnderway', 'onDelete']);
const gridCtrlList = computed(() => {
@@ -150,6 +180,7 @@
        return {
          tag: v[0],
          extData: v[1].extData,
          show: v[1].show,
          opacityValue: 1
        };
      })
@@ -159,61 +190,54 @@
const show = ref(true);
// const gridVisible = ref(false);
// const rankVisible = ref(false);
// const dataVisible = ref(false);
// const isStandardColor = ref(true);
// const isOpacity = ref(false);
// const opacityValue = ref(0.7);
// const emits = defineEmits([
//   'showRank',
//   'showData',
//   'changeColor',
//   'changeOpacity'
// ]);
function handleCloseClick(index, t, value) {
  const key = value.tag;
  toRaw(props.gridCtrls[index]).deleteTagGrid([key]);
  gridCtrlList.value[index].views.splice(t, 1)
  emits('onDelete', index, key)
  gridCtrlList.value[index].views.splice(t, 1);
  emits('onDelete', index, key);
}
function handleGridClick(e, index, value) {
  gridLoading.value = true;
  const key = value.tag;
  toRaw(props.gridCtrls[index]).changeVisibility({
    tags: [key],
    showGridViews: e
  });
  gridLoading.value = false;
}
function handleRankClick(e, index, value) {
  rankLoading.value = true;
  const key = value.tag;
  toRaw(props.gridCtrls[index]).changeVisibility({
    tags: [key],
    showRankTxt: e
  });
  rankLoading.value = false;
}
function handleDataClick(e, index, value) {
  dataLoading.value = true;
  const key = value.tag;
  toRaw(props.gridCtrls[index]).changeVisibility({
    tags: [key],
    showDataTxt: e
  });
  dataLoading.value = false;
}
function handleColorClick(e, index, value) {
  colorLoading.value = true;
  const key = value.tag;
  toRaw(props.gridCtrls[index]).changeGridColor({
    tag: key,
    tags: [key],
    useCustomColor: e
  });
  colorLoading.value = false;
}
function handleOpacityChange(e, index, value) {
  console.log(e, index, value);
  const key = value.tag;
  // value.opacityValue = e;
  toRaw(props.gridCtrls[index]).changeGridOpacity({
@@ -223,18 +247,27 @@
}
function handleUnderwayClick(e, index, value) {
  underwayLoading.value = true;
  emits('showUnderway', {
    isShow: e,
    dataId: value.tag
    dataId: value.tag,
    done: () => (underwayLoading.value = false)
  });
}
function handleHighlightGridClick(e, index, value) {
  toRaw(props.gridCtrls[index]).mixGrid(value.tag.split('-'), e);
  highlightLoading.value = true;
  toRaw(props.gridCtrls[index]).mixGrid({
    tags: value.tag.split('-'),
    isMixGridHighlight: e
  });
  highlightLoading.value = false;
}
let heatTag;
const heatMapSearchLength = 4;
function handleHeatMapClick(e, index, value) {
  heatMapLoading.value = true;
  const _satelliteGrid = toRaw(props.gridCtrls[index]);
  _satelliteGrid.changeVisibility({
    showGridViews: false,
@@ -243,24 +276,29 @@
  });
  if (e) {
    const data = _satelliteGrid.gridDataDetailMap.get(value.tag);
    gridApi.buildUnderwayHeatmap(3, data).then((res) => {
    gridApi
      .buildUnderwayHeatmap(_satelliteGrid.gridGroupId, data, heatMapSearchLength)
      .then((res) => {
      heatTag = _satelliteGrid.drawHeatGrid2(value.tag, res.data);
      _satelliteGrid.setGridEvent(
        [heatTag],
        'click',
        (gridCell, gridDataDetail) => {
          gridStore.selectedGridCellAndDataDetail = {
            gridCell,
            gridDataDetail
          };
        }
      );
    });
        _satelliteGrid.setDefaultGridClickEvent([heatTag]);
        // _satelliteGrid.setGridEvent(
        //   [heatTag],
        //   'click',
        //   (gridCell, gridDataDetail) => {
        //     gridStore.selectedGridCellAndDataDetail = {
        //       gridCell,
        //       gridDataDetail
        //     };
        //   }
        // );
      })
      .finally(() => (heatMapLoading.value = false));
  } else {
    _satelliteGrid.changeVisibility({
      tags: [value.tag],
      showGridViews: true
    });
    heatMapLoading.value = false;
  }
}
</script>