This commit is contained in:
funny 2026-04-13 16:15:13 +08:00
parent cf725cc23f
commit 593c8547a5
5 changed files with 108 additions and 6 deletions

View File

@ -28,10 +28,13 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.ttzero.excel.entity.ListSheet; import org.ttzero.excel.entity.ListSheet;
import org.ttzero.excel.entity.Workbook; import org.ttzero.excel.entity.Workbook;
import org.ttzero.excel.reader.Drawings;
import org.ttzero.excel.reader.ExcelReader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -170,7 +173,7 @@ public class QmsInspectionItemController extends BaseController {
/** /**
* 导入检测项 * 导入检测项
* 校验失败时返回带错误信息的文件URL * 校验失败时返回带错误信息的文件URL
* 图例字段填写图片URL需先通过文件上传接口上传图片获取URL * 图例字段支持嵌入图片自动上传或图片URL
* *
* @param file 导入文件 * @param file 导入文件
*/ */
@ -182,6 +185,19 @@ public class QmsInspectionItemController extends BaseController {
throw new NflgException(STATE.BusinessError, "导入文件内容为空"); throw new NflgException(STATE.BusinessError, "导入文件内容为空");
} }
// 设置行号用于匹配图片
for (int i = 0; i < data.size(); i++) {
data.get(i).setRowIndex(i);
}
// 读取Excel中的嵌入图片
List<Drawings.Picture> pictures = null;
try (InputStream in = file.getInputStream()) {
pictures = new ExcelReader(in).listPictures();
} catch (Exception e) {
pictures = null;
}
// 校验必填字段 // 校验必填字段
boolean hasError = false; boolean hasError = false;
for (QmsInspectionItemImportDTO dto : data) { for (QmsInspectionItemImportDTO dto : data) {
@ -199,7 +215,7 @@ public class QmsInspectionItemController extends BaseController {
} }
if (!hasError) { if (!hasError) {
inspectionItemService.importItems(data); inspectionItemService.importItems(data, pictures);
return ApiResult.success("导入成功"); return ApiResult.success("导入成功");
} else { } else {
try (ByteArrayOutputStream osOut = new ByteArrayOutputStream()) { try (ByteArrayOutputStream osOut = new ByteArrayOutputStream()) {

View File

@ -10,6 +10,11 @@ import org.ttzero.excel.annotation.ExcelColumn;
@Data @Data
public class QmsInspectionItemImportDTO { public class QmsInspectionItemImportDTO {
/**
* 行号从0开始用于匹配图片位置非Excel列
*/
private int rowIndex;
/** /**
* 错误信息导入校验结果 * 错误信息导入校验结果
*/ */

View File

@ -11,6 +11,7 @@ import com.nflg.wms.common.pojo.qo.QmsInspectionItemUpdateQO;
import com.nflg.wms.common.pojo.vo.QmsInspectionItemDetailsVO; import com.nflg.wms.common.pojo.vo.QmsInspectionItemDetailsVO;
import com.nflg.wms.common.pojo.vo.QmsInspectionItemVO; import com.nflg.wms.common.pojo.vo.QmsInspectionItemVO;
import com.nflg.wms.repository.entity.QmsInspectionItem; import com.nflg.wms.repository.entity.QmsInspectionItem;
import org.ttzero.excel.reader.Drawings;
import java.util.List; import java.util.List;
@ -63,5 +64,5 @@ public interface IQmsInspectionItemService extends IService<QmsInspectionItem> {
/** /**
* 批量导入 * 批量导入
*/ */
void importItems(List<QmsInspectionItemImportDTO> dtos); void importItems(List<QmsInspectionItemImportDTO> dtos, List<Drawings.Picture> pictures);
} }

View File

@ -1,5 +1,6 @@
package com.nflg.wms.repository.service.impl; package com.nflg.wms.repository.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -15,6 +16,7 @@ import com.nflg.wms.common.pojo.qo.QmsInspectionItemSearchQO;
import com.nflg.wms.common.pojo.qo.QmsInspectionItemUpdateQO; import com.nflg.wms.common.pojo.qo.QmsInspectionItemUpdateQO;
import com.nflg.wms.common.pojo.vo.QmsInspectionItemDetailsVO; import com.nflg.wms.common.pojo.vo.QmsInspectionItemDetailsVO;
import com.nflg.wms.common.pojo.vo.QmsInspectionItemVO; import com.nflg.wms.common.pojo.vo.QmsInspectionItemVO;
import com.nflg.wms.common.util.DateTimeUtil;
import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.UserUtil;
import com.nflg.wms.repository.entity.QmsInspectionItem; import com.nflg.wms.repository.entity.QmsInspectionItem;
import com.nflg.wms.repository.entity.QmsInspectionItemDetails; import com.nflg.wms.repository.entity.QmsInspectionItemDetails;
@ -22,9 +24,15 @@ import com.nflg.wms.repository.mapper.QmsInspectionItemMapper;
import com.nflg.wms.repository.service.IQmsInspectionItemDetailsService; import com.nflg.wms.repository.service.IQmsInspectionItemDetailsService;
import com.nflg.wms.repository.service.IQmsInspectionItemService; import com.nflg.wms.repository.service.IQmsInspectionItemService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.ttzero.excel.reader.Drawings;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime; import java.time.LocalTime;
@ -43,6 +51,7 @@ public class QmsInspectionItemServiceImpl extends ServiceImpl<QmsInspectionItemM
@Resource @Resource
private IQmsInspectionItemDetailsService detailsService; private IQmsInspectionItemDetailsService detailsService;
// ==================== 新增主表 + 一条明细 ==================== // ==================== 新增主表 + 一条明细 ====================
@Transactional @Transactional
@ -255,7 +264,7 @@ public class QmsInspectionItemServiceImpl extends ServiceImpl<QmsInspectionItemM
@Transactional @Transactional
@Override @Override
public void importItems(List<QmsInspectionItemImportDTO> dtos) { public void importItems(List<QmsInspectionItemImportDTO> dtos, List<Drawings.Picture> pictures) {
String operator = UserUtil.getUserName(); String operator = UserUtil.getUserName();
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
@ -290,11 +299,24 @@ public class QmsInspectionItemServiceImpl extends ServiceImpl<QmsInspectionItemM
// 所有行作为明细插入 // 所有行作为明细插入
for (QmsInspectionItemImportDTO dto : list) { for (QmsInspectionItemImportDTO dto : list) {
// 过滤无效的图片公式只保留有效的 URL
String legend = dto.getLegend(); String legend = dto.getLegend();
// 如果是 DISPIMG 公式尝试从嵌入图片中获取
if (StrUtil.isNotBlank(legend) && legend.startsWith("=DISPIMG(")) { if (StrUtil.isNotBlank(legend) && legend.startsWith("=DISPIMG(")) {
legend = null; // 忽略无效的 Excel 图片公式 if (pictures != null && !pictures.isEmpty()) {
// 根据行号找到这一行对应的图片Excel行号从1开始需要+1跳过表头
Drawings.Picture pic = findPictureByRow(pictures, dto.getRowIndex() + 1);
if (pic != null) {
// 上传图片并获取URL
legend = uploadPicture(pic);
} else {
legend = null;
} }
} else {
legend = null;
}
}
QmsInspectionItemDetails detail = new QmsInspectionItemDetails() QmsInspectionItemDetails detail = new QmsInspectionItemDetails()
.setInspectionItemId(item.getId()) .setInspectionItemId(item.getId())
.setTestStandard(dto.getTestStandard()) .setTestStandard(dto.getTestStandard())
@ -305,6 +327,59 @@ public class QmsInspectionItemServiceImpl extends ServiceImpl<QmsInspectionItemM
} }
} }
/**
* 根据行号查找图片
*/
private Drawings.Picture findPictureByRow(List<Drawings.Picture> pictures, int excelRowIndex) {
for (Drawings.Picture pic : pictures) {
// 使用dimension获取行号dimension.firstRow是起始行号
if (pic.dimension != null && pic.dimension.firstRow == excelRowIndex) {
return pic;
}
}
return null;
}
/**
* 上传图片到文件服务器
*/
private String uploadPicture(Drawings.Picture picture) {
try {
// 从临时路径读取图片数据
Path localPath = picture.getLocalPath();
if (localPath == null || !Files.exists(localPath)) {
return null;
}
byte[] imageBytes = Files.readAllBytes(localPath);
// 从文件名或路径推断扩展名
String fileName = localPath.getFileName().toString();
String ext = "png"; // 默认扩展名
if (fileName.contains(".")) {
ext = fileName.substring(fileName.lastIndexOf(".") + 1);
}
// 根据扩展名确定contentType
String contentType = "image/png";
if ("jpg".equalsIgnoreCase(ext) || "jpeg".equalsIgnoreCase(ext)) {
contentType = "image/jpeg";
} else if ("gif".equalsIgnoreCase(ext)) {
contentType = "image/gif";
} else if ("bmp".equalsIgnoreCase(ext)) {
contentType = "image/bmp";
}
return fileUploadService.upload(
"inspection/legend/" + DateTimeUtil.format(LocalDate.now(), "yyyyMMdd")
+ "/" + IdUtil.fastUUID() + "." + ext,
new ByteArrayInputStream(imageBytes),
contentType);
} catch (Exception e) {
return null;
}
}
// ==================== 私有工具 ==================== // ==================== 私有工具 ====================
private QmsInspectionItemVO toVO(QmsInspectionItem item) { private QmsInspectionItemVO toVO(QmsInspectionItem item) {

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.wms.repository.mapper.QmsCoaTaskMapper">
</mapper>