riku
2024-05-11 e94ea7f723e616a0566ac5c7f9d77435333d9e92
实时走航
已修改13个文件
已删除1个文件
已添加4个文件
已重命名2个文件
18900 ■■■■■ 文件已修改
src/api/monitorDataApi.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chart/GaugeChart.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chart/ProgressLineChart.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chart/RealTimeLineChart.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/DataTable.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/FactorLegend.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/FactorTrend.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/VehicleData.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monitor/WeatherData.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/defaultFactorType.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/lib/AMap.js 18131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/model/Factor.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/elementUI.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/chart/chart-option.js 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/expand/expand.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/historymode/component/DataSheet.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/historymode/component/TrendAnalysis.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realtimemode/RealtimeMode.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realtimemode/component/RealTimeTrend.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/monitorDataApi.js
@@ -31,5 +31,10 @@
    params += startTime ? `&startTime=${startTime}` : '';
    params += endTime ? `&endTime=${endTime}` : '';
    return $http.get(`air/realtime/sec?${params}`).then((res) => res.data);
  },
  fetchNextData({ deviceCode, updateTime, perPage = 50 }) {
    let params = `deviceCode=${deviceCode}&updateTime=${updateTime}&perPage=${perPage}`;
    return $http.get(`air/realtime/sec/next?${params}`).then((res) => res.data);
  }
};
src/components.d.ts
@@ -33,6 +33,7 @@
    ElRadio: typeof import('element-plus/es')['ElRadio']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElSlider: typeof import('element-plus/es')['ElSlider']
    ElTable: typeof import('element-plus/es')['ElTable']
@@ -41,9 +42,10 @@
    FactorCheckbox: typeof import('./components/monitor/FactorCheckbox.vue')['default']
    FactorLegend: typeof import('./components/monitor/FactorLegend.vue')['default']
    FactorRadio: typeof import('./components/monitor/FactorRadio.vue')['default']
    GaugeChart: typeof import('./components/monitor/GaugeChart.vue')['default']
    FactorTrend: typeof import('./components/monitor/FactorTrend.vue')['default']
    GaugeChart: typeof import('./components/chart/GaugeChart.vue')['default']
    HistoricalTrajectory: typeof import('./components/animation/HistoricalTrajectory.vue')['default']
    LineChart: typeof import('./components/monitor/LineChart.vue')['default']
    LineChart: typeof import('./components/chart/LineChart.vue')['default']
    MapToolbox: typeof import('./components/map/MapToolbox.vue')['default']
    MIssionCreate: typeof import('./components/mission/MIssionCreate.vue')['default']
    MissionImport: typeof import('./components/mission/MissionImport.vue')['default']
@@ -52,6 +54,8 @@
    OptionMission: typeof import('./components/search/OptionMission.vue')['default']
    OptionTime: typeof import('./components/search/OptionTime.vue')['default']
    OptionType: typeof import('./components/search/OptionType.vue')['default']
    ProgressLineChart: typeof import('./components/chart/ProgressLineChart.vue')['default']
    RealTimeLineChart: typeof import('./components/chart/RealTimeLineChart.vue')['default']
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
    SearchBar: typeof import('./components/search/SearchBar.vue')['default']
src/components/chart/GaugeChart.vue
ÎļþÃû´Ó src/components/monitor/GaugeChart.vue ÐÞ¸Ä
@@ -26,7 +26,7 @@
      this.gaugeChart.setOption(this.option);
    },
    refreshChart(e) {
      this.option.data[0].value = e;
      this.option.series[0].data[0].value = e;
      this.gaugeChart.setOption(this.option);
    }
  },
