index.vue 4.14 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import { useBaiduMapSDK } from '../../../hook/useBaiduMapSDK';
  import { ref, unref } from 'vue';
  import { buildUUID } from '/@/utils/uuid';
  import { Spin } from 'ant-design-vue';
  import { computed } from 'vue';
  import { useMapTrackPlayBack } from './useMapTrackPlayback';
  import { useMultipleDataFetch } from '../../../hook/socket/useSocket';
  import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type';

  const props = defineProps<{
    config: ComponentPropsConfigType<typeof option>;
  }>();

  const wrapRef = ref<Nullable<Recordable>>(null);

  const mapInstance = ref<Nullable<Recordable>>(null);

  const wrapId = `bai-map-${buildUUID()}`;

  const getDeviceId = computed(() => {
    return props.config.option.dataSource?.at(0)?.deviceId;
  });

  const getDesign = computed(() => {
    const { option } = props.config;
    const { dataSource } = option || {};
    return {
      dataSource: dataSource,
    };
  });

  /**
   * @description 经度key
   */
  const getLngKey = computed(() => {
    return props.config.option.dataSource?.at(0)?.attribute || '';
  });

  /**
   * @description 纬度key
   */
  const getLatKey = computed(() => {
    return props.config.option.dataSource?.at(1)?.attribute || '';
  });

  const validEffective = (value = '') => {
    return !!(value && !isNaN(value as unknown as number));
  };

  const getTwoMap = (message, deviceId) => {
    if (unref(getDeviceId) !== deviceId) return;

    const { data = {} } = message;

    const bindMessage = data[deviceId];

    const lngData = bindMessage[unref(getLngKey)] || [];
    const [lngLatest] = lngData;
    const [, lng] = lngLatest || [];

    const latData = bindMessage[unref(getLatKey)] || [];
    const [latLatest] = latData;
    const [, lat] = latLatest || [];

    if (validEffective(lng) && validEffective(lat)) {
      drawLine({ lng: Number(lng), lat: Number(lat) });
    }
  };

  const getOneMap = (message, deviceId) => {
    if (unref(getDeviceId) !== deviceId) return;

    const { longitude, latitude, attribute } = unref(getDesign)?.dataSource?.[0] || {};
    const { data } = message || {};
    const bindMessage = data[deviceId];
    const [, values] = attribute && bindMessage?.[attribute][0];

    const mapValues = values ? JSON.parse(values) : {};
    const lng = longitude && mapValues[longitude];
    const lat = latitude && mapValues[latitude];

    if (validEffective(lng) && validEffective(lat)) {
      drawLine({ lng: Number(lng), lat: Number(lat) });
    }
  };

  const updateFn: MultipleDataFetchUpdateFn = (message, deviceId) => {
    const { lal } = unref(getDesign)?.dataSource?.[0] || {};
    // 属性选择结构体类型时
    if (lal && unref(getDesign)?.dataSource?.length == 1) {
      getOneMap(message, deviceId);
      return;
    }
    // 选择两个属性时
    getTwoMap(message, deviceId);
  };

  useMultipleDataFetch(props, updateFn);

  const { drawLine } = useMapTrackPlayBack(mapInstance);

  const initMap = () => {
    const wrapEl = unref(wrapRef);
    if (!wrapEl) return;
    if (!Reflect.has(window, 'BMapGL')) return;
    const BMapGL = (window as any).BMapGL;
    mapInstance.value = new BMapGL.Map(wrapId);

    // 定位当前城市
    const localcity = new BMapGL.LocalCity();
    localcity.get(
      (e: { center: Record<'lat' | 'lng', number>; code: number; level: number; name: string }) => {
        const { center } = e;
        const { lat, lng } = center;
        const point = new BMapGL.Point(lng, lat);
        unref(mapInstance)!.centerAndZoom(point, 15);
      }
    );

    unref(mapInstance)!.enableScrollWheelZoom(true);
  };

  const { loading } = useBaiduMapSDK(initMap);
</script>

<template>
  <main class="w-full h-full flex flex-col p-2 justify-center items-center">
    <Spin
      :spinning="loading"
      wrapper-class-name="map-spin-wrapper !w-full !h-full !flex justify-center items-center pointer-events-none"
      tip="地图加载中..."
    />
    <div v-show="!loading" ref="wrapRef" :id="wrapId" class="w-full h-full no-drag"> </div>
  </main>
</template>