HistoryDataModal.vue 7.01 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 { computed, ref, unref } from 'vue';
  import { getAllDeviceByOrg } from '/@/api/dataBoard';
  import { getDeviceHistoryInfo } from '/@/api/alarm/position';
  import { DataSource } from '/@/views/visual/palette/types';
  import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext';
  import { DataTypeEnum } from '/@/enums/objectModelEnum';
  import { StructJSON } from '/@/api/device/model/modelOfMatterModel';
  import { HistoryData } from '/@/api/alarm/position/model';
  import { useJsonParse } from '/@/hooks/business/useJsonParse';
  import { isObject, isString } from '/@/utils/is';
  import { useI18n } from '/@/hooks/web/useI18n';

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

  const { t } = useI18n();

  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 loading = ref(false);
  const dataSourceRef = ref<DataSource[]>([]);

  const getPositionRecord = computed<DataSource>(() => unref(dataSourceRef).at(0) as DataSource);

  const getPositionIdentifier = computed(() => {
    const { latitudeIdentifier, longitudeIdentifier } = unref(getPositionRecord);
    return {
      latitudeIdentifier,
      longitudeIdentifier,
    };
  });

  const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext();

  const handleSetForm = async () => {
    const deviceRecord = unref(getPositionRecord) || {};

    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 { latitudeIdentifier, longitudeIdentifier, deviceProfileId } = deviceRecord;

    const attKey = [latitudeIdentifier, longitudeIdentifier].map((item) => {
      const [identifier, structIdentifier] = item || [];
      const detail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, identifier);

      if (detail?.specs?.dataType.type === DataTypeEnum.STRUCT) {
        const structIdentifierDetail = (detail.specs.dataType.specs as StructJSON[])?.find(
          (temp) => temp.identifier === structIdentifier
        );
        return {
          label: `${detail.functionName} / ${structIdentifierDetail?.functionName}`,
          value: `${identifier} / ${structIdentifierDetail?.identifier}`,
        };
      }

      return { label: detail?.functionName, value: identifier };
    });

    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 [registerModal, { closeModal }] = useModalInner(async (dataSource: DataSource[]) => {
    try {
      dataSourceRef.value = dataSource;
      handleSetForm();
    } catch (error) {
      throw error;
    }
  });

  const getPositionDataSource = async (res: HistoryData) => {
    const track: Record<'lng' | 'lat', number>[] = [];
    const {
      latitudeIdentifier = [],
      longitudeIdentifier = [],
      deviceProfileId,
    } = unref(getPositionRecord);

    const [latIdentifier, structLatIdentifier] = latitudeIdentifier || [];
    const [lngIdentifier, structLngIdentifier] = longitudeIdentifier || [];

    if (!latIdentifier || !lngIdentifier) return track;

    const latDetail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, latIdentifier);
    const lngDetail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, lngIdentifier);

    if (!latDetail || !lngDetail) return track;

    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)];

    for (const position of [longitudeIdentifier, latitudeIdentifier]) {
      const [attribute] = position;
      const detail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute);
      if (!detail) continue;
      const { identifier } = detail || {};

      if (detail?.specs?.dataType.type === DataTypeEnum.STRUCT) {
        res[identifier].forEach((temp) => {
          if (isString(temp.value)) {
            temp.value = useJsonParse(temp.value).value;
          }
        });
      }
    }

    for (const ts of timespanList) {
      const latRecord = res[latIdentifier].find((item) => ts === item.ts);
      const lngRecord = res[lngIdentifier].find((item) => ts === item.ts);

      if (!latRecord || !lngRecord) continue;

      const positionRecord = { lat: 0, lng: 0 };

      positionRecord.lat =
        structLatIdentifier && isObject(latRecord.value)
          ? Reflect.get(latRecord.value as unknown as object, structLatIdentifier)
          : latRecord.value;

      positionRecord.lng =
        structLngIdentifier && isObject(lngRecord.value)
          ? Reflect.get(latRecord.value as unknown as object, structLngIdentifier)
          : lngRecord.value;

      if (positionRecord.lat && positionRecord.lng) {
        track.push({ lng: Number(positionRecord.lng), lat: Number(positionRecord.lat) });
      }
    }

    return track;
  };

  const handleOk = async () => {
    try {
      await validate();
      let value = getFieldsValue();

      value = getHistorySearchParams(value);

      loading.value = true;

      const res = await getDeviceHistoryInfo({
        ...value,
        [SchemaFiled.KEYS]: `${unref(getPositionIdentifier).latitudeIdentifier?.at(0)},${unref(
          getPositionIdentifier
        ).longitudeIdentifier?.at(0)}`,
      });

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

<template>
  <BasicModal
    :title="t('visual.board.mapComponent.history')"
    @register="registerModal"
    @ok="handleOk"
    :ok-button-props="{ loading }"
  >
    <BasicForm @register="registerForm" />
  </BasicModal>
</template>