src/components/chart/ProgressLineChart.vue
ÎļþÃû´Ó src/components/monitor/LineChart.vue ÐÞ¸Ä
@@ -19,6 +19,7 @@
import { factorName } from '@/constant/factor-name';
import { factorLineOption } from '@/utils/chart/chart-option';
// å¸¦å¯æ‹–动进度条的折线图
export default {
  props: {
    loading: Boolean,
@@ -119,20 +120,17 @@
    // ä¿®æ”¹å›¾è¡¨å±•示的折线图类型
    changeChartSeries() {
      this.option.series = this.getShowSeries();
      this.option.legend.data = this.getLegends(this.option.series);
      this.lineChart.setOption(this.option, { notMerge: true });
    },
    changeChartRange() {
      const { sIndex, eIndex, startPer, endPer } = this.getRange();
      const showSeries = this.getShowSeries(sIndex, eIndex);
      const xAxis = this.getShowXAxis(sIndex, eIndex);
      const legends = this.getLegends(showSeries);
      if (!this.option) {
        this.option = factorLineOption(xAxis, showSeries, legends);
        this.option = factorLineOption(xAxis, showSeries);
      } else {
        this.option.xAxis.data = xAxis;
        this.option.series = showSeries;
        this.option.legend.data = legends;
      }
      // this.option.dataZoom[0].start = startPer;
      // this.option.dataZoom[0].end = endPer;
@@ -160,11 +158,6 @@
      const startPer = (sIndex / this.allXAxis.length) * 100;
      const endPer = (eIndex / this.allXAxis.length) * 100;
      return { sIndex, eIndex, startPer, endPer };
    },
    getLegends(series) {
      return series.map((s) => {
        return s.name;
      });
    }
  },
  beforeUnmount() {
src/components/chart/RealTimeLineChart.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
<template>
  <div class="chart-wrap">
    <div ref="lineChart" class="line-chart"></div>
  </div>
</template>
<script>
import * as echarts from 'echarts';
import { smallLineOption } from '@/utils/chart/chart-option';
export default {
  props: {
    modelValue: {
      type: Object
      // default: () => {
      //   return {
      //     xAxis: [],
      //     series: []
      //   };
      // }
    }
  },
  data() {
    return {
      option: null
    };
  },
  watch: {
    modelValue: {
      handler() {
        this.refreshChart();
      },
      deep: false,
      immediate: true
    }
  },
  methods: {
    refreshChart() {
      const { xAxis, series } = this.modelValue;
      if (!this.option) {
        this.option = smallLineOption(xAxis, series);
      } else {
        this.option.xAxis[0].data = xAxis;
        this.option.series = series;
      }
      if (this.lineChart) {
        this.lineChart.setOption(this.option, { notMerge: true });
      } else {
        this.onChartCreated = () => {
          this.lineChart.setOption(this.option, { notMerge: true });
        };
      }
    }
  },
  mounted() {
    this.lineChart = echarts.init(this.$refs.lineChart);
    if (typeof this.onChartCreated === 'function') {
      this.onChartCreated();
    }
  }
};
</script>
<style scoped>
.chart-wrap {
  /* width: 300px; */
  display: flex;
  justify-content: center;
}
.line-chart {
  width: 300px;
  height: 140px;
  /* border-bottom: 1px solid rgba(255, 255, 255, 0.329); */
}
</style>
src/components/monitor/DataTable.vue
@@ -77,7 +77,7 @@
    },
    selectFactorType: {
      type: Array,
      default: () => ['1', '2', '3']
      default: () => []
    },
    // å½“前选中高亮的数据点索引
    locateIndex: Number
src/components/monitor/FactorLegend.vue
@@ -33,7 +33,7 @@
<script>
import { Legend } from '@/model/Legend';
import { factorUnit } from '../../constant/factor-unit';
import { factorUnit } from '@/constant/factor-unit';
import { Factor } from '@/model/Factor';
export default {
src/components/monitor/FactorTrend.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
<template>
  <BaseCard size="medium" direction="left">
    <template #content>
      <el-scrollbar height="calc(98vh - var(--bevel-length-2))">
        <!-- <div v-for="item in factorTypes" :key="item">
          <el-row>
            <div>{{ allSeries.get(item.value).name }}</div>
            <div>{{ allSeries.get(item.value).currentData }}</div>
            <div>{{ allSeries.get(item.value).min }}</div>
            <div>{{ allSeries.get(item.value).max }}</div>
            <RealTimeLineChart
              v-show="selectFactorType.includes(item.value)"
              :model-value="series(item.value)"
            ></RealTimeLineChart>
          </el-row>
        </div> -->
        <div v-for="item in seriesList" :key="item.key">
          <el-row
            v-show="selectFactorType.includes(item.series.key)"
            justify="space-between"
            class="wrap"
          >
            <div class="flex-col">
              <div class="factor-name">{{ item.series.name }}</div>
              <div class="factor-value">{{ item.series.currentData }}</div>
              <div class="factor-unit">
                {{ getUnit(item.series.label) }}
              </div>
              <!-- <div class="flex-col">
                <div>min:{{ item.series.min }}</div>
                <div>max:{{ item.series.max }}</div>
              </div> -->
            </div>
            <RealTimeLineChart :model-value="item"></RealTimeLineChart>
          </el-row>
        </div>
      </el-scrollbar>
    </template>
  </BaseCard>
</template>
<script>
import { FactorDatas } from '@/model/FactorDatas';
import { TYPE0 } from '@/constant/device-type';
import { checkboxOptions } from '@/constant/checkbox-options';
import { factorName } from '@/constant/factor-name';
import { factorUnit } from '@/constant/factor-unit';
export default {
  props: {
    loading: Boolean,
    factorDatas: FactorDatas,
    deviceType: {
      type: String,
      // type0: è½¦è½½æˆ–无人机; type1:无人船
      default: TYPE0
    },
    selectFactorType: {
      type: Array,
      default: () => ['1', '2', '3']
    },
    // æŠ˜çº¿å›¾æ˜¾ç¤ºçš„æœ€æ•°æ®é‡
    maxCount: {
      type: Number,
      default: 75
    }
  },
  data() {
    return {
      xAxis: [],
      allSeries: new Map(),
      seriesList: []
    };
  },
  computed: {
    factorTypes() {
      return checkboxOptions(this.deviceType);
    }
    // seriesList() {
    //   const list = [];
    //   for (const iterator of this.allSeries) {
    //     list.push({
    //       xAxis: this.xAxis,
    //       series: iterator[1]
    //     });
    //   }
    //   return list;
    // }
  },
  watch: {
    factorDatas: {
      handler() {
        this.refreshData();
      },
      deep: false
    }
  },
  methods: {
    refreshData() {
      this.refreshX();
      this.refreshY();
    },
    refreshX() {
      const newTimes = this.factorDatas.times
        .lastCount(this.maxCount)
        .map((v) => {
          return v.split(' ')[1];
        });
      this.xAxis = this.xAxis.concat(newTimes).lastCount(this.maxCount);
    },
    refreshY() {
      for (const key in this.factorDatas.factor) {
        if (Object.hasOwnProperty.call(this.factorDatas.factor, key)) {
          const e = this.factorDatas.factor[key];
          if (!this.allSeries.has(key)) {
            this.allSeries.set(key, {
              key: key,
              name: factorName[e.factorName],
              label: e.factorName,
              type: 'line',
              data: [],
              showAllSymbol: true,
              animationDelay: function (idx) {
                return idx * 10;
              }
            });
          }
          if (e.datas.length == 0) {
            continue;
          }
          const series = this.allSeries.get(key);
          // æ’入新数据
          const newSeries = e.datas.map((v) => v.factorData);
          series.data = series.data.concat(newSeries).lastCount(this.maxCount);
          // è®¡ç®—数据范围
          const { min, max } = this.dataRange(series.data);
          series.min = min;
          series.max = max;
          // è®°å½•最新数据
          series.currentData =
            Math.round(series.data[series.data.length - 1] * 10) / 10;
        }
      }
      this.toList();
    },
    series(key) {
      return {
        xAxis: this.xAxis,
        // series: this.allSeries.get(key)
        series: key
      };
    },
    dataRange(dataList) {
      let min, max;
      dataList.forEach((e) => {
        if (!min || min > e) {
          min = e;
        }
        if (!max || max < e) {
          max = e;
        }
      });
      return { min, max };
    },
    toList() {
      const list = [];
      for (const iterator of this.allSeries) {
        list.push({
          xAxis: this.xAxis,
          series: iterator[1]
        });
      }
      this.seriesList = list;
    },
    getUnit(label) {
      return factorUnit[label];
    }
  }
};
</script>
<style scoped>
.wrap {
  border-bottom: 1px solid rgba(255, 255, 255, 0.329);
}
.flex-col {
  display: flex;
  flex-direction: column;
}
.factor-value {
  font-weight: 600;
  font-size: 20px;
}
.factor-name {
  color: var(--el-color-warning);
}
.factor-unit {
  /* font-size: ; */
}
</style>
src/components/monitor/VehicleData.vue
@@ -1,11 +1,11 @@
<template>
  <el-row class="wrap">
    <el-form :inline="true">
  <el-row justify="center" class="wrap">
    <!-- <el-form :inline="true">
      <el-form-item label="车速:" class="tag-2">
        {{ speed }}
        {{ speed }}km/h
      </el-form-item>
    </el-form>
    <GaugeChart name="车速" :speed="speed"></GaugeChart>
    </el-form> -->
    <GaugeChart name="车速" :value="speed"></GaugeChart>
  </el-row>
</template>
<script>
@@ -18,13 +18,13 @@
  },
  data() {
    return {
      speed: '--km/h'
      speed: 0
    };
  },
  watch: {
    factorDatas: {
      handler(nV) {
        this.speed = this.lastOne(nV, '14') + 'km/h';
        this.speed = this.lastOne(nV, '14');
      },
      deep: true
    }
@@ -36,9 +36,15 @@
        const lastIndex = f.datas.length - 1;
        return factorDatas.factor[key].datas[lastIndex].factorData;
      } else {
        return '--';
        return 0;
      }
    }
  }
};
</script>
<style scoped>
.wrap {
  /* flex-direction: column; */
  /* background-color: antiquewhite; */
}
</style>
src/components/monitor/WeatherData.vue
@@ -1,27 +1,27 @@
<template>
  <el-row class="wrap">
    <el-form :inline="true">
      <el-form-item label="温度:" class="tag-2">
    <el-form :inline="true" class="form">
      <el-form-item label="温度:" class="w-tag">
        {{ temprature }}
      </el-form-item>
      <el-form-item label="湿度:" class="tag-2">
      <el-form-item label="湿度:" class="w-tag">
        {{ humidity }}
      </el-form-item>
    </el-form>
    <!-- <div class="tag-2">{{ temprature }}</div>
    <div class="tag-2">{{ humidity }}</div> -->
    <!-- <div class="w-tag">{{ temprature }}</div>
    <div class="w-tag">{{ humidity }}</div> -->
  </el-row>
  <el-row class="wrap">
    <el-form :inline="true">
      <el-form-item label="风向:" class="tag-2">
    <el-form :inline="true" class="form">
      <el-form-item label="风向:" class="w-tag">
        {{ windDirection }}
      </el-form-item>
      <el-form-item label="风速:" class="tag-2">
      <el-form-item label="风速:" class="w-tag">
        {{ windSpeed }}
      </el-form-item>
    </el-form>
    <!-- <div class="tag-2">{{ windDirection }}</div>
    <div class="tag-2">{{ windSpeed }}</div> -->
    <!-- <div class="w-tag">{{ windDirection }}</div>
    <div class="w-tag">{{ windSpeed }}</div> -->
  </el-row>
