config.ts 11.4 KB
import { unref } from 'vue';
import { createHexCommandRuleValidator } from '.';
import { createFunctionNameFormItem, createIdentifierFormItem } from './DataTypeForm/config';
import { useObjectModelFormContext } from './useObjectModelFormContext';
import { findDictItemByCode } from '/@/api/system/dict';
import { FormSchema } from '/@/components/Form';
import { ServiceCallTypeEnum, TCPProtocolTypeEnum, TransportTypeEnum } from '/@/enums/deviceEnum';
import { DictEnum } from '/@/enums/dictEnum';
import {
  ObjectModelAccessModeEnum,
  FunctionTypeEnum,
  FunctionTypeNameEnum,
  ObjectEventTypeEnum,
  BuiltInIdentifierEnum,
} from '/@/enums/objectModelEnum';
import { DataActionModeEnum } from '/@/enums/toolEnum';
import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
import { DeviceProfileDetail } from '/@/api/device/model/deviceConfigModel';
import { useI18n } from '/@/hooks/web/useI18n';

export enum FormFieldsEnum {
  FUNCTION_TYPE = 'functionType',
  FUNCTION_NAME = 'functionName',
  IDENTIFIER = 'identifier',
  DATA_TYPE = 'dataType',
  ACCESS_MODE = 'accessMode',
  VALUE_RANGE = 'valueRange',
  STEP = 'step',
  UNIT = 'unit',
  UNIT_NAME = 'unitName',
  REMARK = 'remark',
  BOOL_CLOSE = 'boolClose',
  BOOL_OPEN = 'boolOpen',
  LENGTH = 'length',
  EXTENSION_DESC = 'extensionDesc',
  ENUMS_DATA = 'enumsData',
  STRUCT_DATA = 'structData',

  CALL_TYPE = 'callType',
  SERVICE_COMMAND = 'serviceCommand',
  INPUT_DATA = 'inputData',
  OUTPUT_DATA = 'outputData',

  EVENT_TYPE = 'eventType',

  DATA_TYPE_FORM = 'dataTypeForm',
}

export enum FormFieldsNameEnum {
  FUNCTION_TYPE = 'deviceManagement.product.featureTypeText',
  FUNCTION_NAME = 'deviceManagement.product.featureNameText',
  IDENTIFIER = 'deviceManagement.product.identifierText',
  DATA_TYPE = 'deviceManagement.product.dataTypeText',
  ACCESS_MODE = 'deviceManagement.product.accessModeText',
  VALUE_RANGE = 'deviceManagement.product.valueRangeText',
  STEP = 'deviceManagement.product.stepText',
  UNIT = 'deviceManagement.product.unitText',
  UNIT_NAME = 'deviceManagement.product.unitNameText',
  REMARK = 'common.remarkText',
  BOOL_CLOSE = 'deviceManagement.product.boolCloseText',
  BOOL_OPEN = 'deviceManagement.product.boolOpenText',
  LENGTH = 'deviceManagement.product.lengthText',
  EXTENSION_DESC = 'deviceManagement.product.extensionDescText',
  ENUMS_DATA = 'deviceManagement.product.enumsDataText',
  STRUCT_DATA = 'deviceManagement.product.structDataText',

  CALL_TYPE = 'deviceManagement.product.callTypeText',
  SERVICE_COMMAND = 'deviceManagement.product.inputDatText',
  INPUT_DATA = 'deviceManagement.product.inputDatText',
  OUTPUT_DATA = 'deviceManagement.product.outputDataText',

  EVENT_TYPE = 'deviceManagement.product.eventTypeText',
}

