SelectImport.vue 6.79 KB
<template>
  <BasicModal
    title="导入物模型"
    :maskClosable="false"
    destroyOnClose
    v-bind="$attrs"
    width="25rem"
    :min-height="150"
    @register="register"
    @cancel="handleCancel"
    :showOkBtn="false"
  >
    <BasicForm @register="registerForm">
      <template #importType="{ model }">
        <RadioGroup v-model:value="model.importType">
          <Authority :value="['api:yt:things_model:category:import', 'api:yt:things_model:import']">
            <Radio value="2">JSON导入</Radio>
          </Authority>
          <Authority :value="['api:yt:things_model:excel_import']">
            <Radio value="1">Excel导入</Radio>
          </Authority>
        </RadioGroup>
        <div v-if="model.importType === '1'" class="absolute -left-28">
          <Button @click="handleTemplateDownload" type="link">excel模板下载</Button>
        </div>
      </template>
    </BasicForm>
  </BasicModal>
</template>
<script lang="ts" setup>
  import { ref, unref } from 'vue';
  import { Button, Radio, RadioGroup } from 'ant-design-vue';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { DeviceRecord } from '/@/api/device/model/deviceModel';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { isObject, isString } from '/@/utils/is';
  import {
    importCsvCategory,
    importModelCategory,
    importModelOfMatter,
    importCsvDeviceProfileId,
    excelExport,
  } from '/@/api/device/modelOfMatter';
  import { useLoading } from '/@/components/Loading';
  import { BasicForm, useForm } from '/@/components/Form';
  import { Authority } from '/@/components/Authority';
  import { usePermission } from '/@/hooks/web/usePermission';

  const emits = defineEmits(['register', 'handleImportCSV', 'handleReload']);

  defineProps<{
    record: DeviceRecord;
  }>();

  const { createMessage } = useMessage();
  const loadingRef = ref();
  const [openLoading, closeLoading] = useLoading({
    target: loadingRef,
    props: {
      tip: '加载中',
      absolute: true,
    },
  });

  const isEmptyObject = (value: any) => isObject(value) && !Object.keys(value).length;

  const ImportInfo = ref<{ id?: string; isCateGory?: string | Boolean }>({});

  const [register, { closeModal }] = useModalInner(async (data) => {
    ImportInfo.value = data;
  });

  const { hasPermission } = usePermission();

  const [registerForm, { validate }] = useForm({
    schemas: [
      {
        field: 'importType',
        label: '导入类型',
        component: 'RadioGroup',
        slot: 'importType',
        defaultValue: hasPermission([
          'api:yt:things_model:category:import',
          'api:yt:things_model:import',
        ])
          ? '2'
          : '1',
        helpMessage:
          'JSON导入请使用从物模型TSL导出的JSON文件在进行导入,Excel导入请使用下载的模板编辑之后在进行导入',
        required: true,
      },
      {
        field: 'apiId',
        label: '',
        component: 'ApiUpload',
        ifShow: ({ model }) => model.importType,
        componentProps: ({ formModel }) => {
          return {
            maxFileLimit: 1,
            accept: formModel.importType == 2 ? '.json,' : '.csv,.xls,.xlsx',
            api: async (file: File) => {
              try {
                if (formModel.importType == 2) {
                  handleImportModel(file);
                } else {
                  handleCSVImport(file);
                }
                return {
                  uid: '',
                  name: '',
                };
              } catch {}
            },
          };
        },
      },
    ],
    labelWidth: 100,
    showActionButtonGroup: false,
  });

  // 导入loading
  const importLoading = ref(false);

  const paseJSON = (string: string) => {
    let data = null;
    let flag = false;
    try {
      if (!isString(string)) return { flag: false, data };
      data = JSON.parse(string);
      flag = true;
      if (!isObject(data)) flag = false;
    } catch (error) {}
    return { flag, data };
  };

  // JSON导入
  const handleImportModel = async (file: File) => {
    await validate();
    const fileReader = new FileReader();
    const { isCateGory, id } = unref(ImportInfo);

    fileReader.onload = async () => {
      const { flag, data } = paseJSON(fileReader.result as string);
      if (!flag) {
        createMessage.warning('JSON解析失败,请导入正确的JSON');
        return;
      }
      openLoading();
      try {
        importLoading.value = true;

        Object.keys(data || {}).forEach((key) => {
          const value = (data || {})[key];
          if (value && isEmptyObject(value)) {
            (data || {})[key] = [];
          }
        });

        const result = isCateGory
          ? await importModelCategory({
              categoryId: id,
              data: data!,
              functionType: 'all',
            })
          : await importModelOfMatter({
              tkDeviceProfileId: id,
              data: data!,
              functionType: 'all',
            });

        result
          ? createMessage.success('导入成功~')
          : createMessage.error('JSON解析失败,请导入正确的JSON');

        result && emits('handleReload');
      } catch (error) {
        throw error;
      } finally {
        importLoading.value = false;
        closeLoading();
        closeModal();
      }
    };

    fileReader.readAsText(file, 'utf-8');
  };

  // CSV导入
  const handleCSVImport = async (file) => {
    await validate();
    const { isCateGory, id } = unref(ImportInfo);

    try {
      openLoading();
      const formData = new FormData();
      formData.set('file', file);
      const flag = isCateGory
        ? await importCsvCategory({ categoryId: id, deviceProfileId: undefined, file: formData })
        : await importCsvDeviceProfileId({
            categoryId: undefined,
            deviceProfileId: id,
            file: formData,
          });
      flag && createMessage.info(flag?.message);
    } catch (msg) {
      console.error(msg, 'msg');
    } finally {
      closeLoading();
      closeModal();
      emits('handleReload');
    }
  };

  const downloadFile = (data: Blob, fileName: string, ext: string) => {
    const objectURL = URL.createObjectURL(data);
    const element = document.createElement('a');
    element.href = objectURL;
    element.download = `${fileName}.${ext}`;
    element.style.display = 'none';
    document.body.appendChild(element);
    element.click();
    element.remove();
    URL.revokeObjectURL(objectURL);
  };

  // 模板下载
  const handleTemplateDownload = async () => {
    const res = await excelExport();
    downloadFile(res, '物模型属性导入模板', 'xls');
  };

  const handleCancel = () => {
    closeModal();
  };
</script>

<style lang="less" scoped>
  :deep(.ant-form-item) {
    margin-bottom: 28px !important;
  }
</style>