</template>
<script>
@@ -51,20 +51,6 @@
      deep: true
    }
  },
  // computed: {
  //   temprature() {
  //     return `${this.lastOne('TEMPERATURE')}℃`;
  //   },
  //   humidity() {
  //     return `${this.lastOne('HUMIDITY')}%`;
  //   },
  //   windDirection() {
  //     return `${this.lastOne('WIND_DIRECTION')}`;
  //   },
  //   windSpeed() {
  //     return `${this.lastOne('WIND_SPEED')}m/s`;
  //   }
  // },
  methods: {
    lastOne(factorDatas, key) {
      const f = factorDatas.factor[key];
@@ -78,3 +64,24 @@
  }
};
</script>
<style scoped>
.w-tag {
  padding: 2px 4px;
  /* background-color: green; */
  border: 1px solid white;
  border-radius: 2px;
  -moz-border-radius: 25px;
  width: 130px;
  /* Old Firefox */
}
.form {
  display: flex;
  gap: 4px;
}
.el-form-item {
  margin-bottom: 4px;
  margin-right: 0px !important;
}
</style>
src/composables/defaultFactorType.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
// ç›‘测因子复选框默认选项
import { defineProps, ref, watch } from 'vue';
import { checkboxOptions } from '@/constant/checkbox-options';
import { TYPE0 } from '@/constant/device-type';
export function useDefaultFactorType() {
  const props = defineProps({
    deviceType: {
      type: String,
      // type0: è½¦è½½æˆ–无人机; type1:无人船
      default: TYPE0
    }
  });
  // æ ¹æ®å½“前数据对应的设备类型, èŽ·å–é»˜è®¤é€‰ä¸­çš„ç›‘æµ‹å› å­id集合
  function defaultFactorTypes() {
    const list = checkboxOptions(props.deviceType);
    if (list.length > 3) {
      return list.slice(0, 3).map((v) => v.value);
    } else {
      return list.map((v) => v.value);
    }
  }
  const selectFactorType = ref(defaultFactorTypes());
  watch(props.deviceType, (nV, oV) => {
    if (nV != oV) {
      selectFactorType.value = defaultFactorTypes();
    }
  });
  return { selectFactorType, props };
}
src/lib/AMap.js
ÎļþÒÑɾ³ý
src/model/Factor.js
@@ -34,7 +34,6 @@
/**
 * ç›‘测因子类
 * å­˜å‚¨æŸä¸€ç±»åž‹çš„监测因子数据,提供3d地图绘制高度换算,绘图范围设定等功能
 * ç”¨äºŽ3d地图绘制
 */
