index.vue 4.57 KB
<script lang="ts" setup>
  import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
  import { option } from './config';
  import HistoryDataModel from './HistoryDataModal.vue';
  import { useModal } from '/@/components/Modal';
  import { Button, Tooltip, Spin } from 'ant-design-vue';
  import {
    PlayCircleOutlined,
    PauseCircleOutlined,
    ClockCircleOutlined,
  } from '@ant-design/icons-vue';
  import { computed, ref, toRaw, unref } from 'vue';
  import { buildUUID } from '/@/utils/uuid';
  import { useBaiduMapSDK } from '../../../hook/useBaiduMapSDK';
  import { HistoryModalOkEmitParams, TrackAnimationStatus } from './type';
  import { useMapTrackPlayback } from './useMapTrackPlayback';
  import { shallowRef } from 'vue';
  import { formatToDateTime } from '/@/utils/dateUtil';

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

  const wrapRef = ref();

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

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

  const rangString = ref<Nullable<string>>(null);

  const [register, { openModal }] = useModal();

  const handleTrackSwitch = () => {
    openModal(true, toRaw(props.config.option.dataSource));
  };

  const getIsWidgetLibSelectMode = computed(() => {
    return !props.config.option.dataSource;
  });

  const handleRenderHistroyData = (data: HistoryModalOkEmitParams) => {
    const { track, value } = data;
    const { startTs, endTs } = value;
    const formatType = 'YYYY-MM-DD HH:mm:ss';
    rangString.value = `从${formatToDateTime(startTs, formatType)} 到 ${formatToDateTime(
      endTs,
      formatType
    )}`;
    genTrackPlaybackAnimation(track as any[]);
  };

  const handlePlay = () => {
    if (unref(playStatus) === TrackAnimationStatus.PAUSE) {
      unref(continueFn)?.();
      return;
    }
    if (unref(playStatus) === TrackAnimationStatus.DONE) {
      unref(playFn)?.();
      return;
    }
    if (unref(playStatus) === TrackAnimationStatus.PLAY) {
      unref(pauseFn)?.();
      return;
    }
  };

  async function initMap() {
    const wrapEl = unref(wrapRef);
    if (!wrapEl) return;
    const BMapGL = (window as any).BMapGL;
    if (!Reflect.has(window, 'BMapGL')) return;
    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);

    unref(getIsWidgetLibSelectMode) && genTrackPlaybackAnimation();
  }

  const { loading } = useBaiduMapSDK(initMap);

  const { genTrackPlaybackAnimation, playStatus, playFn, continueFn, pauseFn } =
    useMapTrackPlayback(mapInstance);
</script>

<template>
  <main class="w-full h-full flex flex-col justify-center items-center">
    <div class="w-full flex justify-end">
      <Button
        type="text"
        class="!px-2 flex-auto !text-left truncate mr-2"
        :disabled="getIsWidgetLibSelectMode"
        @click="handleTrackSwitch"
      >
        <div class="w-full truncate text-gray-500 flex items-center">
          <ClockCircleOutlined class="mx-1" />
          <span>历史</span>
          <span class="mx-1">-</span>
          <Tooltip :title="rangString || '请选择'">
            <span class="truncate"> {{ rangString || '请选择' }} </span>
          </Tooltip>
        </div>
      </Button>
      <Button type="text" class="!px-2 !text-gray-500" @click="handlePlay">
        <PlayCircleOutlined v-show="playStatus !== TrackAnimationStatus.PLAY" />
        <PauseCircleOutlined class="!ml-0" v-show="playStatus === TrackAnimationStatus.PLAY" />
        <Tooltip title="请选择查询时间段">
          <span>
            {{ playStatus !== TrackAnimationStatus.PLAY ? '播放轨迹' : '暂停播放' }}
          </span>
        </Tooltip>
      </Button>
    </div>
    <Spin
      :spinning="loading"
      wrapper-class-name="map-spin-wrapper !w-full !h-full !flex justify-center items-center pointer-events-none"
      tip="地图加载中..."
    >
      <div ref="wrapRef" :id="wrapId" class="w-full h-full no-drag"> </div>
    </Spin>

    <HistoryDataModel @register="register" @ok="handleRenderHistroyData" />
  </main>
</template>

<style lang="less" scoped>
  .map-spin-wrapper {
    :deep(.ant-spin-container) {
      @apply justify-center items-center p-2 w-full h-full;
    }
  }
</style>