BasicConfiguration.vue 7.56 KB
<script lang="ts" setup>
  import { CopyOutlined, DeleteOutlined, SettingOutlined } from '@ant-design/icons-vue';
  import { Tooltip, Button } from 'ant-design-vue';
  import { FormActionType, useForm } from '/@/components/Form';
  import { basicSchema, dataSourceSchema } from '../config/basicConfiguration';
  import BasicForm from '/@/components/Form/src/BasicForm.vue';
  import { ref, shallowReactive, unref, nextTick, watch } from 'vue';
  import VisualOptionsModal from './VisualOptionsModal.vue';
  import { useModal } from '/@/components/Modal';
  import { buildUUID } from '/@/utils/uuid';
  import type { ComponentInfo, DataSource } from '/@/api/dataBoard/model';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { DataBoardLayoutInfo } from '../../types/type';
  import { FrontComponent } from '../config/help';
  import { computed } from '@vue/reactivity';

  type DataSourceFormEL = { [key: string]: Nullable<FormActionType> };

  type DataSourceEl = DataSource & { id: string };

  const props = defineProps<{
    record: DataBoardLayoutInfo;
    frontId?: string;
    defaultConfig?: Partial<ComponentInfo>;
  }>();

  const { createMessage } = useMessage();

  const dataSource = ref<DataSourceEl[]>([
    { id: buildUUID(), componentInfo: props.defaultConfig || {} } as unknown as DataSourceEl,
  ]);

  const [basicRegister, basicMethod] = useForm({
    schemas: basicSchema,
    showActionButtonGroup: false,
    labelWidth: 96,
  });

  const dataSourceEl = shallowReactive<DataSourceFormEL>({} as unknown as DataSourceFormEL);

  const setFormEl = (el: any, id: string) => {
    if (!dataSourceEl[id] && el) {
      const { formActionType } = el as unknown as { formActionType: FormActionType };
      dataSourceEl[id] = formActionType;
    }
  };

  const validate = async () => {
    await basicMethod.validate();
    await validateDataSourceField();
  };

  const getAllDataSourceFieldValue = () => {
    const _dataSource = getDataSourceField();
    const basicInfo = basicMethod.getFieldsValue();
    return {
      ...basicInfo,
      dataSource: _dataSource,
    };
  };

  const validateDataSourceField = async () => {
    const hasExistEl = Object.keys(dataSourceEl).filter((key) => dataSourceEl[key]);
    const _dataSource: boolean[] = [];
    for (const id of hasExistEl) {
      const flag = (await (dataSourceEl[id] as FormActionType).validate()) as boolean;
      _dataSource.push(flag);
    }
    return _dataSource;
  };

  const getDataSourceField = () => {
    const hasExistEl = Object.keys(dataSourceEl).filter((key) => dataSourceEl[key]);
    const _dataSource: DataSource[] = [];
    for (const id of hasExistEl) {
      const index = unref(dataSource).findIndex((item) => item.id === id);
      const value = (dataSourceEl[id] as FormActionType).getFieldsValue() as DataSource;
      if (!~index) continue;
      const componentInfo = unref(dataSource)[index].componentInfo || {};
      _dataSource.unshift({
        ...value,
        componentInfo: { ...(props.defaultConfig || {}), ...componentInfo },
      });
    }
    return _dataSource;
  };

  const handleCopy = async (data: DataSourceEl) => {
    const value = (dataSourceEl[data.id] as FormActionType).getFieldsValue() as DataSource;
    const index = unref(dataSource).findIndex((item) => item.id === data.id);

    const componentInfo = ~index
      ? unref(dataSource)[index].componentInfo
      : ({} as unknown as ComponentInfo);

    const copyRecordId = buildUUID();
    unref(dataSource).push({
      ...value,
      id: copyRecordId,
      componentInfo,
    });
    await nextTick();
    (dataSourceEl[copyRecordId] as FormActionType).setFieldsValue(value);
    (dataSourceEl[copyRecordId] as FormActionType).clearValidate();
  };

  const [registerVisualOptionModal, { openModal }] = useModal();

  const handleSetting = (item: DataSourceEl) => {
    if (!props.frontId) {
      createMessage.warning('请先选择可视化组件');
      return;
    }

    // const defaultConfig = getComponentDefaultConfig(props.frontId as WidgetComponentType);

    const componentInfo: ComponentInfo = {
      ...(props.defaultConfig || {}),
      ...(item.componentInfo || {}),
    };

    openModal(true, {
      recordId: item.id,
      componentInfo,
    });
  };

  const handleDelete = (data: DataSourceEl) => {
    const index = unref(dataSource).findIndex((item) => item.id === data.id);
    ~index && unref(dataSource).splice(index, 1);
    dataSourceEl[data.id] = null;
  };

  const handleAdd = () => {
    unref(dataSource).push({
      id: buildUUID(),
      componentInfo: props.defaultConfig || {},
    } as unknown as DataSourceEl);
  };

  const echoDataSource = () => {
    basicMethod.setFieldsValue(props.record.record);
    basicMethod.clearValidate();
    dataSource.value = [];
    dataSource.value = props.record.record.dataSource.map((item) => {
      const id = buildUUID();

      dataSource.value.push({
        id,
        ...item,
      });

      nextTick(() => {
        (dataSourceEl[id] as FormActionType).setFieldsValue(item);
        (dataSourceEl[id] as FormActionType).clearValidate();
      });
      return {
        id,
        ...item,
      };
    });
  };

  const showSettingButton = computed(() => {
    return props.frontId !== FrontComponent.PICTURE_COMPONENT_1;
  });

  watch(
    () => props.record,
    () => {
      if (Object.keys(props.record).length) echoDataSource();
    }
  );

  const handleRowComponentInfo = (recordId: string, value: ComponentInfo) => {
    const index = unref(dataSource).findIndex((item) => item.id === recordId);
    ~index && (unref(dataSource)[index].componentInfo = value);
  };

  defineExpose({
    getAllDataSourceFieldValue,
    validate,
  });
