|
|
|
@ -24,9 +24,12 @@ import com.xujie.sys.modules.pms.util.HttpClientUtil; |
|
|
|
import com.xujie.sys.modules.pms.util.ResponseData; |
|
|
|
import com.xujie.sys.modules.report.dao.ProcedureDao; |
|
|
|
import com.xujie.sys.modules.sys.entity.SysSceneDynamicControlModelEntity; |
|
|
|
import javafx.util.Pair; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.apache.poi.openxml4j.opc.OPCPackage; |
|
|
|
import org.apache.poi.ss.usermodel.CellType; |
|
|
|
import org.apache.poi.ss.usermodel.DataFormatter; |
|
|
|
import org.apache.poi.ss.usermodel.Sheet; |
|
|
|
import org.apache.poi.xssf.usermodel.XSSFCell; |
|
|
|
import org.apache.poi.xssf.usermodel.XSSFRow; |
|
|
|
@ -43,6 +46,11 @@ import org.springframework.mail.javamail.MimeMessageHelper; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
import org.apache.poi.xssf.eventusermodel.XSSFReader; |
|
|
|
import org.xml.sax.XMLReader; |
|
|
|
import javax.xml.parsers.SAXParserFactory; |
|
|
|
import javax.xml.parsers.ParserConfigurationException; |
|
|
|
import org.xml.sax.SAXException; |
|
|
|
|
|
|
|
import javax.mail.internet.MimeMessage; |
|
|
|
import javax.servlet.ServletOutputStream; |
|
|
|
@ -58,6 +66,7 @@ import java.text.DecimalFormat; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.*; |
|
|
|
import java.util.function.Function; |
|
|
|
import java.util.regex.Pattern; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
@ -1452,60 +1461,101 @@ public class QcServiceImpl implements QcService { |
|
|
|
@Override |
|
|
|
@Transactional |
|
|
|
public void uploadPartAttributeExcel(MultipartFile file, GetParamInData paramData) { |
|
|
|
try(InputStream is = file.getInputStream(); |
|
|
|
XSSFWorkbook workbook = new XSSFWorkbook(is)) { |
|
|
|
DataFormatter formatter = new DataFormatter(); |
|
|
|
List<QcPartAttributeData> newAttrs = new ArrayList<>(); |
|
|
|
List<QcTemplateData> newDetails = new ArrayList<>(); |
|
|
|
|
|
|
|
// 1. 预加载:已有 attributeNo 和 模板主数据 |
|
|
|
Set<String> existNos = new HashSet<>( |
|
|
|
qcMapper.selectAllAttributeNos(paramData.getSite(), paramData.getBuNo()) |
|
|
|
); |
|
|
|
Map<String, QcTemplateData> templateMap = qcMapper.selectAllTemplateData(paramData.getSite(), paramData.getBuNo()) |
|
|
|
.stream() |
|
|
|
.collect(Collectors.toMap(QcTemplateData::getTemplateId, Function.identity())); |
|
|
|
|
|
|
|
try (InputStream is = file.getInputStream(); |
|
|
|
XSSFWorkbook workbook = new XSSFWorkbook(is)) { |
|
|
|
|
|
|
|
XSSFSheet sheet = workbook.getSheetAt(0); |
|
|
|
int rows = sheet.getPhysicalNumberOfRows(); |
|
|
|
for (int rowIdx = 1; rowIdx <= sheet.getLastRowNum(); rowIdx++) { |
|
|
|
XSSFRow row = sheet.getRow(rowIdx); |
|
|
|
if (row == null) continue; |
|
|
|
|
|
|
|
// —— 解析 partNo —— |
|
|
|
String partNo = formatter.formatCellValue(row.getCell(0)); |
|
|
|
if (partNo == null || partNo.isEmpty()) { |
|
|
|
throw new RuntimeException("第 " + (rowIdx+1) + " 行:[物料编码] 不能为空"); |
|
|
|
} |
|
|
|
|
|
|
|
// 遍历每一行(从第二行开始) |
|
|
|
for (int j = 1; j < rows; j++) { |
|
|
|
// 实例化对象 |
|
|
|
QcPartAttributeData task = new QcPartAttributeData(); |
|
|
|
// 获得该行 |
|
|
|
XSSFRow row = sheet.getRow(j); |
|
|
|
// 为对象赋值 |
|
|
|
task.setSite(paramData.getSite()); |
|
|
|
task.setPartNo(row.getCell(0).getRawValue()); |
|
|
|
task.setSupplierNo(row.getCell(1).getRawValue()); |
|
|
|
task.setAttributeType("A"); |
|
|
|
task.setAttributeRemark(row.getCell(2).getStringCellValue()); |
|
|
|
task.setCreateBy(paramData.getCreateBy()); |
|
|
|
// 查重 |
|
|
|
task.setAttributeNo(task.getPartNo()); |
|
|
|
QcPartAttributeData partAttributeData = qcMapper.selectPartAttributeByNo(task); |
|
|
|
if(partAttributeData != null){ |
|
|
|
throw new RuntimeException("该物料属性已存在!"); |
|
|
|
// 如果数据库已存在,跳过新增属性,只插入新明细 |
|
|
|
boolean isNewAttr = existNos.add(partNo); |
|
|
|
if (isNewAttr) { |
|
|
|
QcPartAttributeData attr = new QcPartAttributeData(); |
|
|
|
attr.setSite(paramData.getSite()); |
|
|
|
attr.setBuNo(paramData.getBuNo()); |
|
|
|
attr.setAttributeNo(partNo); |
|
|
|
attr.setPartNo(partNo); |
|
|
|
attr.setSupplierNo(formatter.formatCellValue(row.getCell(1))); |
|
|
|
attr.setAttributeType("A"); |
|
|
|
attr.setAttributeRemark(formatter.formatCellValue(row.getCell(2))); |
|
|
|
attr.setCreateBy(paramData.getCreateBy()); |
|
|
|
newAttrs.add(attr); |
|
|
|
} |
|
|
|
// 新增物料属性 |
|
|
|
qcMapper.qcPartAttributeSave(task); |
|
|
|
QcTemplateData templateData = new QcTemplateData(); |
|
|
|
templateData.setSite(task.getSite()); |
|
|
|
templateData.setAttributeNo(task.getPartNo()); |
|
|
|
// 新增物料属性中的模板 |
|
|
|
int cells = row.getLastCellNum(); |
|
|
|
for (int i = 1; i <= cells - 3; i++) { |
|
|
|
templateData.setTemplateId(row.getCell(2 + i).getRawValue()); |
|
|
|
QcTemplateData data = qcMapper.selectTemplateData(templateData); |
|
|
|
templateData.setSamplingLevelNo(data.getSamplingLevelNo()); |
|
|
|
templateData.setInspectionCycle(data.getInspectionCycle()); |
|
|
|
templateData.setSamplingProgrammeNo(data.getSamplingProgrammeNo()); |
|
|
|
templateData.setAql(data.getAql()); |
|
|
|
templateData.setAc(data.getAc()); |
|
|
|
templateData.setRe(data.getRe()); |
|
|
|
templateData.setAttributeType(task.getAttributeType()); |
|
|
|
// 新增 |
|
|
|
qcMapper.savePartAttributeDetails(templateData); |
|
|
|
|
|
|
|
// —— 解析模板明细列(第 3 列以后)—— |
|
|
|
for (int c = 3; c < row.getLastCellNum(); c++) { |
|
|
|
String tplId = formatter.formatCellValue(row.getCell(c)); |
|
|
|
if (tplId == null || tplId.isEmpty()) continue; |
|
|
|
|
|
|
|
QcTemplateData master = templateMap.get(tplId); |
|
|
|
if (master == null) { |
|
|
|
throw new RuntimeException("找不到模板配置:" + tplId); |
|
|
|
} |
|
|
|
|
|
|
|
// 复制主数据字段到明细 |
|
|
|
QcTemplateData detail = new QcTemplateData(); |
|
|
|
detail.setSite(paramData.getSite()); |
|
|
|
detail.setBuNo(paramData.getBuNo()); |
|
|
|
detail.setAttributeNo(partNo); |
|
|
|
detail.setTemplateId(master.getTemplateId()); |
|
|
|
detail.setSamplingLevelNo(master.getSamplingLevelNo()); |
|
|
|
detail.setInspectionCycle(master.getInspectionCycle()); |
|
|
|
detail.setSamplingProgrammeNo(master.getSamplingProgrammeNo()); |
|
|
|
detail.setAql(master.getAql()); |
|
|
|
detail.setAc(master.getAc()); |
|
|
|
detail.setRe(master.getRe()); |
|
|
|
detail.setAttributeType("A"); |
|
|
|
newDetails.add(detail); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (IOException e) { |
|
|
|
throw new RuntimeException("Failed to read Excel file.", e); |
|
|
|
} catch (DataAccessException e) { |
|
|
|
throw new RuntimeException("Database access failed.", e); |
|
|
|
throw new RuntimeException("读取 Excel 失败", e); |
|
|
|
} |
|
|
|
|
|
|
|
// 4. 批量写库 |
|
|
|
// 批量插入属性 |
|
|
|
if (!newAttrs.isEmpty()) { |
|
|
|
int attrBatch = 200; // 根据字段数和参数限制设定 |
|
|
|
for (int i = 0; i < newAttrs.size(); i += attrBatch) { |
|
|
|
int end = Math.min(i + attrBatch, newAttrs.size()); |
|
|
|
qcMapper.batchSavePartAttribute(newAttrs.subList(i, end)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 批量插入明细 |
|
|
|
if (!newDetails.isEmpty()) { |
|
|
|
int detailBatch = 100; |
|
|
|
for (int i = 0; i < newDetails.size(); i += detailBatch) { |
|
|
|
int end = Math.min(i + detailBatch, newDetails.size()); |
|
|
|
qcMapper.batchSavePartAttributeDetails(newDetails.subList(i, end)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ======================= 类别属性设置维护 ======================= |
|
|
|
|
|
|
|
/** |
|
|
|
|