Files
2026-10-11 19:06:33 +08:00

4.3 KiB
Raw Permalink Blame History

9.11 Excel 导入导出组件

:::tip 概述 本节介绍前端项目中的 Excel 导入导出组件,包括导入组件(ImportExcel)和导出功能(Export2Excel)的使用方法,并说明前端解析与后端导入两条链路的选择。 :::

导入组件(前端解析)

<template>
  <n-button @click="handleImport">导入</n-button>
  <ImportExcel @success="onImportSuccess" />
</template>

<script setup>
import ImportExcel from '@/components/Excel/src/ImportExcel.vue';

const onImportSuccess = (data) => {
  // data 为解析后的数组,每项是对象
  console.log(data);
};
</script>

:::tip 前端解析 vs 后端导入

  • 前端解析(本组件):xlsx 库本地解析,适合导入前预览、无业务校验的场景;
  • 后端导入(推荐):fileUpload 导入弹窗(内部 n-upload 直传 /api/{module}/import,自动携带 Bearer 头),由 Service 逐行 add()(字典反查、唯一校验、事务隔离、错误行明细),见 7.4 数据导入导出。 :::

后端导入对接

<template>
  <!-- 导入按钮 -->
  <n-button @click="importVisible = true" v-perm="['sys:example:import']">导入</n-button>

  <!-- 导入弹窗,templateCode 对应后端模板编码(来自项目实际的 example 模块) -->
  <fileUpload
    v-if="importVisible"
    v-model:visible="importVisible"
    api="/api/example/import"
    templateCode="example_import"
    dialogTitle="导入案例演示"
    @success="reloadTable()"
  />
</template>

<script setup>
import { ref } from 'vue';
import fileUpload from '@/components/importFile/index.vue';

const importVisible = ref(false);
</script>

fileUpload 组件(ui/src/components/importFile/index.vue)核心为 NaiveUI 上传弹窗:

<n-modal v-model:show="props.visible" preset="dialog">
  <n-upload
    :action="props.api"
    :headers="uploadHeaders"
    name="file"
    :max="1"
    v-model:file-list="fileList"
    @before-upload="beforeUpload"
  >
    <n-upload-dragger>
      <!-- 点击或将文件拖拽到这里上传 -->
    </n-upload-dragger>
  </n-upload>
  <n-button quaternary type="info" @click="handleDownload">下载模板</n-button>
</n-modal>

导入结果由组件统一反馈(useMessage 提示成功条数 / 失败明细,errors: [{ row, name, reason }]),成功后触发 @success 回调刷新列表。

导出功能(前端导出)

import { jsonToSheetXlsx } from '@/components/Excel/src/Export2Excel';

const handleExport = () => {
  jsonToSheetXlsx({
    data: tableData.value,
    header: {
      name: '名称',
      typeText: '类型',
      statusText: '状态',
      createTime: '创建时间',
    },
    filename: '导出数据.xlsx',
  });
};

后端导出对接(推荐)

// 调用后端导出接口,返回文件 URL(全量数据 + 权限控制 + 字典翻译)
const handleExport = async () => {
  const res = await exampleExport(searchParams.value);   // 文件地址
  window.open(res);
};

后端接口由 Controller::_export() 封装(#[OperationLog(TYPE_EXPORT)] + #[Permission] + ExcelService),大数据量时 Service 内改用 chunkExport 分批导出。

导入模板下载

// 下载导入模板
const handleDownloadTemplate = async () => {
  const url = await exampleExportTemplate();
  window.open(url);
};

导入导出注意事项

场景 说明
大数据量导出 后端 chunkExport 分批导出(回调取空终止),避免内存溢出
导入模板 第一行为表头,第二行起为数据(行号反馈 row = 索引 + 2)
字段映射 后端 headerMap 配置表头与字段的对应关系(未声明列忽略)
枚举翻译 导入时 DictCacheService::getValue 文本转值,导出时 serializeMaps 值转文本
文件限制 仅 xls/xlsx、10MB 上限、finfo MIME 检测(_import 内置)

两种方案选择

方式 适用场景 校验
前端 ImportExcel 解析 导入预览、轻量转换 仅格式解析
后端 /import 接口 正式导入 FormRequest/钩子/唯一性/字典全量校验

相关文档