Ant Design实现导入 Excel 文件生成tbale列表

<template>
  <PageWrapper title="导入需要校验的 Excel 文件" content="请上传一个有效的 Excel 文件,将计算返回处理结果。">
    <div class="bg-white justify-center items-center">
      <a-upload-dragger
        v-model:fileList="fileList"
        name="file"
        :multiple="false"
        :show-upload-list="false"
        :before-upload="beforeUpload"
        :action="throttledUploadFile"
        :progress="progress" 
      >
        <p class="ant-upload-drag-icon">
          <InboxOutlined />
        </p>
        <p class="ant-upload-text">点击或拖拽文件到此区域上传</p>
        <p class="ant-upload-hint">支持上传一个 Excel 文件(.xls 或 .xlsx)</p>
      </a-upload-dragger>
      <!-- 显示上传进度 -->
      <a-progress
        v-if="uploadProgress > 0"
        :percent="uploadProgress"
        status="active"
        class="upload-progress"
      />
      <div v-if="loading" class="loading-text">文件导入中,请耐心等待...</div>
      <div v-if="responseData && responseData.length > 0" class="mt-4">
        <h3>计算结果:</h3>
        <a-table
          :columns="columns"
          :dataSource="responseData"
          :pagination="false"
          bordered
          class="full-table"
        >
          <template #bodyCell="{ column, index }">
            <span v-if="column.key === 'index'">{{ index + 1 }}</span>
          </template>
        </a-table>
      </div>
    </div>
  </PageWrapper>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import { PageWrapper } from '@/components/Page';
import { useMessage } from '@/hooks/web/useMessage';
import { InboxOutlined } from '@ant-design/icons-vue';
import { updateOldUserapi } from '@/api/demo/system'; 

const { createMessage } = useMessage();
const fileList = ref<any[]>([]);
const responseData = ref<any[]>([]);
const loading = ref(false); // 添加加载状态
const uploadProgress = ref(0); // 上传进度状态
const columns = ref([
  {
    title: '序号',
    dataIndex: 'index',
    key: 'index',
    width: 80,
    align: 'center',
  },
  {
    title: '查找结果',
    dataIndex: 'errorInfo',
    key: 'errorInfo',
    width: 180,
  },
  {
    title: '项目编码',
    dataIndex: 'projectNo',
    key: 'projectNo',
    width: 180,
    resizable: true,
  },
  {
    title: '项目名称',
    dataIndex: 'projectName',
    key: 'projectName',
    width: 380,
    resizable: true,
  },
]);

const beforeUpload = (file: File) => {
  const isExcel = file.type === 'application/vnd.ms-excel' || 
                  file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  if (!isExcel) {
    createMessage.error('只能上传 Excel 文件(.xls 或 .xlsx)!');
  }
  return isExcel;
};

// 定义节流函数
const throttle = (fn: Function, delay: number) => {
  let lastTime = 0;
  return function (...args: any[]) {
    const now = Date.now();
    if (now - lastTime >= delay) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
};

const uploadFile = async (file: File) => {
  loading.value = true; // 开始加载
  uploadProgress.value = 1; 

  const updateProgress = (percent: number) => {
    uploadProgress.value = percent;
  };

  try {
    for (let i = 40; i <= 90; i += 10) {
      await new Promise((resolve) => setTimeout(resolve, 700)); 
      updateProgress(i);
    }

    const result = await updateOldUserapi(file); 
    updateProgress(100);
    responseData.value = result.map((item: any, index: number) => ({
      index: index + 1, // 添加序号
      errorInfo: item.errorInfo || '无错误信息', // 默认值
      projectNo: item.projectNo,
      projectName: item.projectName,
    }));

    createMessage.success(`${file.name} 文件导入成功.`);
  } catch (error) {
    createMessage.error(`${file.name} 文件导入超时,请重新导入`);
  } finally {
    loading.value = false; 
    setTimeout(() => {
      uploadProgress.value = 0; 
    }, 500);
  }
};
const throttledUploadFile = throttle(uploadFile, 5000); 

// const handleDrop = (e: DragEvent) => {
//   const file = e.dataTransfer.files[0];
//   if (file) {
//     throttledUploadFile(file);
//   }
// };
</script>

<style scoped lang="less">
::v-deep .ant-table-thead > tr > th {
  background-color: #f3f9fd !important;
  color: #1a5174;
}

::v-deep .ant-table-tbody > tr > td {
  color: #1a5174;
}

.full-table {
  width: 100%; 
}

.loading-text {
  margin-top: 20px;
  color: #7ccd7d;
  font-size: 16px;
}

.upload-progress {
  margin-top: 20px;
  padding-right: 20px;
}
</style>

②封装的api     updateOldUserapi


import { defHttp } from '@/utils/http/axios';
import { ContentTypeEnum } from '@/enums/httpEnum';
import { ErrorMessageMode } from '#/axios';

enum Api {

  updateOldUser = '/projectOld/updateOldUser',
}

// 导入校验接口
export const updateOldUserapi = (file: File, mode: ErrorMessageMode = 'modal') => {
  const formData = new FormData();
  formData.append('file', file);
  return defHttp.post({
    url: Api.updateOldUser, 
    params: formData,
    headers: {
      'Content-Type': 'multipart/form-data',
    },
  }, { errorMessageMode: mode });
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值