index.vue 6.76 KB
<script lang="ts" setup>
  import { h } from 'vue';
  import { getMeetTheConditionsDevice } from '/@/api/dataBoard';
  import { getOrganizationList } from '/@/api/system/system';
  import { BasicForm, useForm } from '/@/components/Form';
  import { copyTransFun } from '/@/utils/fnUtils';
  import { Tooltip } from 'ant-design-vue';
  import { watch } from 'vue';
  import { nextTick } from 'vue';
  import { getDeviceProfile } from '/@/api/alarm/position';
  import { findDictItemByCode } from '/@/api/system/dict';
  import { DictEnum } from '/@/enums/dictEnum';
  import { FormFieldsEnum } from '.';
  import { isObject } from '/@/utils/is';
  import { createPickerSearch } from '/@/utils/pickerSearch';

  const props = withDefaults(
    defineProps<{
      value?: Recordable;
      multiple?: boolean;
      max?: 3;
    }>(),
    {
      value: () => ({}),
      multiple: false,
    }
  );

  const emit = defineEmits(['update:value', 'change']);

  const handleChange = (key: string, value: string | string[], option: Recordable) => {
    emit('change', key, value, option);
  };

  // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
  const createMaxTagPlaceholder = (omittedValues: Record<'label' | 'value', string>[]) => {
    return h(
      Tooltip,
      {},
      {
        default: () => h('span', `+${omittedValues.length}...`),
        title: () => h('span', 'other'),
      }
    );
  };

  const handleEmit = async (key: string, value: string | string[], option: Recordable) => {
    await nextTick();
    let _value = getFieldsValue();
    _value = {
      ..._value,

      ...(key === FormFieldsEnum.DEVICE_TYPE
        ? {
            [FormFieldsEnum.DEVICE_PROFILE]: null,
            [FormFieldsEnum.ORGANIZATION]: null,
            [FormFieldsEnum.DEVICE]: props.multiple ? [] : null,
          }
        : {}),

      ...(key === FormFieldsEnum.DEVICE_PROFILE
        ? {
            [FormFieldsEnum.ORGANIZATION]: null,
            [FormFieldsEnum.DEVICE]: props.multiple ? [] : null,
          }
        : {}),

      ...(key === FormFieldsEnum.ORGANIZATION
        ? {
            [FormFieldsEnum.DEVICE]: props.multiple ? [] : null,
          }
        : {}),
    };
    handleChange(key, value, option);
    emit('update:value', { ..._value });
  };
  const [register, { setFieldsValue, getFieldsValue, resetFields }] = useForm({
    schemas: [
      {
        field: FormFieldsEnum.DEVICE_TYPE,
        component: 'ApiSelect',
        label: '',
        componentProps: () => {
          return {
            api: findDictItemByCode,
            params: {
              dictCode: DictEnum.DEVICE_TYPE,
            },
            labelField: 'itemText',
            valueField: 'itemValue',
            placeholder: '请选择设备类型',
            onChange(value: string, option: Recordable) {
              handleEmit(FormFieldsEnum.DEVICE_TYPE, value, option);
            },
            getPopupContainer: () => document.body,
            ...createPickerSearch(),
          };
        },
      },
      {
        field: FormFieldsEnum.DEVICE_PROFILE,
        component: 'ApiSelect',
        label: '',
        componentProps: ({ formModel }) => {
          const deviceType = Reflect.get(formModel, FormFieldsEnum.DEVICE_TYPE);
          return {
            api: async () => {
              try {
                return await getDeviceProfile(deviceType);
              } catch (error) {
                return [];
              }
            },
            placeholder: '请选择产品',
            labelField: 'name',
            valueField: 'id',
            onChange(value: string, options: Recordable) {
              handleEmit(FormFieldsEnum.DEVICE_PROFILE, value, options);
            },
            getPopupContainer: () => document.body,
            ...createPickerSearch(),
          };
        },
      },
      {
        field: FormFieldsEnum.ORGANIZATION,
        component: 'ApiTreeSelect',
        label: '',
        componentProps: () => {
          return {
            api: async () => {
              try {
                const data = await getOrganizationList();
                copyTransFun(data as any);
                return data;
              } catch (error) {
                console.error(error);
                return [];
              }
            },
            placeholder: '请选择组织',
            labelField: 'name',
            valueField: 'id',
            childField: 'children',
            onChange(value: string, option: Recordable) {
              handleEmit(FormFieldsEnum.ORGANIZATION, value, option);
            },
            dropdownStyle: { maxHeight: '300px' },
            getPopupContainer: () => document.body,
          };
        },
      },
      {
        field: FormFieldsEnum.DEVICE,
        label: '',
        component: 'ApiSelect',
        componentProps: ({ formModel }) => {
          const deviceType = Reflect.get(formModel, FormFieldsEnum.DEVICE_TYPE);
          const deviceProfileId = Reflect.get(formModel, FormFieldsEnum.DEVICE_PROFILE);
          const organizationId = Reflect.get(formModel, FormFieldsEnum.ORGANIZATION);
          return {
            api: async () => {
              try {
                if (!organizationId) return [];
                const result = await getMeetTheConditionsDevice({
                  deviceProfileId,
                  deviceType,
                  organizationId,
                });
                return result.map((item) => ({
                  ...item,
                  value: item.tbDeviceId,
                  label: item.alias || item.name,
                }));
              } catch (error) {
                return [];
              }
            },
            mode: props.multiple ? 'multiple' : 'combobox',
            placeholder: '请选择设备',
            maxTagCount: 3,
            maxTagTextLength: 4,
            onChange(value: string, option: Recordable) {
              handleEmit(FormFieldsEnum.DEVICE, value, option);
            },
            getPopupContainer: () => document.body,
            ...createPickerSearch(),
          };
        },
      },
    ],
    showActionButtonGroup: false,
    layout: 'inline',
    baseColProps: { span: 6 },
  });

  const setValue = async () => {
    await nextTick();
    if (!props.value || (isObject(props.value) && !Object.values(props.value).length)) {
      resetFields();
      return;
    }
    setFieldsValue(props.value);
  };

  watch(
    () => props.value,
    () => {
      setValue();
    },
    {
      immediate: true,
    }
  );
</script>

<template>
  <BasicForm @register="register" class="device-picker" />
</template>

<style lang="less" scoped>
  .device-picker {
    :deep(.ant-row) {
      width: 100%;
    }

    :deep(.ant-form-item-control-input-content) {
      div > div {
        width: 100%;
      }
    }
  }
</style>