config.ts 11.6 KB
import { FormSchema } from '/@/components/Table';
import { ExtendDescOperationTypeEnum, OriginalDataTypeEnum } from '/@/enums/objectModelEnum';
import { validateValueRange } from '../DataTypeForm/config';
import { useComponentRegister } from '/@/components/Form';
import { HexInput, InputTypeEnum } from '../HexInput';
import { isFloatType } from './useParseOperationType';
import { useObjectModelFormContext } from '../useObjectModelFormContext';
import { unref } from 'vue';
import { DataActionModeEnum } from '/@/enums/toolEnum';
import { useI18n } from '/@/hooks/web/useI18n';

useComponentRegister('HexInput', HexInput);

export enum FormFieldsEnum {
  ACTION_TYPE = 'actionType',
  ZOOM_FACTOR = 'zoomFactor',

  OBJECT_MODEL_TYPE = 'objectModelType',

  ORIGINAL_DATA_TYPE = 'originalDataType',
  REGISTER_ADDRESS = 'registerAddress',
  OPERATION_TYPE = 'operationType',
  VALUE_RANGE = 'valueRange',
  SCALING = 'scaling',
  BIT_MASK = 'bitMask',

  REGISTER_COUNT = 'registerCount',

  VALUE_MAPPING = 'valueMapping',
}

export enum FormFieldsNameEnum {
  ORIGINAL_DATA_TYPE = 'deviceManagement.product.originalDataTypeText',
  REGISTER_ADDRESS = 'deviceManagement.product.registerAddressText',
  OPERATION_TYPE = 'deviceManagement.product.actionTypeText',
  VALUE_RANGE = 'deviceManagement.product.valueRangeText',
  SCALING = 'deviceManagement.product.scalingFactorText',
  BIT_MASK = 'deviceManagement.product.bitPositionText',
  REGISTER_COUNT = 'deviceManagement.product.registerNumberText',
  VALUE_MAPPING = 'deviceManagement.product.valueMappingText',
}

export const BOOL_DEFAULT_VALUE_RANGE = { min: 0, max: 1 };

export const INT16_VALUE_RANGE = {
  min: -(2 ** 15),
  max: 2 ** 15 - 1,
};

export const UINT16_VALUE_RANGE = {
  min: 0,
  max: 2 ** 16 - 1,
};

export const INT32_VALUE_RANGE = {
  min: -(2 ** 31),
  max: 2 ** 31 - 1,
};

export const UINT32_VALUE_RANGE = {
  min: 0,
  max: 2 ** 32 - 1,
};

function getValueRangeFromOriginDataType(
  originalDataType?: OriginalDataTypeEnum,
  type: 'range' | 'defaultValue' = 'range'
): Record<'min' | 'max', number> {
  switch (originalDataType) {
    case OriginalDataTypeEnum.BOOLEAN:
      return type === 'defaultValue' ? BOOL_DEFAULT_VALUE_RANGE : UINT16_VALUE_RANGE;

    case OriginalDataTypeEnum.BITS:
      return BOOL_DEFAULT_VALUE_RANGE;

    case OriginalDataTypeEnum.INT16_AB:
    case OriginalDataTypeEnum.INT16_BA:
      return INT16_VALUE_RANGE;

    case OriginalDataTypeEnum.UINT16_AB:
    case OriginalDataTypeEnum.UINT16_BA:
      return UINT16_VALUE_RANGE;

    case OriginalDataTypeEnum.INT32_AB_CD:
    case OriginalDataTypeEnum.INT32_BA_DC:
    case OriginalDataTypeEnum.INT32_CD_AB:
    case OriginalDataTypeEnum.INT32_DC_BA:
      return INT32_VALUE_RANGE;

    case OriginalDataTypeEnum.UINT32_AB_CD:
    case OriginalDataTypeEnum.UINT32_BA_DC:
    case OriginalDataTypeEnum.UINT32_CD_AB:
    case OriginalDataTypeEnum.UINT32_DC_BA:
      return UINT32_VALUE_RANGE;

    default:
      return INT32_VALUE_RANGE;
  }
}

const BOOL_OPERATION_TYPE = [
  ExtendDescOperationTypeEnum.INPUT_STATUS_R_02,
  ExtendDescOperationTypeEnum.COIL_STATUS_R_01,
  ExtendDescOperationTypeEnum.COIL_STATUS_RW_01_05,
  ExtendDescOperationTypeEnum.COIL_STATUS_RW_01_0F,
  ExtendDescOperationTypeEnum.COIL_STATUS_W_05,
  ExtendDescOperationTypeEnum.COIL_STATUS_W_0F,
];

