util.ts 5.03 KB
import { HourRange, SixtyRange } from 'cron-parser';
import { dateUtil } from '/@/utils/dateUtil';
import { ExecuteTimeTypeEnum, FormFieldsEnum, PeriodTypeEnum, PushWayEnum } from './config';
import { CreateTaskRecordType, TaskRecordType } from '/@/api/task/model';
import { DeviceCascadePickerValueType } from '../DevicePicker';
import { TaskTargetEnum } from '../../config';
import { TimeUnitEnum } from '/@/enums/toolEnum';
import { ProductCascadePickerValueType } from '../ProductPicker';
import { toRaw } from 'vue';

export interface FormValueType extends Partial<Record<FormFieldsEnum, any>> {
  [FormFieldsEnum.EXECUTE_TARGET_DATA]: DeviceCascadePickerValueType;
  [FormFieldsEnum.DEVICE_PROFILE]: ProductCascadePickerValueType;
}

interface GenCronExpressionResultType {
  effective: boolean;
  expression?: string;
}

export const genPollCronExpression = (value: number, type: TimeUnitEnum) => {
  const placeholder = 'placeholder';
  const expression = {
    [TimeUnitEnum.SECOND]: `${placeholder} * * * * ? *`,
    [TimeUnitEnum.MINUTE]: `0 ${placeholder} * * * ? *`,
    [TimeUnitEnum.HOUR]: `0 0 ${placeholder} * * ? *`,
  };
  const newExpression = expression[type];
  return newExpression.replace(placeholder, `0/${value}`);
};

export const genCronExpression = (
  time: string,
  expression = '* * * * * * *',
  periodType: PeriodTypeEnum
): GenCronExpressionResultType => {
  try {
    if (periodType === PeriodTypeEnum.DAY) {
      expression = '* * * * * ? *';
    }
    const separator = ' ';
    const list: (string | number)[] = expression.split(separator);

    const date = dateUtil(time, 'HH:mm:ss');

    const second = date.get('second') as SixtyRange;
    const minute = date.get('minute') as SixtyRange;
    const hour = date.get('hour') as HourRange;

    list[0] = second;
    list[1] = minute;
    list[2] = hour;

    return { effective: true, expression: list.join(separator) };
  } catch (error) {
    // throw error;
    return { effective: false };
  }
};

export const composeData = (result: Required<FormValueType>): CreateTaskRecordType => {
  const {
    name,
    targetType,
    rpcCommand,
    pushWay,
    executeContentType,
    executeTargetData,
    deviceProfile,
    executeTimeType,
    period,
    periodType,
    time,
    interval,
    pollUnit,
  } = result;

  const { organizationId, deviceType, deviceId, deviceProfileId } = executeTargetData || {};

  const {
    organizationId: productOrg,
    deviceProfileId: productId,
    deviceType: productDeviceType,
  } = deviceProfile || {};

  const { expression } = genCronExpression(time, period, periodType);

  const cron =
    executeTimeType === ExecuteTimeTypeEnum.POLL
      ? genPollCronExpression(interval, pollUnit)
      : expression!;

  return {
    name,
    organizationId: result.organizationId,
    targetType,
    executeContent: {
      pushContent: {
        rpcCommand:
          pushWay === PushWayEnum.TCP ? rpcCommand.replaceAll(/\s/g, '') : JSON.parse(rpcCommand),
      },
      pushWay,
      type: executeContentType,
    },
    executeTarget: {
      data: targetType === TaskTargetEnum.PRODUCTS ? [productId] : (deviceId as string[]),
      deviceType: targetType === TaskTargetEnum.PRODUCTS ? productDeviceType : deviceType,
      organizationId: targetType === TaskTargetEnum.PRODUCTS ? productOrg : organizationId,
      deviceProfileId: targetType === TaskTargetEnum.PRODUCTS ? productId : deviceProfileId,
    },
    executeTime: {
      type: executeTimeType,
      periodType,
      period,
      time: executeTimeType === ExecuteTimeTypeEnum.POLL ? interval : time,
      cron,
      pollUnit,
    },
  };
};

export const parseData = (result: TaskRecordType): Required<FormValueType> => {
  const { name, targetType, executeContent, executeTarget, executeTime } = result;
  const { pushContent: { rpcCommand } = {}, pushWay, type: executeContentType } = executeContent;
  const { data, deviceProfileId, deviceType, organizationId } = executeTarget as Required<
    TaskRecordType['executeTarget']
  >;
  const { type: executeTimeType, period, periodType, time, pollUnit } = executeTime;
  return {
    name,
    organizationId: result.organizationId,
    targetType,
    rpcCommand: pushWay === PushWayEnum.MQTT ? JSON.stringify(rpcCommand, null, 2) : rpcCommand,
    transportType: pushWay,
    pushWay,
    executeContentType,
    executeTargetData: {
      deviceId: targetType === TaskTargetEnum.DEVICES ? toRaw(data) : [],
      deviceProfileId,
      deviceType,
      organizationId,
    },
    deviceProfile:
      targetType === TaskTargetEnum.PRODUCTS
        ? {
            deviceProfileId: data[0],
            deviceType,
            organizationId,
          }
        : ({} as unknown as ProductCascadePickerValueType),
    executeTimeType,
    period,
    periodType: executeTimeType === ExecuteTimeTypeEnum.CUSTOM ? periodType : null,
    time: executeTimeType === ExecuteTimeTypeEnum.CUSTOM ? time : null,
    interval: executeTimeType === ExecuteTimeTypeEnum.POLL ? Number(time) : null,
    pollUnit: executeTimeType === ExecuteTimeTypeEnum.POLL ? pollUnit : TimeUnitEnum.SECOND,
  };
};