样本导入功能
This commit is contained in:
parent
f00ef3c082
commit
e6c769c141
|
|
@ -5,15 +5,35 @@ import com.bonus.common.annotation.SysLog;
|
||||||
import com.bonus.common.core.controller.BaseController;
|
import com.bonus.common.core.controller.BaseController;
|
||||||
import com.bonus.common.core.domain.AjaxResult;
|
import com.bonus.common.core.domain.AjaxResult;
|
||||||
import com.bonus.common.core.page.TableDataInfo;
|
import com.bonus.common.core.page.TableDataInfo;
|
||||||
|
import com.bonus.common.domain.data.dto.SampleDto;
|
||||||
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
||||||
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
||||||
import com.bonus.common.enums.OperaType;
|
import com.bonus.common.enums.OperaType;
|
||||||
|
import com.bonus.common.utils.FileUtil;
|
||||||
|
import com.bonus.file.config.MinioConfig;
|
||||||
|
import com.bonus.file.util.MinioUtil;
|
||||||
import com.bonus.web.service.data.SampleService;
|
import com.bonus.web.service.data.SampleService;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||||
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @className:SampleController
|
* @className:SampleController
|
||||||
|
|
@ -29,6 +49,12 @@ public class SampleController extends BaseController {
|
||||||
@Resource(name = "SampleService")
|
@Resource(name = "SampleService")
|
||||||
private SampleService sampleService;
|
private SampleService sampleService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MinioUtil minioUtil;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MinioConfig minioConfig;
|
||||||
|
|
||||||
@ApiOperation(notes = "查询样本库列表数据",value = "查询样本库列表数据")
|
@ApiOperation(notes = "查询样本库列表数据",value = "查询样本库列表数据")
|
||||||
@RequiresPermissions("data:sample:list")
|
@RequiresPermissions("data:sample:list")
|
||||||
@GetMapping("/getSampleList")
|
@GetMapping("/getSampleList")
|
||||||
|
|
@ -70,4 +96,119 @@ public class SampleController extends BaseController {
|
||||||
return sampleService.delLabelData(dto);
|
return sampleService.delLabelData(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "导入样本ZIP包", notes = "批量导入ZIP内的图片文件到指定样本库(支持多层ZIP嵌套+中文文件名)")
|
||||||
|
@PostMapping("/importSampleFile")
|
||||||
|
@SysLog(title = "数据管理", module = "数据管理->样本库管理->导入样本", businessType = OperaType.IMPORT, details = "导入样本ZIP包", logType = 1)
|
||||||
|
@RequiresPermissions("data:sample:import")
|
||||||
|
public AjaxResult importSampleFile(
|
||||||
|
@RequestParam("sampleLibraryId") Long sampleLibraryId,
|
||||||
|
@RequestParam("file") MultipartFile file) {
|
||||||
|
// 1. 基础参数校验
|
||||||
|
if (sampleLibraryId == null || file.isEmpty()) {
|
||||||
|
return AjaxResult.error("样本库ID和ZIP文件不能为空");
|
||||||
|
}
|
||||||
|
String fileName = file.getOriginalFilename();
|
||||||
|
if (fileName == null || !fileName.toLowerCase().endsWith(".zip")) {
|
||||||
|
return AjaxResult.error("仅支持上传ZIP格式文件");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 解析ZIP包(支持多层嵌套+UTF-8编码),并上传图片到MinIO生成filePath
|
||||||
|
List<SampleDto> sampleList = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
// 先将MultipartFile缓存为字节数组,避免流被多次消费
|
||||||
|
byte[] zipBytes = file.getBytes();
|
||||||
|
try (InputStream inputStream = new ByteArrayInputStream(zipBytes)) {
|
||||||
|
parseNestedZipWithUtf8(inputStream, "", sampleList);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return AjaxResult.error("解析ZIP文件失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 校验有效文件数量
|
||||||
|
if (sampleList.isEmpty()) {
|
||||||
|
return AjaxResult.error("ZIP包内未检测到有效图片文件(仅支持jpg/png/jpeg)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 调用业务层导入(仅入库filePath)
|
||||||
|
return sampleService.importSampleFile(sampleLibraryId, getUserId(), sampleList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归解析多层嵌套的ZIP文件,上传图片到MinIO并生成filePath
|
||||||
|
* @param inputStream 当前ZIP的输入流
|
||||||
|
* @param parentPath 父级路径(标识嵌套层级)
|
||||||
|
* @param sampleList 存储有效图片的列表
|
||||||
|
*/
|
||||||
|
private void parseNestedZipWithUtf8(InputStream inputStream, String parentPath, List<SampleDto> sampleList) {
|
||||||
|
// 支持的图片格式
|
||||||
|
List<String> validImageSuffix = Arrays.asList("jpg", "png", "jpeg");
|
||||||
|
|
||||||
|
try (ZipArchiveInputStream zais = new ZipArchiveInputStream(
|
||||||
|
inputStream,
|
||||||
|
StandardCharsets.UTF_8.name(), // 指定UTF-8编码
|
||||||
|
true, // 允许非标准ZIP格式
|
||||||
|
true // 解析注释
|
||||||
|
)) {
|
||||||
|
ZipArchiveEntry entry;
|
||||||
|
while ((entry = zais.getNextZipEntry()) != null) {
|
||||||
|
// 跳过文件夹
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接完整路径(含嵌套层级)
|
||||||
|
String entryFullName = parentPath + entry.getName();
|
||||||
|
int suffixIndex = entryFullName.lastIndexOf(".");
|
||||||
|
if (suffixIndex == -1 || suffixIndex == entryFullName.length() - 1) {
|
||||||
|
continue; // 无后缀/后缀为空,跳过
|
||||||
|
}
|
||||||
|
String suffix = entryFullName.substring(suffixIndex + 1).toLowerCase();
|
||||||
|
|
||||||
|
// 情况1:当前是ZIP文件 → 递归解析
|
||||||
|
if ("zip".equals(suffix)) {
|
||||||
|
// 完整读取子ZIP的字节
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
IOUtils.copy(zais, baos);
|
||||||
|
byte[] zipBytes = baos.toByteArray();
|
||||||
|
// 递归解析子ZIP
|
||||||
|
parseNestedZipWithUtf8(new ByteArrayInputStream(zipBytes), entryFullName + "/", sampleList);
|
||||||
|
}
|
||||||
|
// 情况2:当前是图片文件 → 上传到MinIO并生成filePath
|
||||||
|
else if (validImageSuffix.contains(suffix)) {
|
||||||
|
try {
|
||||||
|
// 读取图片文件字节
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
IOUtils.copy(zais, baos);
|
||||||
|
byte[] imageBytes = baos.toByteArray();
|
||||||
|
ByteArrayInputStream imageInputStream = new ByteArrayInputStream(imageBytes);
|
||||||
|
|
||||||
|
// 生成MinIO存储路径(filePath)
|
||||||
|
String uploadPath = FileUtil.generateZipDatePath(entryFullName, "sampleImage");
|
||||||
|
// 上传图片到MinIO
|
||||||
|
minioUtil.uploadFile(minioConfig.getBucketName(), uploadPath, imageInputStream);
|
||||||
|
|
||||||
|
// 拼接完整的filePath(存储到数据库)
|
||||||
|
String filePath = uploadPath;
|
||||||
|
|
||||||
|
// 封装SampleDto(仅设置filePath)
|
||||||
|
SampleDto sampleDto = new SampleDto();
|
||||||
|
sampleDto.setFileName(entryFullName); // 含嵌套路径的完整文件名
|
||||||
|
sampleDto.setFileSuffix(suffix);
|
||||||
|
// 处理文件大小
|
||||||
|
long fileSize = entry.getSize() == -1 ? imageBytes.length : entry.getSize();
|
||||||
|
sampleDto.setFileSize(new BigDecimal(fileSize));
|
||||||
|
// 仅存储filePath到数据库
|
||||||
|
sampleDto.setFilePath(filePath);
|
||||||
|
|
||||||
|
sampleList.add(sampleDto);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("上传图片文件失败:" + entryFullName + ",错误:" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("解析嵌套ZIP失败(路径:" + parentPath + "):" + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.bonus.web.service.data;
|
||||||
|
|
||||||
import com.bonus.common.core.domain.AjaxResult;
|
import com.bonus.common.core.domain.AjaxResult;
|
||||||
import com.bonus.common.domain.data.dto.LabelGroupDto;
|
import com.bonus.common.domain.data.dto.LabelGroupDto;
|
||||||
|
import com.bonus.common.domain.data.dto.SampleDto;
|
||||||
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
||||||
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
||||||
import com.bonus.common.utils.ValidatorsUtils;
|
import com.bonus.common.utils.ValidatorsUtils;
|
||||||
|
|
@ -13,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -134,4 +136,46 @@ public class SampleService {
|
||||||
}
|
}
|
||||||
return AjaxResult.success(vo);
|
return AjaxResult.success(vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量导入样本文件(新增核心方法)
|
||||||
|
* @param sampleLibraryId 样本库ID
|
||||||
|
* @param createUserId 创建人ID
|
||||||
|
* @param sampleList 样本列表
|
||||||
|
* @return AjaxResult
|
||||||
|
* @author lhdhy
|
||||||
|
* @date 2026/01/05
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public AjaxResult importSampleFile(Long sampleLibraryId, Long createUserId, List<SampleDto> sampleList) {
|
||||||
|
try {
|
||||||
|
// 1. 校验样本库是否存在
|
||||||
|
SampleLibraryDto libraryDto = new SampleLibraryDto();
|
||||||
|
libraryDto.setSampleLibraryId(sampleLibraryId);
|
||||||
|
SampleLibraryVo libraryVo = diSampleService.getSampleDetail(libraryDto);
|
||||||
|
if (libraryVo == null) {
|
||||||
|
return AjaxResult.error("样本库不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 封装样本公共字段
|
||||||
|
for (SampleDto sample : sampleList) {
|
||||||
|
sample.setSampleLibraryId(sampleLibraryId);
|
||||||
|
sample.setCreateUserId(createUserId);
|
||||||
|
sample.setUpdateUserId(createUserId);
|
||||||
|
sample.setDelFlag("0");
|
||||||
|
// 兜底文件大小(避免null)
|
||||||
|
if (sample.getFileSize() == null) {
|
||||||
|
sample.setFileSize(BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 批量插入样本数据
|
||||||
|
diSampleService.batchInsertSample(sampleList);
|
||||||
|
return AjaxResult.success("导入成功,共导入 " + sampleList.size() + " 个图片文件");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("样本文件导入失败", e);
|
||||||
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||||
|
return AjaxResult.error("导入失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,18 @@ public class SampleDto {
|
||||||
/**
|
/**
|
||||||
* 文件格式
|
* 文件格式
|
||||||
*/
|
*/
|
||||||
private String fileSuffiex;
|
private String fileSuffix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件大小
|
* 文件大小
|
||||||
*/
|
*/
|
||||||
private BigDecimal fileSize;
|
private BigDecimal fileSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件路径
|
||||||
|
*/
|
||||||
|
private String filePath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public class SampleVo {
|
||||||
/**
|
/**
|
||||||
* 文件格式
|
* 文件格式
|
||||||
*/
|
*/
|
||||||
private String fileSuffiex;
|
private String fileSuffix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件大小
|
* 文件大小
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,21 @@ public class FileUtil {
|
||||||
return Paths.get(baseDir, datePath, uniqueFileName).toString();
|
return Paths.get(baseDir, datePath, uniqueFileName).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成日期目录格式的存储路径
|
||||||
|
*/
|
||||||
|
public static String generateZipDatePath(String fileName, String baseDir) {
|
||||||
|
// 生成日期目录:年/月/日(与原有方法逻辑一致)
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
|
||||||
|
String datePath = sdf.format(new Date());
|
||||||
|
// 生成唯一文件名(复用原有工具方法)
|
||||||
|
String fileExtension = getFileExtension(fileName);
|
||||||
|
String uniqueFileName = UUID.randomUUID().toString().replaceAll("-","") + fileExtension;
|
||||||
|
|
||||||
|
// 构建完整路径:baseDir/年/月/日/UUID.扩展名(与原有方法逻辑一致)
|
||||||
|
return Paths.get(baseDir, datePath, uniqueFileName).toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件扩展名
|
* 获取文件扩展名
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.bonus.data.mapper;
|
package com.bonus.data.mapper;
|
||||||
|
|
||||||
|
import com.bonus.common.domain.data.dto.SampleDto;
|
||||||
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
||||||
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
@ -62,4 +63,12 @@ public interface DISampleMapper {
|
||||||
* @date 2025/12/22 13:18
|
* @date 2025/12/22 13:18
|
||||||
*/
|
*/
|
||||||
SampleLibraryVo getSampleDetail(SampleLibraryDto dto);
|
SampleLibraryVo getSampleDetail(SampleLibraryDto dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插入样本数据
|
||||||
|
* @param sampleList 样本列表
|
||||||
|
* @author lhdhy
|
||||||
|
* @date 2026/01/05
|
||||||
|
*/
|
||||||
|
void batchInsertSample(@Param("sampleList") List<SampleDto> sampleList);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.bonus.data.service;
|
package com.bonus.data.service;
|
||||||
|
|
||||||
|
import com.bonus.common.domain.data.dto.SampleDto;
|
||||||
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
||||||
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
||||||
|
|
||||||
|
|
@ -60,4 +61,12 @@ public interface DISampleService {
|
||||||
* @date 2025/12/22 13:17
|
* @date 2025/12/22 13:17
|
||||||
*/
|
*/
|
||||||
SampleLibraryVo getSampleDetail(SampleLibraryDto dto);
|
SampleLibraryVo getSampleDetail(SampleLibraryDto dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插入样本数据
|
||||||
|
* @param sampleList 样本列表
|
||||||
|
* @author lhdhy
|
||||||
|
* @date 2026/01/05
|
||||||
|
*/
|
||||||
|
void batchInsertSample(List<SampleDto> sampleList);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.bonus.data.service.impl;
|
package com.bonus.data.service.impl;
|
||||||
|
|
||||||
|
import com.bonus.common.domain.data.dto.SampleDto;
|
||||||
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
import com.bonus.common.domain.data.dto.SampleLibraryDto;
|
||||||
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
import com.bonus.common.domain.data.vo.SampleLibraryVo;
|
||||||
import com.bonus.data.mapper.DISampleMapper;
|
import com.bonus.data.mapper.DISampleMapper;
|
||||||
|
|
@ -47,4 +48,11 @@ public class DSampleServiceImpl implements DISampleService {
|
||||||
public SampleLibraryVo getSampleDetail(SampleLibraryDto dto) {
|
public SampleLibraryVo getSampleDetail(SampleLibraryDto dto) {
|
||||||
return diSampleMapper.getSampleDetail(dto);
|
return diSampleMapper.getSampleDetail(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void batchInsertSample(List<SampleDto> sampleList) {
|
||||||
|
if (sampleList != null && !sampleList.isEmpty()) {
|
||||||
|
diSampleMapper.batchInsertSample(sampleList);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@
|
||||||
<if test="operType == 2">
|
<if test="operType == 2">
|
||||||
UPDATE tb_sample_library
|
UPDATE tb_sample_library
|
||||||
SET sample_library_name = #{params.sampleLibraryName},
|
SET sample_library_name = #{params.sampleLibraryName},
|
||||||
sample_library_label = #{params.sampleLibraryLabel},
|
sample_library_label = #{params.sampleLibraryLabel},
|
||||||
sample_library_type = #{params.sampleLibraryType},
|
sample_library_type = #{params.sampleLibraryType},
|
||||||
sample_library_desc = #{params.sampleLibraryDesc}
|
sample_library_desc = #{params.sampleLibraryDesc}
|
||||||
WHERE sample_library_id = #{params.sampleLibraryId};
|
WHERE sample_library_id = #{params.sampleLibraryId};
|
||||||
</if>
|
</if>
|
||||||
<if test="operType == 3">
|
<if test="operType == 3">
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT sample_library_id, COUNT(*) AS num
|
SELECT sample_library_id, COUNT(*) AS num
|
||||||
FROM tb_sample
|
FROM tb_sample
|
||||||
WHERE del_flag = '1'
|
WHERE del_flag = '0'
|
||||||
GROUP BY sample_library_id
|
GROUP BY sample_library_id
|
||||||
) A ON tsl.sample_library_id = A.sample_library_id
|
) A ON tsl.sample_library_id = A.sample_library_id
|
||||||
LEFT JOIN sys_dict_data sdd
|
LEFT JOIN sys_dict_data sdd
|
||||||
|
|
@ -103,10 +103,40 @@
|
||||||
<!--查询样本库详情-->
|
<!--查询样本库详情-->
|
||||||
<select id="getSampleDetail" resultType="com.bonus.common.domain.data.vo.SampleLibraryVo">
|
<select id="getSampleDetail" resultType="com.bonus.common.domain.data.vo.SampleLibraryVo">
|
||||||
SELECT sample_library_id,
|
SELECT sample_library_id,
|
||||||
sample_library_name,
|
sample_library_name,
|
||||||
sample_library_label,
|
sample_library_label,
|
||||||
sample_library_type,
|
sample_library_type,
|
||||||
sample_library_desc
|
sample_library_desc
|
||||||
FROM tb_sample_library WHERE sample_library_id = #{sampleLibraryId}
|
FROM tb_sample_library WHERE sample_library_id = #{sampleLibraryId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 新增:批量插入样本数据 -->
|
||||||
|
<insert id="batchInsertSample">
|
||||||
|
INSERT INTO tb_sample (
|
||||||
|
sample_library_id,
|
||||||
|
file_name,
|
||||||
|
file_suffix,
|
||||||
|
file_size,
|
||||||
|
file_path,
|
||||||
|
create_user_id,
|
||||||
|
update_user_id,
|
||||||
|
del_flag,
|
||||||
|
create_time,
|
||||||
|
update_time
|
||||||
|
) VALUES
|
||||||
|
<foreach collection="sampleList" item="item" separator=",">
|
||||||
|
(
|
||||||
|
#{item.sampleLibraryId},
|
||||||
|
#{item.fileName},
|
||||||
|
#{item.fileSuffix},
|
||||||
|
#{item.fileSize},
|
||||||
|
#{item.filePath},
|
||||||
|
#{item.createUserId},
|
||||||
|
#{item.updateUserId},
|
||||||
|
'0',
|
||||||
|
NOW(),
|
||||||
|
NOW()
|
||||||
|
)
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue