HistoryDataModal.vue 5.96 KB
<script lang="ts" setup>
  import { BasicForm, useForm } from '/@/components/Form';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { formSchema, getHistorySearchParams, SchemaFiled } from './history.config';
  import { HistoryModalOkEmitParams } from './type';
  import { ref, unref } from 'vue';
  import { getAllDeviceByOrg } from '/@/api/dataBoard';
  import { getDeviceHistoryInfo } from '/@/api/alarm/position';
  import { DataSource } from '/@/views/visual/palette/types';
  import { cloneDeep } from 'lodash-es';

  const emit = defineEmits(['register', 'ok']);

  const [registerForm, { updateSchema, setFieldsValue, validate, getFieldsValue }] = useForm({
    schemas: formSchema(),
    showActionButtonGroup: false,
    fieldMapToTime: [
      [SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS], 'YYYY-MM-DD HH:mm:ss'],
    ],
  });

  const getTwoMap = async (dataSource) => {
    if (dataSource.length < 2) return;
    dataSource = dataSource.splice(0, 2);
    const deviceRecord = dataSource?.at(0) || ({} as DataSource);

    if (!deviceRecord.organizationId) return;
    const deviceList = await getAllDeviceByOrg(
      deviceRecord.organizationId,
      deviceRecord.deviceProfileId
    );
    const options = deviceList
      .filter((item) => item.tbDeviceId === deviceRecord.deviceId)
      .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId }));

    const attKey = dataSource.map((item) => ({
      ...item,
      label: item.attribute,
      value: item.attribute,
    }));

    updateSchemaMap(options, attKey, deviceRecord);
  };

  const getOneMap = async (dataSource) => {
    const deviceRecord = dataSource?.[0];
    if (!deviceRecord.organizationId) return;
    const deviceList = await getAllDeviceByOrg(
      deviceRecord.organizationId,
      deviceRecord.deviceProfileId
    );
    const options = deviceList
      .filter((item) => item.tbDeviceId === deviceRecord.deviceId)
      .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId }));

    const attKey = dataSource?.map((item) => ({
      ...item,
      label: item.attributeName,
      value: item.attribute,
    }));
    updateSchemaMap(options, attKey, deviceRecord);
  };

  const updateSchemaMap = (options, attKey, deviceRecord) => {
    updateSchema([
      {
        field: SchemaFiled.DEVICE_ID,
        componentProps: {
          options,
        },
      },
      {
        field: SchemaFiled.KEYS,
        component: 'Select',
        defaultValue: attKey.map((item) => item.value),
        componentProps: {
          options: attKey,
          mode: 'multiple',
          disabled: true,
        },
      },
    ]);

    setFieldsValue({
      [SchemaFiled.DEVICE_ID]: deviceRecord.deviceId,
      [SchemaFiled.KEYS]: attKey.map((item) => item.value),
    });
  };

  const getDesign = ref();

  const [registerModal, { closeModal }] = useModalInner(async (dataSource: DataSource[]) => {
    try {
      getDesign.value = dataSource;
      dataSource = cloneDeep(dataSource);
      //判断选择是不是结构体
      if (dataSource.length == 1 && dataSource?.[0]?.lal) {
        getOneMap(dataSource);
        return;
      }
      getTwoMap(dataSource);
    } catch (error) {
      throw error;
    }
  });

  const getMultipleDataSource = async (res) => {
    let timespanList = Object.keys(res).reduce((prev, next) => {
      const ts = res[next].map((item) => item.ts);
      return [...prev, ...ts];
    }, [] as number[]);
    timespanList = [...new Set(timespanList)];

    const track: Record<'lng' | 'lat', number>[] = [];
    const keys = Object.keys(res);

    for (const ts of timespanList) {
      const list: { ts: number; value: number }[] = [];
      for (const key of keys) {
        const record = res[key].find((item) => ts === item.ts);
        if (!validEffective(record?.value)) {
          continue;
        }
        list.push(record as any);
      }

      if (list.length === 2 && list.every(Boolean)) {
        const lng = list.at(0)?.value;
        const lat = list.at(1)?.value;
        if (lng && lat) track.push({ lng, lat });
      }
    }
    return track;
  };

  const getSingleDataSource = async (res) => {
    const [keys] = Object.keys(res);
    const track: Record<'lng' | 'lat', number>[] = [];
    const dataSource = res[keys]?.map((item) => {
      return {
        value: item.value ? JSON.parse(item.value) : {},
      };
    });
    const list: { value: number }[] = [];
    dataSource?.forEach((item) => {
      if (
        //判断结构体得值是不是数字
        Object.values(item.value).every((item1) => {
          return validEffective(item1 as any);
        })
      ) {
        list.push(item.value);
      }
    });
    const { latitude, longitude } = unref(getDesign)?.[0]; //获取选择得经纬度选项

    list.forEach((item) => {
      const lng = item[longitude];
      const lat = item[latitude];
      if (lng && lat) track.push({ lng, lat });
    });
    return track;
  };

  const validEffective = (value = '') => {
    return !!(value && !isNaN(value as unknown as number));
  };
  const loading = ref(false);
  const handleOk = async () => {
    try {
      await validate();
      let value = getFieldsValue();

      value = getHistorySearchParams(value);

      loading.value = true;

      const res = await getDeviceHistoryInfo({
        ...value,
        [SchemaFiled.KEYS]: value[SchemaFiled.KEYS].join(','),
      });
      const ifSingle = unref(getDesign).length === 1 && unref(getDesign)?.[0]?.lal;

      const track = ifSingle ? await getSingleDataSource(res) : await getMultipleDataSource(res);
      emit('ok', { track, value } as HistoryModalOkEmitParams);
      closeModal();
    } catch (error) {
      throw error;
    } finally {
      loading.value = false;
    }
  };
</script>

<template>
  <BasicModal
    title="历史轨迹"
    @register="registerModal"
    @ok="handleOk"
    :ok-button-props="{ loading }"
  >
    <BasicForm @register="registerForm" />
  </BasicModal>
</template>