export const getFormSchemas = ({
  transportType,
  deviceRecord,
}: {
  transportType?: string;
  mode?: DataActionModeEnum;
  deviceRecord?: DeviceProfileDetail;
}): FormSchema[] => {
  const isTCPTransport = deviceRecord?.transportType === TransportTypeEnum.TCP;

  const { t } = useI18n();
  const isTCPModbusProduct =
    isTCPTransport &&
    deviceRecord?.profileData.transportConfiguration.protocol === TCPProtocolTypeEnum.MODBUS_RTU;

  const isTCPCustomProdcut =
    isTCPTransport &&
    deviceRecord?.profileData.transportConfiguration.protocol === TCPProtocolTypeEnum.CUSTOM;

  const deviceType = deviceRecord?.deviceType;

  return [
    {
      field: FormFieldsEnum.FUNCTION_TYPE,
      label: t(FormFieldsNameEnum.FUNCTION_TYPE),
      component: 'Segmented',
      defaultValue: FunctionTypeEnum.PROPERTIES,
      required: true,
      helpMessage: [t('deviceManagement.product.thingsModelDescText')],
      dynamicDisabled: () => {
        const { getModalMode } = useObjectModelFormContext();
        return unref(getModalMode) !== DataActionModeEnum.CREATE;
      },
      componentProps: ({ formActionType }) => {
        const isSensor = deviceRecord?.deviceType === DeviceTypeEnum.SENSOR;
        return {
          options: [
            { title: t(FunctionTypeNameEnum.PROPERTIES), value: FunctionTypeEnum.PROPERTIES },
            {
              title: t(FunctionTypeNameEnum.SERVICE),
              value: FunctionTypeEnum.SERVICE,
              disabled: (isTCPTransport && isSensor) || isTCPModbusProduct,
            },
            {
              title: t(FunctionTypeNameEnum.EVENTS),
              value: FunctionTypeEnum.EVENTS,
              disabled: isTCPTransport,
            },
          ],
          onChange() {
            const { setFieldsValue, clearValidate } = formActionType;
            setFieldsValue({
              [FormFieldsEnum.INPUT_DATA]: [],
              [FormFieldsEnum.OUTPUT_DATA]: [],
              [FormFieldsEnum.STRUCT_DATA]: [],
              [FormFieldsEnum.SERVICE_COMMAND]: null,
            });
            clearValidate();
          },
        };
      },
    },
    {
      field: FormFieldsEnum.DATA_TYPE_FORM,
      component: 'Input',
      label: '',
      ifShow: ({ model }) =>
        model[FormFieldsEnum.FUNCTION_TYPE] === FunctionTypeEnum.PROPERTIES && !isTCPModbusProduct,
      colSlot: FormFieldsEnum.DATA_TYPE_FORM,
    },
    createFunctionNameFormItem({
      ifShow: ({ model }) =>
        model[FormFieldsEnum.FUNCTION_TYPE] !== FunctionTypeEnum.PROPERTIES || isTCPModbusProduct,
    }),
    createIdentifierFormItem({
      helpMessage: [t('deviceManagement.product.identifierTCPHelpText')],
      ifShow: ({ model }) =>
        model[FormFieldsEnum.FUNCTION_TYPE] !== FunctionTypeEnum.PROPERTIES || isTCPModbusProduct,
      component: 'AutoComplete',
      defaultValue: '',
      componentProps: {
        options: isTCPModbusProduct ? [{ value: BuiltInIdentifierEnum.SOURCE }] : [],
        autocomplete: false,
      },
    }),
    {
      field: FormFieldsEnum.ACCESS_MODE,
      component: 'ApiRadioGroup',
      label: t(FormFieldsNameEnum.ACCESS_MODE),
      required: true,
      ifShow: ({ model }) =>
        ![FunctionTypeEnum.SERVICE, FunctionTypeEnum.EVENTS].includes(
          model[FormFieldsEnum.FUNCTION_TYPE]
        ) && !isTCPModbusProduct,
      defaultValue:
        isTCPCustomProdcut && deviceType !== DeviceTypeEnum.DIRECT_CONNECTION
          ? ObjectModelAccessModeEnum.READ
          : ObjectModelAccessModeEnum.READ_AND_WRITE,
      componentProps: {
        api: async (params) => {
          const res = await findDictItemByCode(params);

          // if (isTCPCustomProdcut && deviceType !== DeviceTypeEnum.DIRECT_CONNECTION) {
          //   res = res.filter((item) => item.itemValue === ObjectModelAccessModeEnum.READ);
          // }

          return res;
        },
        params: {
          dictCode: DictEnum.READ_WRITE_TYP,
        },
        labelField: 'itemText',
        valueField: 'itemValue',
      },
    },

    // 服务
    {
      field: FormFieldsEnum.CALL_TYPE,
      label: t(FormFieldsNameEnum.CALL_TYPE),
      component: 'RadioGroup',
      defaultValue: ServiceCallTypeEnum.ASYNC,
      required: true,
      ifShow: ({ model }) => model[FormFieldsEnum.FUNCTION_TYPE] === FunctionTypeEnum.SERVICE,
      componentProps: () => {
        return {
          options: Object.values(ServiceCallTypeEnum).map((value) => ({
            label: t(`enum.callType.${value}`),
            value,
          })),
        };
      },
    },
    {
      field: FormFieldsEnum.SERVICE_COMMAND,
      label: t(FormFieldsNameEnum.SERVICE_COMMAND),
      component: 'Input',
      required: true,
      rules: [{ required: true }, ...createHexCommandRuleValidator()],
      ifShow: ({ model }) =>
        model[FormFieldsEnum.FUNCTION_TYPE] === FunctionTypeEnum.SERVICE &&
        transportType === TransportTypeEnum.TCP,
      componentProps: () => {
        return {
          placeholder: t('deviceManagement.product.hexCommandRuleMessageText'),
        };
      },
    },
    {
      field: FormFieldsEnum.INPUT_DATA,
      label: t(FormFieldsNameEnum.INPUT_DATA),
      component: 'Input',
      slot: FormFieldsEnum.INPUT_DATA,
      changeEvent: 'update:value',
      valueField: 'value',
      required: true,
      ifShow: ({ model }) =>
        model[FormFieldsEnum.FUNCTION_TYPE] === FunctionTypeEnum.SERVICE &&
        transportType !== TransportTypeEnum.TCP,
    },

    // 事件
    {
      field: FormFieldsEnum.EVENT_TYPE,
      label: t(FormFieldsNameEnum.EVENT_TYPE),
      required: true,
      component: 'ApiRadioGroup',
      defaultValue: ObjectEventTypeEnum.INFO,
      ifShow: ({ model }) => model[FormFieldsEnum.FUNCTION_TYPE] === FunctionTypeEnum.EVENTS,
      componentProps: () => {
        return {
          api: findDictItemByCode,
          params: {
            dictCode: DictEnum.EVENT_TYPE,
          },
          labelField: 'itemText',
          valueField: 'itemValue',
          getPopupContainer: () => document.body,
        };
      },
    },
    {
      field: FormFieldsEnum.OUTPUT_DATA,
      label: t(FormFieldsNameEnum.OUTPUT_DATA),
      component: 'Input',
      slot: FormFieldsEnum.OUTPUT_DATA,
      changeEvent: 'update:value',
      valueField: 'value',
      ifShow: ({ model }) =>
        [FunctionTypeEnum.SERVICE, FunctionTypeEnum.EVENTS].includes(
          model[FormFieldsEnum.FUNCTION_TYPE]
        ),
    },

    // TCP Modbus
    {
      field: FormFieldsEnum.UNIT_NAME,
      label: FormFieldsNameEnum.UNIT_NAME,
      component: 'Input',
      show: false,
    },
    {
      field: FormFieldsEnum.UNIT,
      label: t(FormFieldsNameEnum.UNIT),
      component: 'ApiSelect',
      ifShow: () => isTCPModbusProduct,
      componentProps: ({ formActionType }) => {
        const { setFieldsValue } = formActionType;
        return {
          api: async (params: Recordable) => {
            const list = await findDictItemByCode(params);
            list.forEach((item) => (item.itemText = `${t(item.itemText)} / ${item.itemValue}`));
            return list;
          },
          params: {
            dictCode: DictEnum.ATTRIBUTE_UNIT,
          },
          labelField: 'itemText',
          valueField: 'itemValue',
          onChange(_, record: Record<'label' | 'value', string>) {
            if (record) {
              const { label } = record;
              setFieldsValue({ [FormFieldsEnum.UNIT_NAME]: label });
            }
          },
          getPopupContainer: () => document.body,
          showSearch: true,
          filterOption: (inputValue: string, option: Record<'label' | 'value', string>) => {
            let { label, value } = option;
            label = label.toLowerCase();
            value = value.toLowerCase();
            inputValue = inputValue.toLowerCase();
            return label.includes(inputValue) || value.includes(inputValue);
          },
        };
      },
    },
    {
      field: FormFieldsEnum.EXTENSION_DESC,
      component: 'Input',
      label: t(FormFieldsNameEnum.EXTENSION_DESC),
      slot: FormFieldsEnum.EXTENSION_DESC,
      helpMessage: [t('deviceManagement.product.extensionDescHelpText')],
      rules: [
        {
          required: true,
          validator(_rule, value: any) {
            return Object.values(value || {}).length
              ? Promise.resolve()
              : Promise.reject(t('deviceManagement.product.extensionDescRuleText'));
          },
        },
      ],
      ifShow: ({ model }) =>
        isTCPModbusProduct && model[FormFieldsEnum.IDENTIFIER] !== BuiltInIdentifierEnum.SOURCE,
    },

    {
      field: FormFieldsEnum.REMARK,
      label: t(FormFieldsNameEnum.REMARK),
      component: 'InputTextArea',
      componentProps: {
        rows: 4,
        maxLength: 100,
      },
    },
  ];
};