ruoyi的excel批量导入

最简单方式

若依的官方文档提供了教程,可以按照起前后端的教学,进行代码编写

前段

组件

html 复制代码
    <!-- 导入对话框 -->
    <el-dialog
        title="导入数据"
        v-model="openImport"
        width="500px"
        append-to-body
    >
      <el-upload
          ref="uploadRef"
          class="upload-demo"
          :action="uploadFileUrl"
          accept=".xlsx, .xls"
          :headers="headers"
          :limit="1"
          :auto-upload="false"
          :on-success="uploadSuccess"
          :on-error="uploadError"
          :before-upload="beforeUpload"
      >
        <template #trigger>
          <el-button type="primary">选择文件</el-button>
        </template>

        <el-button class="ml-3" type="success" @click="submitUpload" style="margin-left: 20px">
          上传文件
        </el-button>

        <template #tip>
          <div class="el-upload__tip">
            请上传Excel文件,<el-link type="primary">点击下载模板</el-link>
          </div>
        </template>
      </el-upload>

    </el-dialog>

上传文件:有heads,上传的url必须是动态拼接的

js 复制代码
/** 导入文件 */
const uploadRef = ref({});
const headers = ref({Authorization: "Bearer " + getToken()}); // 请求头
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/manage/sku/import"); // 上传文件服务器地址
function submitUpload() {
  uploadRef.value.submit();
}

仿照若依的imageload改造,可以对上传的文件进行简单的校验

js 复制代码
/** 上传前校检格式和大小 */
const props = defineProps({
  modelValue: [String, Object, Array],
  // 大小限制(MB)
  fileSize: {
    type: Number,
    default: 1,
  },
  // 文件类型, 例如['xlsx', 'xls']
  fileType: {
    type: Array,
    default: () => ["xlsx", "xls"],
  },
});
function beforeUpload(file) {
  let isExcel = false;
  if (props.fileType.length) {
    let fileExtension = "";
    if (file.name.lastIndexOf(".") > -1) {
      fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
    }
    isExcel = props.fileType.some(type => {
      if (file.type.indexOf(type) > -1) return true;
      if (fileExtension && fileExtension.indexOf(type) > -1) return true;
      return false;
    });
  }

成功回调函数和失败回调函数

js 复制代码
/** 上传成功 */
function uploadSuccess(response, file, fileList) {
  if (response.code === 200) {
    proxy.$modal.msgSuccess("上传成功");
    openImport.value = false;
    getList();
  } else {
    proxy.$modal.msgError(response.msg);
  }
  // 上传成功后清空文件列表
  uploadRef.value.clearFiles();
  // 关闭提示信息
  proxy.$modal.closeLoading();
}

/** 上传失败 */
function uploadError(err) {
  proxy.$modal.msgError("上传失败");
  // 上传失败后清空文件列表
  uploadRef.value.clearFiles();
  // 关闭提示信息
  proxy.$modal.closeLoading();
}

controller层

java 复制代码
    /**
     * 商品导入
     */
    @PreAuthorize("@ss.hasPermi('manage:sku:import')")
    @Log(title = "商品管理", businessType = BusinessType.IMPORT)
    @PostMapping("/import")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<Sku> util = new ExcelUtil<Sku>(Sku.class);
        List<Sku> skuList = util.importExcel(file.getInputStream());
        String operName = SecurityUtils.getUsername();
        updateSupport = true;
        String message = skuService.importSkuList(skuList, updateSupport, operName);
        return AjaxResult.success(message);

    }

service层

java 复制代码
    /**
     * 导入商品数据
     *
     * @param skuList 商品数据列表
     * @param updateSupport 是否更新支持,如果已存在,则进行更新数据
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    public String importSkuList(List<Sku> skuList, boolean updateSupport, String operName) {
        if (CollUtil.isEmpty(skuList)) {
            throw new RuntimeException("导入数据不能为空!");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        for (Sku sku : skuList) {
            try {
                // 验证是否存在这个商品
                Sku queryEntity = new Sku();
                queryEntity.setSkuName(sku.getSkuName());
                List<Sku> existingSkuList = skuMapper.selectSkuList(queryEntity);

                Optional<List<Sku>> optionalSkuList = Optional.ofNullable(existingSkuList);
                if (optionalSkuList.isPresent() && !optionalSkuList.get().isEmpty()) {
                    if (!updateSupport) {
                        failureNum++;
                        failureMsg.append("<br/>").append(failureNum).append("、商品名称 ").append(sku.getSkuName()).append(" 已存在");
                        continue;
                    } else {
                        sku.setUpdateBy(operName);
                        // 根据名称获取skuId
                        sku.setSkuId(existingSkuList.get(0).getSkuId());
                        // 更新sku
                        skuMapper.updateSku(sku);
                    }
                } else {
                    sku.setCreateBy(operName);
                    sku.setUpdateBy(operName);
                    skuMapper.insertSku(sku);
                }
                successNum++;
                successMsg.append("<br/>").append(successNum).append("、商品名称 ").append(sku.getSkuName()).append(" 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、商品名称 " + sku.getSkuName() + " 导入失败:";
                failureMsg.append(msg).append(e.getMessage());
            }
        }

        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
            throw new RuntimeException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您,数据已全部导入成功!");
            if (successNum == 0) {
                successMsg.append("0条数据导入成功,数据已存在");
            }
        }
        return successMsg.toString();
    }
相关推荐
Agent世界2 小时前
用 CDP 做发布自动化:四道机器闸门与产物验收
前端·javascript
FungLeo2 小时前
成为全栈·Vue 管理后台篇·编辑器图片上传:从文件选择到文章附件关联
前端·vue.js·编辑器·markdown·文件上传·formdata·附件管理
总要学点什么2 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
某哈压力大2 小时前
SSH 突然 Connection reset?不是密钥坏了,是 OpenSSL 把 sshd 干趴了
前端·node.js·命令行
程序员大阳2 小时前
副队长ES6+教程(3)--解构赋值
前端·javascript·es6·赋值·解构
神膘护体小月半2 小时前
css - 元素背景图由 hover 触发,初次加载时闪动的解决办法
前端·javascript·css
程序员大阳3 小时前
副队长ES6+教程(2)--let 与 const
前端·javascript·es6·const·let·var
deli0073 小时前
写满 200GB 后 SSD 为什么掉到 95MB/s?SLC 缓存模型实测
前端
曦樂~4 小时前
【Web Development】03JavaScript 基础和事件
开发语言·前端·javascript
deli0074 小时前
HTTPS 的锁是怎么挂上的?TLS 1.3 握手 6 步实测
前端