</script>

<template>
  <section>
    <h3 class="w-24 text-right pr-2 my-4">基础信息</h3>
    <div class="w-3/4">
      <BasicForm @register="basicRegister" class="w-full" />
    </div>
    <h3 class="w-24 flex-shrink-0 text-right pr-2 my-4">选择数据源</h3>
    <div v-for="item in dataSource" :key="item.id" class="flex">
      <div
        class="w-24 text-right leading-30px pr-8px flex right"
        style="flex: 0 0 96px; justify-content: right"
      >
        选择设备
      </div>
      <div class="pl-2 flex-auto">
        <BasicForm
          :ref="(el) => setFormEl(el, item.id)"
          :schemas="dataSourceSchema"
          class="w-full flex-1 data-source-form"
          :show-action-button-group="false"
          :row-props="{
            gutter: 10,
          }"
          layout="inline"
          :label-col="{ span: 0 }"
        />
      </div>
      <div class="flex justify-center gap-3 w-24">
        <Tooltip title="复制">
          <CopyOutlined @click="handleCopy(item)" class="cursor-pointer text-lg !leading-32px" />
        </Tooltip>
        <Tooltip title="设置">
          <SettingOutlined
            v-show="showSettingButton"
            @click="handleSetting(item)"
            class="cursor-pointer text-lg !leading-32px"
          />
        </Tooltip>
        <Tooltip title="删除">
          <DeleteOutlined
            @click="handleDelete(item)"
            class="cursor-pointer text-lg !leading-32px"
          />
        </Tooltip>
      </div>
    </div>
    <div class="text-center">
      <Button type="primary" @click="handleAdd">添加数据源</Button>
    </div>
    <VisualOptionsModal
      :value="props.frontId"
      @close="handleRowComponentInfo"
      @register="registerVisualOptionModal"
    />
  </section>
</template>

<style scoped>
  .data-source-form:deep(.ant-row) {
    width: 100%;
  }

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