upload-data.tsx 8.87 KB
import React, { useState, useEffect } from 'react';
import { Button, message, Progress, Radio, Upload } from 'antd';
import { CloudUploadOutlined, DeleteOutlined } from '@ant-design/icons';
import type { UploadChangeParam } from 'antd/lib/upload';
import {
  exportProgress,
  getImportTemplate,
  importDataUpload,
} from '../../services';
import QxUtils from '@qx/utils';
import { handleDownload } from '@/libs/htmlHandle';

const { Dragger } = Upload;

interface UploadDataProps {
  changeTaskId: any;
  changeImportWay: any;
  changeNext: any;
  changeFinish: any;
  appCode: string;
  funCode: string;
  viewCode: string;
}
const plainOptions = [
  { label: '新增导入', value: 'add' },
  { label: '更新导入', value: 'edit' },
];

const UploadData: React.FC<UploadDataProps> = (props) => {
  const {
    changeImportWay = () => {},
    changeTaskId = () => {},
    changeNext = () => {},
    changeFinish = () => {},
    appCode,
    funCode,
    viewCode,
  } = props;
  const [status, setStatus] = useState<string>('add');
  const [progressData, setProgressData] = useState<any>();
  const [infoStatus, setInfoStatus] = useState<boolean>(false);
  const [intervalName, setIntervalName] = useState<any>();
  const [taskId, setTaskId] = useState<string>('');
  const [fileInfo, setFileInfo] = useState<{
    name: string;
    size: number | undefined;
  }>({
    name: '',
    size: 0,
  });
  const [loading, setLoading] = useState<boolean>(false);
  useEffect(() => {
    if (status) {
      changeImportWay(status);
    }
  }, [status]);
  const changeStatus = (value: string) => {
    setStatus(value);
  };
  const handleUpload = async (v: UploadChangeParam) => {
    setLoading(true);
    try {
      setFileInfo({
        name: v.file.name,
        size: v.file.size,
      });
      const result = await importDataUpload(
        appCode,
        funCode,
        viewCode,
        [v.file][0],
      );
      if (result.status === 'FAIL') {
        setLoading(false);
        if (result.finalMsg) {
          message.error(result.finalMsg);
        }
        setProgressData({
          percent: 0,
          status: '',
          finalMsg: result.finalMsg || '',
          taskId: '',
        });
      } else if (result.status === 'SUCCESS') {
        setLoading(false);
        //导入成功,刷新列表
        setProgressData({
          percent: 100,
          status: 'SUCCESS',
          taskId: result.taskId,
        });
      } else if (result.status === 'PROCESSING') {
        setProgressData({
          percent: result.percent,
          status: 'PROCESSING',
          taskId: '',
        });
      }
    } catch (e) {
      setLoading(false);
      //导入出错、响应超时等
      setProgressData({
        percent: 0,
        status: '',
        taskId: '',
      });
    }
  };
  const exportData = (taskType: string) => {
    // taskType: UPLOAD || EXPORT
    exportProgress(appCode, funCode, viewCode, taskType)
      .then((res) => {
        setLoading(false);
        setProgressData(res || null);
        if (res.percent === '100' && res.status === 'SUCCESS') {
          clearInterval(intervalName);
          setIntervalName(null);
        } else if (res.status !== 'PROCESSING') {
          clearInterval(intervalName);
          setIntervalName(null);
        }
      })
      .catch(() => {
        clearInterval(intervalName);
        setIntervalName(null);
        setLoading(false);
      });
  };
  useEffect(() => {
    if (progressData) {
      if (progressData.status === 'PROCESSING' && !intervalName) {
        setIntervalName(setInterval(() => exportData('UPLOAD'), 3000));
        return;
      }
      if (progressData.status !== 'PROCESSING') {
        if (intervalName) {
          clearInterval(intervalName);
          setIntervalName(null);
        }

        if (progressData.status === 'SUCCESS') {
          setTimeout(() => {
            setInfoStatus(true);
            setTaskId(progressData.taskId);
            changeTaskId(progressData.taskId);
            setIntervalName(null);
            setTimeout(() => {
              changeNext(1);
            }, 500);
          }, 100);
        }
      }
    }
  }, [progressData]);

  const downTemplate = () => {
    handleDownload(
      getImportTemplate(appCode, funCode, viewCode),
      '模板文件.xlsx',
    );
  };

  return (
    <>
      <div className={'qx-import-step'}>
        <div className={'qx-import-step-title'}>1、数据导入</div>
        <div className={'qx-import-step-status'}>
          导入方式:
          <Radio.Group
            disabled={loading}
            options={plainOptions}
            onChange={(e) => changeStatus(e.target.value)}
            value={status}
          />
        </div>
        <div className={'qx-import-step-describe'}>
          <ul>
            <li>
              <div>·</div>
              {status === 'add' ? (
                <div>
                  为保证数据导入顺利,请先下载{' '}
                  <span onClick={() => downTemplate()}>导入模板</span>;
                </div>
              ) : (
                <div>请先导出需要更新的数据,修改后再进行更新导入</div>
              )}
            </li>
            <li>
              <div>·</div>
              <div>导入文件只支持.xls和.xlsx格式;</div>
            </li>
            <li>
              <div>·</div>
              <div>
                数据模版中只有可填写的字段,不包含附件、图片、创建人、创建时间、更新人、更新时间、流水号、关联属性、
                公式、标题备注、分隔线字段;
              </div>
            </li>
            <li>
              <div style={{ marginTop: 3 }}>·</div>
              <div className={'more-describe'}>
                <div>同时导入主子表数据,且一条主表数据有多条子表数据时:</div>
                <div>1、只需填写第一个子表数据行的主表数据;</div>
                <div>
                  2、注意:如果多条子表数据都填写了主表数据,系统会生成多条主表数据;
                </div>
              </div>
            </li>
            {status === 'edit' && (
              <li>
                <div>·</div>
                <div>
                  更新导入时根据数据ID匹配找到系统中已有数据,并对其进行更新。
                </div>
              </li>
            )}
          </ul>
        </div>
      </div>
      <div className={'qx-import-step'}>
        <div className={'qx-import-step-title'}>2、上传文件</div>
        <div className={'qx-import-step-upload'}>
          {progressData?.percent ? (
            <>
              {infoStatus ? (
                <div className={'qx-import-step-upload-file'}>
                  <span style={{ display: 'inline-block' }}>
                    {fileInfo.name} (
                    {QxUtils.formatBytes(Number(fileInfo.size), 2)})
                  </span>
                  <DeleteOutlined
                    onClick={() => {
                      setProgressData({});
                      setInfoStatus(false);
                      setFileInfo({
                        name: '',
                        size: 0,
                      });
                      setTaskId('');
                      changeTaskId('');
                    }}
                  />
                </div>
              ) : (
                <Progress percent={progressData.percent} status={'active'} />
              )}
            </>
          ) : (
            <Dragger
              name="file"
              accept=".xlsx,.xls"
              fileList={[]}
              beforeUpload={() => false}
              onChange={handleUpload}
            >
              <div className={'qx-import-step-upload-drag'}>
                <CloudUploadOutlined
                  style={{ fontSize: 18, color: '#3499FF' }}
                />
                <span className={'drag-span'} style={{ color: '#999' }}>
                  点击或拖拽上传文件
                </span>
              </div>
            </Dragger>
            // <Upload
            //   name="file"
            //   accept=".xlsx"
            //   fileList={fileList}
            //   beforeUpload={() => false}
            //   onChange={handleUpload}
            //   disabled={fileList.length > 1}
            // >
            //   <Button block>
            //     <CloudUploadOutlined style={{ fontSize: 18, color: '#3499FF' }} />
            //     <span style={{ color: '#999' }}>点击或拖拽上传文件</span>
            //   </Button>
            // </Upload>
          )}
        </div>
      </div>
      <div className={'qx-import-button'}>
        <Button onClick={changeFinish}>取消</Button>
        <Button
          disabled={!taskId || loading}
          type="primary"
          onClick={() => changeNext(1)}
        >
          下一步
        </Button>
      </div>
    </>
  );
};

export default UploadData;