function getOriginalDataTypeByOperationType(
  operationType: ExtendDescOperationTypeEnum
): Record<'label' | 'value', string>[] {
  const { t } = useI18n();
  switch (operationType) {
    case ExtendDescOperationTypeEnum.INPUT_STATUS_R_02:
    case ExtendDescOperationTypeEnum.COIL_STATUS_R_01:
    case ExtendDescOperationTypeEnum.COIL_STATUS_RW_01_05:
    case ExtendDescOperationTypeEnum.COIL_STATUS_RW_01_0F:
    case ExtendDescOperationTypeEnum.COIL_STATUS_W_05:
    case ExtendDescOperationTypeEnum.COIL_STATUS_W_0F:
      return [
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.BOOLEAN}`),
          value: OriginalDataTypeEnum.BOOLEAN,
        },
      ];

    case ExtendDescOperationTypeEnum.HOLDING_REGISTER_RW_03_06:
    case ExtendDescOperationTypeEnum.HOLDING_REGISTER_W_06:
      return [
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.INT16_AB}`),
          value: OriginalDataTypeEnum.INT16_AB,
        },
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.INT16_BA}`),
          value: OriginalDataTypeEnum.INT16_BA,
        },
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.UINT16_AB}`),
          value: OriginalDataTypeEnum.UINT16_AB,
        },
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.UINT16_BA}`),
          value: OriginalDataTypeEnum.UINT16_BA,
        },
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.BITS}`),
          value: OriginalDataTypeEnum.BITS,
        },
        {
          label: t(`enum.originalDataType.${OriginalDataTypeEnum.BOOLEAN}`),
          value: OriginalDataTypeEnum.BOOLEAN,
        },
      ];

    case ExtendDescOperationTypeEnum.HOLDING_REGISTER_RW_03_10:
    case ExtendDescOperationTypeEnum.HOLDING_REGISTER_W_10:
    case ExtendDescOperationTypeEnum.HOLDING_REGISTER_R_03:
    case ExtendDescOperationTypeEnum.INPUT_REGISTER_R_04:
      return Object.keys(OriginalDataTypeEnum).map((key) => ({
        label: t(`enum.originalDataType.${key}`),
        value: OriginalDataTypeEnum[key],
      }));
  }
}