function Factor(options) {
  /**
src/styles/elementUI.scss
@@ -4,6 +4,7 @@
.el-form-item {
  margin-bottom: 0px;
  margin-right: 8px !important;
}
.el-form-item__label {
src/utils/chart/chart-option.js
@@ -15,7 +15,7 @@
}
// æŠ˜çº¿å›¾
function factorLineOption(_xAxis, _series, legends) {
function factorLineOption(_xAxis, _series) {
  var fontSize = fGetChartFontSize();
  return {
    animationEasing: 'elasticOut',
@@ -39,7 +39,7 @@
    },
    legend: {
      type: 'scroll',
      data: legends,
      // data: legends,
      left: 0,
      textStyle: {
        fontSize: fontSize,
@@ -94,35 +94,128 @@
      },
      minInterval: 1
    },
    series: _series,
    dataZoom: [
      {
        type: 'inside',
        start: 0,
        end: 100
    series: _series
  };
      }
    ]
// æŠ˜çº¿å›¾
function smallLineOption(_xAxis, _series) {
  var fontSize = fGetChartFontSize();
  return {
    animationEasing: 'elasticOut',
    animationDelayUpdate: function (idx) {
      return idx * 5;
    },
    tooltip: {
      textStyle: {
        fontSize: fontSize
      }
    },
    grid: {
      left: '11%',
      right: '2%',
      top: '7%',
      bottom: '20%'
    },
    legend: {
      show: false
    },
    xAxis: [
      {
        show: true,
        // name: '时间',
        // type: 'time',
        data: _xAxis,
        axisLabel: {
          textStyle: {
            fontSize: fontSize
          },
          color: '#ffffff',
          textBorderColor: '#fff'
        },
        axisTick: {
          lineStyle: {
            color: 'white'
          },
          intervel: 0,
          inside: false
        },
        nameTextStyle: {
          color: '#ffffff'
        },
        axisLine: {
          lineStyle: {
            color: '#ffffff'
          }
        }
      },
      { show: true }
    ],
    yAxis: [
      {
        // name: '浓度(μg/m³)',
        // type: 'time',
        axisLabel: {
          textStyle: {
            fontSize: fontSize
          }
        },
        axisLine: {
          show: true,
          lineStyle: {
            color: 'white'
          }
        },
        axisTick: {
          show: false,
          lineStyle: {
            color: 'white'
          }
        },
        splitLine: {
          show: false
        },
        minInterval: 1,
        intervel: 1,
        min: function (value) {
          return Math.floor(value.min);
        },
        max: function (value) {
          return Math.ceil(value.max);
        }
      },
      {
        axisLine: {
          show: true,
          lineStyle: {
            color: 'white'
          }
        }
      }
    ],
    series: _series
  };
}
// ä»ªè¡¨ç›˜
function gaugeOption(name, value) {
  var fontSize = fGetChartFontSize();
  // var fontSize = fGetChartFontSize();
  var option = {
    title: {
      text: name,
      textStyle: {
        color: 'white',
        fontSize: fontSize
      },
      left: 'center'
    },
    // title: {
    //   text: name,
    //   textStyle: {
    //     color: 'white',
    //     fontSize: fontSize
    //   },
    //   left: 'center'
    // },
    textStyle: {
      color: '#ffffff',
      fontSize: 10
    },
    tooltip: {
      formatter: '{a} <br/>{b} : {c}%'
      formatter: '{a} : {c}km/h'
    },
    toolbox: {
      // feature: {
@@ -134,12 +227,17 @@
      {
        name: name,
        type: 'gauge',
        title: {
          color: 'white',
          offsetCenter: [0, '50%']
        },
        detail: {
          color: 'white',
          formatter: '{value}',
          formatter: '{value}km/h',
          textStyle: {
            fontSize: fontSize
          }
            fontSize: 18
          },
          offsetCenter: [0, '80%']
        },
        splitLine: {
          lineStyle: {
@@ -156,13 +254,13 @@
          fontSize: 10
        },
        axisLine: {
          lineStyle: {
            color: [
              [0.2, '#2afd2a'],
              [0.8, '#f1e74d'],
              [1, '#c23531']
            ]
          }
          // lineStyle: {
          //   color: [
          //     [0.2, '#2afd2a'],
          //     [0.8, '#f1e74d'],
          //     [1, '#c23531']
          //   ]
          // }
        },
        itemStyle: {
          color: 'white'
@@ -170,7 +268,7 @@
        data: [
          {
            value: value,
            name: ''
            name: '车速'
          }
        ],
        min: 0,
@@ -181,4 +279,4 @@
  return option;
}
export { factorLineOption, gaugeOption };
export { factorLineOption, smallLineOption, gaugeOption };
src/utils/expand/expand.js
@@ -24,3 +24,9 @@
  }
  return fmt;
};
Array.prototype.lastCount = function (size) {
  const l = this.length;
  const s = size > this.length ? 0 : this.length - size;
  return this.slice(s, l);
};
src/views/historymode/component/DataSheet.vue
@@ -39,10 +39,17 @@
  </el-row>
</template>
<script>
// import { toRefs } from 'vue';
import { TYPE0 } from '@/constant/device-type';
import { checkboxOptions } from '@/constant/checkbox-options';
import { FactorDatas } from '@/model/FactorDatas';
// import { useDefaultFactorType } from "../../../composables/defaultFactorType";
export default {
  // setup(){
  //   const {selectFactorType, props} = useDefaultFactorType()
  //   return {selectFactorType, ...toRefs(props)}
  // },
  props: {
    loading: Boolean,
    factorDatas: FactorDatas,
@@ -56,14 +63,29 @@
  },
  data() {
    return {
      selectFactorType: ['1', '2', '3'],
      selectFactorType: this.defaultFactorTypes(),
      show: false
    };
  },
  emits: ['tableClick'],
  watch: {
    deviceType(nV, oV) {
      if (nV != oV) {
        this.selectFactorType = this.defaultFactorTypes();
      }
    }
  },
  methods: {
    handleTableClick(index) {
      this.$emit('tableClick', index);
    },
    defaultFactorTypes() {
      const list = checkboxOptions(this.deviceType);
      if (list.length > 3) {
        return list.slice(0, 3).map((v) => v.value);
      } else {
        return list.map((v) => v.value);
      }
    }
  }
};
src/views/historymode/component/TrendAnalysis.vue
@@ -6,12 +6,12 @@
          v-model="selectFactorType"
          :device-type="deviceType"
        ></FactorCheckbox>
        <LineChart
        <ProgressLineChart
          :locate-index="locateIndex"
          @chart-click="handleChartClick"
          :factor-datas="factorDatas"
          :select-factor-type="selectFactorType"
        ></LineChart>
        ></ProgressLineChart>
      </el-col>
    </Transition>
    <el-col span="2">
src/views/realtimemode/RealtimeMode.vue
@@ -16,6 +16,11 @@
    <el-row class="m-t-2" justify="start">
      <DashBoard :factor-datas="factorDatas"></DashBoard>
    </el-row>
    <RealTimeTrend
      class="real-time-trend"
      :factor-datas="factorDatas"
      :device-type="deviceType"
    ></RealTimeTrend>
  </div>
</template>
@@ -25,9 +30,13 @@
import { FactorDatas } from '@/model/FactorDatas';
import monitorDataApi from '@/api/monitorDataApi';
import DashBoard from './component/DashBoard.vue';
import RealTimeTrend from './component/RealTimeTrend.vue';
import { MapAnimation } from '@/utils/map/animation';
const mapAnimation = new MapAnimation();
export default {
  components: { DashBoard },
  components: { DashBoard, RealTimeTrend },
  setup() {
    const { loading, fetchData } = useFetchData(10000);
    return { loading, fetchData };
@@ -36,19 +45,33 @@
    return {
      // ç›‘测设备类型
      deviceType: TYPE0,
      deviceCode: '0a0000000001',
      // ç›‘测因子的类型编号
      factorType: '1',
      // ç›‘测数据
      factorDatas: new FactorDatas()
      // æ–°èŽ·å–çš„ç›‘æµ‹æ•°æ®
      factorDatas: new FactorDatas(),
      // å…¨éƒ¨ç›‘测数据
      allFactorDatas: new FactorDatas()
    };
  },
  computed: {
    latestTime() {
      if (this.factorDatas.times.length == 0) {
        return '----/--/-- --:--:--';
      } else {
        return this.factorDatas.times[this.factorDatas.times.length - 1];
      }
    }
  },
  methods: {
    onFetchData(type, data) {
    onFetchData(data) {
      // todo æ ¹æ®è®¾å¤‡ç±»åž‹åˆ‡æ¢åœ°å›¾ç›‘测因子展示单选框、折线图复选框、数据表格复选框的因子类型
      this.deviceType = type;
      this.factorDatas.setData(data, this.drawMode, () => {
        this.factorDatas.refreshHeight(this.factorType);
      // this.deviceType = type;
      const fDatas = new FactorDatas();
      fDatas.setData(data, this.drawMode, () => {
        fDatas.refreshHeight(this.factorType);
        // this.draw();
        this.factorDatas = fDatas;
      });
    },
    fetchRealTimeData() {
@@ -56,18 +79,75 @@
      this.fetchData((page) => {
        return monitorDataApi
          .fetchHistroyData({
            deviceCode: '0a0000000001',
            deviceCode: this.deviceCode,
            startTime: '2021-11-04 09:53:35',
            page,
            perPage: 100
          })
          .then((res) => {
            this.onFetchData(TYPE0, res.data);
            this.onFetchData(res.data);
            this.onMapData(res.data);
            this.fetchNextData();
          });
      });
    },
    clearFetchingTask() {
      if (this.fetchingTask) {
        clearInterval(this.fetchingTask);
      }
    },
    fetchNextData() {
      this.clearFetchingTask();
      this.fetchingTask = setInterval(() => {
        if (this.isFetching) {
          return;
        }
        this.isFetching = true;
        this.fetchData(() => {
          return monitorDataApi
            .fetchNextData({
              deviceCode: this.deviceCode,
              updateTime: this.latestTime,
              perPage: 2
            })
            .then((res) => {
              this.onFetchData(res.data);
              this.onMapData(res.data);
            })
            .finally(() => (this.isFetching = false));
        });
      }, 10000);
    },
    onMapData(dataList) {
      let startIndex = this.allFactorDatas.length() - 1;
      if (!this.notFirstFetch) {
        startIndex = dataList.length - 2;
        this.notFirstFetch = true;
      }
      startIndex = startIndex < 0 ? 0 : startIndex;
      this.allFactorDatas.addData(dataList, this.drawMode, () => {
        mapAnimation.moveAnimation(
          this.allFactorDatas,
          this.factorType,
          startIndex
        );
      });
    }
  },
  mounted() {
    this.fetchRealTimeData();
  },
  unmounted() {
    this.clearFetchingTask();
    mapAnimation.stop();
  }
};
</script>
<style scoped>
.real-time-trend {
  position: absolute;
  right: 0;
  top: 0;
}
</style>
src/views/realtimemode/component/RealTimeTrend.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
<template>
  <el-row class="wrap">
    <el-col span="" class="flex-col">
      <el-row justify="end">
        <CardButton
          name="实时趋势"
          direction="left"
          @click="() => (show = !show)"
        ></CardButton>
      </el-row>
      <FactorCheckbox
        v-show="show"
        direction="right"
        vertical
        borderless-direction="r"
        v-model="selectFactorType"
        :device-type="deviceType"
      ></FactorCheckbox>
    </el-col>
    <el-col v-show="show" span="">
      <el-row align="bottom">
        <FactorTrend
          :factor-datas="factorDatas"
          :device-type="deviceType"
          :select-factor-type="selectFactorType"
        ></FactorTrend>
      </el-row>
    </el-col>
  </el-row>
</template>
<script>
import { TYPE0 } from '@/constant/device-type';
import { FactorDatas } from '@/model/FactorDatas';
export default {
  props: {
    loading: Boolean,
    factorDatas: FactorDatas,
    deviceType: {
      type: String,
      // type0: è½¦è½½æˆ–无人机; type1:无人船
      default: TYPE0
    }
  },
  data() {
    return {
      selectFactorType: ['1', '2', '3'],
      show: true
    };
  }
};
</script>
<style scoped>
.flex-col {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
</style>