export const getExtendDescFormSchemas = (): FormSchema[] => {
  const DEFAULT_OPERATION_TYPE = ExtendDescOperationTypeEnum.INPUT_STATUS_R_02;
  const DEFAULT_ORIGINAL_TYPE = OriginalDataTypeEnum.BOOLEAN;
  const { t } = useI18n();
  return [
    {
      field: FormFieldsEnum.OPERATION_TYPE,
      label: t(FormFieldsNameEnum.OPERATION_TYPE),
      component: 'Select',
      required: true,
      defaultValue: DEFAULT_OPERATION_TYPE,
      componentProps: ({ formActionType }) => {
        return {
          options: Object.keys(ExtendDescOperationTypeEnum).map((key) => ({
            label: t(`enum.actionType.${key}`),
            value: ExtendDescOperationTypeEnum[key],
          })),
          labelField: 'itemText',
          valueField: 'itemValue',
          getPopupContainer: () => document.body,
          allowClear: false,
          onChange(value: ExtendDescOperationTypeEnum) {
            const isBoolTypeOperationType = BOOL_OPERATION_TYPE.includes(value);
            const originalDataType = isBoolTypeOperationType
              ? OriginalDataTypeEnum.BOOLEAN
              : OriginalDataTypeEnum.INT16_AB;

            formActionType.setFieldsValue({
              [FormFieldsEnum.ORIGINAL_DATA_TYPE]: originalDataType,
              [FormFieldsEnum.VALUE_RANGE]: isBoolTypeOperationType
                ? BOOL_DEFAULT_VALUE_RANGE
                : INT16_VALUE_RANGE,
            });
          },
        };
      },
    },
    {
      field: FormFieldsEnum.REGISTER_ADDRESS,
      label: t(FormFieldsNameEnum.REGISTER_ADDRESS),
      component: 'HexInput',
      changeEvent: 'update:value',
      valueField: 'value',
      helpMessage: [t('deviceManagement.product.registerAddressHelpText')],
      required: true,
      componentProps: {
        type: InputTypeEnum.HEX,
        maxValue: parseInt('0xFFFF', 16),
      },
    },
    {
      field: FormFieldsEnum.ORIGINAL_DATA_TYPE,
      label: t(FormFieldsNameEnum.ORIGINAL_DATA_TYPE),
      component: 'Select',
      required: true,
      defaultValue: DEFAULT_ORIGINAL_TYPE,
      dynamicDisabled: ({ model }) =>
        BOOL_OPERATION_TYPE.includes(model[FormFieldsEnum.OPERATION_TYPE]) ||
        unref(useObjectModelFormContext().getModalMode) === DataActionModeEnum.READ,
      componentProps: ({ formActionType, formModel }) => {
        const operationType = formModel[FormFieldsEnum.OPERATION_TYPE];

        return {
          options: getOriginalDataTypeByOperationType(operationType),
          labelField: 'itemText',
          valueField: 'itemValue',
          getPopupContainer: () => document.body,
          onChange(value: OriginalDataTypeEnum) {
            const { setFieldsValue } = formActionType;
            setFieldsValue({
              [FormFieldsEnum.VALUE_RANGE]: getValueRangeFromOriginDataType(
                value as OriginalDataTypeEnum,
                'defaultValue'
              ),
            });
          },
        };
      },
    },
    {
      field: FormFieldsEnum.BIT_MASK,
      label: t(FormFieldsNameEnum.BIT_MASK),
      component: 'Select',
      ifShow: ({ model }) => model[FormFieldsEnum.ORIGINAL_DATA_TYPE] === OriginalDataTypeEnum.BITS,
      required: true,
      defaultValue: 7,
      componentProps: () => {
        return {
          options: Array.from({ length: 16 }, (_, index) => ({
            label: `${index}`,
            value: index,
          })),
          allowClear: false,
          getPopupContainer: () => document.body,
        };
      },
    },
    {
      field: FormFieldsEnum.VALUE_RANGE,
      label: t(FormFieldsNameEnum.VALUE_RANGE),
      component: 'CustomMinMaxInput',
      rules: [{ required: true, validator: validateValueRange }],
      changeEvent: 'update:value',
      valueField: 'value',
      defaultValue: BOOL_DEFAULT_VALUE_RANGE,
      helpMessage: [t('deviceManagement.product.valueRangeHelpText')],
      ifShow: ({ model }) =>
        model[FormFieldsEnum.ORIGINAL_DATA_TYPE] !== OriginalDataTypeEnum.STRING,
      componentProps: ({ formModel }) => {
        const originalDataType = formModel[FormFieldsEnum.ORIGINAL_DATA_TYPE];

        const { min, max } = getValueRangeFromOriginDataType(
          originalDataType as OriginalDataTypeEnum
        );

        const flag = isFloatType(originalDataType);

        return {
          minInputProps: {
            precision: 0,
            min: flag ? undefined : min,
            max: flag ? undefined : max,
          },
          maxInputProps: {
            precision: 0,
            min: flag ? undefined : min,
            max: flag ? undefined : max,
          },
        };
      },
    },

    {
      field: FormFieldsEnum.SCALING,
      label: t(FormFieldsNameEnum.SCALING),
      component: 'InputNumber',
      required: true,
      defaultValue: 1,
      helpMessage: [t('deviceManagement.product.scalingFactorHelpText')],
      ifShow: ({ model }) =>
        ![OriginalDataTypeEnum.STRING, OriginalDataTypeEnum.BOOLEAN].includes(
          model[FormFieldsEnum.ORIGINAL_DATA_TYPE]
        ),
      rules: [
        {
          validator: (_rule, value: any) => {
            if (Number(value) > 0) return Promise.resolve();
            return Promise.reject(Error(t('deviceManagement.product.scalingFactorHelpText')));
          },
        },
      ],
      componentProps: () => {},
    },
    {
      field: FormFieldsEnum.REGISTER_COUNT,
      label: t(FormFieldsNameEnum.REGISTER_COUNT),
      component: 'InputNumber',
      helpMessage: [t('deviceManagement.product.registerCountHelpText')],
      ifShow: ({ model }) =>
        model[FormFieldsEnum.ORIGINAL_DATA_TYPE] === OriginalDataTypeEnum.STRING,
      required: true,
      componentProps: () => {
        return {
          min: 1,
          max: 125,
          precision: 0,
        };
      },
    },
    {
      field: FormFieldsEnum.VALUE_MAPPING,
      component: 'Input',
      label: t(FormFieldsNameEnum.VALUE_MAPPING),
      slot: FormFieldsEnum.VALUE_MAPPING,
      defaultValue: [
        { value: 0, name: t('deviceManagement.product.closeNameText') },
        { value: 1, name: t('deviceManagement.product.openNameText') },
      ],
      ifShow: ({ model }) =>
        [OriginalDataTypeEnum.BOOLEAN, OriginalDataTypeEnum.BITS].includes(
          model[FormFieldsEnum.ORIGINAL_DATA_TYPE]
        ),
    },
  ];
};