diff --git a/nflg-qms-admin/pom.xml b/nflg-qms-admin/pom.xml index f89fa50a..67cbca07 100644 --- a/nflg-qms-admin/pom.xml +++ b/nflg-qms-admin/pom.xml @@ -23,6 +23,10 @@ com.nflg nflg-wms-starter + + com.nflg + nflg-qms-pdf-extract + org.springframework.boot spring-boot-starter-web diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/config/PdfExtractConfig.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/config/PdfExtractConfig.java new file mode 100644 index 00000000..ff298f5d --- /dev/null +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/config/PdfExtractConfig.java @@ -0,0 +1,33 @@ +package com.nflg.qms.admin.config; + +import extraction.DimensionIdentifier; +import extraction.TextGrouper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import service.PdfExtractionService; +import service.RegionFilterService; + +@Configuration +public class PdfExtractConfig { + + @Bean + public PdfExtractionService pdfExtractionService(TextGrouper textGrouper, DimensionIdentifier dimensionIdentifier) { + return new PdfExtractionService(textGrouper,dimensionIdentifier); + } + + @Bean + public TextGrouper textGrouper() { + return new TextGrouper(); + } + + @Bean + public DimensionIdentifier dimensionIdentifier() { + return new DimensionIdentifier(); + } + + @Bean + public RegionFilterService regionFilterService() { + return new RegionFilterService(); + } + +} diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java index 35a22994..2065acae 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardController.java @@ -1,18 +1,24 @@ package com.nflg.qms.admin.controller; +import com.nflg.qms.admin.pojo.qo.QmsInspectionStandardSaveQO; +import com.nflg.qms.admin.pojo.qo.QmsPdfExtractRegionQO; import com.nflg.qms.admin.service.QmsInspectionStandardControllerService; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.PageData; import com.nflg.wms.common.pojo.qo.*; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardDetailVO; +import com.nflg.qms.admin.pojo.vo.QmsInspectionStandardDetailVO; import com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO; import com.nflg.wms.starter.BaseController; import jakarta.annotation.Resource; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +import model.DimensionResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.io.IOException; +import java.util.List; + /** * 检验标准 */ @@ -92,4 +98,12 @@ public class QmsInspectionStandardController extends BaseController { inspectionStandardControllerService.delete(request.getIds()); return ApiResult.success(); } + + /** + * PDF文件提取区域数据 + */ + @PostMapping("/pdf/extract-region") + public ApiResult> pdfExtractRegion(@Valid @RequestBody QmsPdfExtractRegionQO request) throws IOException { + return ApiResult.success(inspectionStandardControllerService.pdfExtractRegion(request)); + } } diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardItemController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardItemController.java index 39f627c9..0fd0e0e9 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardItemController.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsInspectionStandardItemController.java @@ -2,7 +2,7 @@ package com.nflg.qms.admin.controller; import com.nflg.qms.admin.service.QmsInspectionStandardItemControllerService; import com.nflg.wms.common.pojo.ApiResult; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardItemContentVO; +import com.nflg.qms.admin.pojo.vo.QmsInspectionStandardItemContentVO; import com.nflg.wms.starter.BaseController; import jakarta.annotation.Resource; import jakarta.validation.constraints.NotNull; diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsInspectionStandardSaveQO.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/qo/QmsInspectionStandardSaveQO.java similarity index 97% rename from nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsInspectionStandardSaveQO.java rename to nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/qo/QmsInspectionStandardSaveQO.java index b084a42c..3c8e0f11 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsInspectionStandardSaveQO.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/qo/QmsInspectionStandardSaveQO.java @@ -1,9 +1,10 @@ -package com.nflg.wms.common.pojo.qo; +package com.nflg.qms.admin.pojo.qo; import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; +import model.TextPosition; import java.util.List; @@ -167,7 +168,7 @@ public class QmsInspectionStandardSaveQO { /** * PDF信息 */ - private String pdfInfo; + private TextPosition pdfInfo; /** * 判定类型,0:直接判定;1:测量值 diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/qo/QmsPdfExtractRegionQO.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/qo/QmsPdfExtractRegionQO.java new file mode 100644 index 00000000..bdce8205 --- /dev/null +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/qo/QmsPdfExtractRegionQO.java @@ -0,0 +1,51 @@ +package com.nflg.qms.admin.pojo.qo; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class QmsPdfExtractRegionQO { + + /** + * 文件地址 + */ + @NotBlank + private String url; + + /** + * 页码 + */ + @Min(1) + @NotNull + private int pageNum; + + /** + * x轴起始位置 + */ + @Min(0) + @NotNull + private float x; + + /** + * y轴起始位置 + */ + @Min(0) + @NotNull + private float y; + + /** + * 宽度 + */ + @Min(0) + @NotNull + private float width; + + /** + * 高度 + */ + @Min(0) + @NotNull + private float height; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardDetailVO.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardDetailVO.java similarity index 98% rename from nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardDetailVO.java rename to nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardDetailVO.java index 62a5e24e..96b2a1eb 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardDetailVO.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardDetailVO.java @@ -1,4 +1,4 @@ -package com.nflg.wms.common.pojo.vo; +package com.nflg.qms.admin.pojo.vo; import lombok.Data; diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardItemContentVO.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardItemContentVO.java similarity index 90% rename from nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardItemContentVO.java rename to nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardItemContentVO.java index 740f5a8a..ede9766b 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardItemContentVO.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardItemContentVO.java @@ -1,6 +1,7 @@ -package com.nflg.wms.common.pojo.vo; +package com.nflg.qms.admin.pojo.vo; import lombok.Data; +import model.TextPosition; import java.time.LocalDateTime; @@ -38,7 +39,7 @@ public class QmsInspectionStandardItemContentVO { /** * PDF信息 */ - private String pdfInfo; + private TextPosition pdfInfo; /** * 判定类型,0:直接判定;1:测量值 diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardItemVO.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardItemVO.java similarity index 96% rename from nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardItemVO.java rename to nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardItemVO.java index 5d6d7b67..44f8eb5a 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/vo/QmsInspectionStandardItemVO.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/pojo/vo/QmsInspectionStandardItemVO.java @@ -1,4 +1,4 @@ -package com.nflg.wms.common.pojo.vo; +package com.nflg.qms.admin.pojo.vo; import lombok.Data; diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java index 391b48ac..33fd1d59 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardControllerService.java @@ -1,18 +1,22 @@ package com.nflg.qms.admin.service; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.nflg.qms.admin.pojo.qo.QmsPdfExtractRegionQO; import com.nflg.wms.common.exception.NflgException; import com.nflg.wms.common.pojo.PageData; +import com.nflg.wms.common.pojo.dto.QmsInspectionStandardDetailDTO; import com.nflg.wms.common.pojo.qo.QmsInspectionStandardAddQO; import com.nflg.wms.common.pojo.qo.QmsInspectionStandardEditQO; -import com.nflg.wms.common.pojo.qo.QmsInspectionStandardSaveQO; +import com.nflg.qms.admin.pojo.qo.QmsInspectionStandardSaveQO; import com.nflg.wms.common.pojo.qo.QmsInspectionStandardSearchQO; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardDetailVO; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardItemContentVO; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardItemVO; +import com.nflg.qms.admin.pojo.vo.QmsInspectionStandardDetailVO; +import com.nflg.qms.admin.pojo.vo.QmsInspectionStandardItemContentVO; +import com.nflg.qms.admin.pojo.vo.QmsInspectionStandardItemVO; import com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO; import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; @@ -21,9 +25,14 @@ import com.nflg.wms.repository.mapper.QmsInspectionStandardMapper; import com.nflg.wms.repository.service.*; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import model.DimensionResult; +import model.TextPosition; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import service.PdfExtractionService; +import service.RegionFilterService; +import java.io.IOException; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -59,6 +68,12 @@ public class QmsInspectionStandardControllerService { @Resource private IQmsAqlPriorityValueService aqlPriorityValueService; + @Resource + private PdfExtractionService pdfExtractionService; + + @Resource + private RegionFilterService regionFilterService; + /** * 分页查询检验标准 */ @@ -153,10 +168,10 @@ public class QmsInspectionStandardControllerService { } // 2. 查询检验标准详情(关联物料等信息) - QmsInspectionStandardDetailVO detail = inspectionStandardMapper.getDetailById(id); - if (detail == null) { - detail = new QmsInspectionStandardDetailVO(); - } + QmsInspectionStandardDetailDTO detailDTO = inspectionStandardMapper.getDetailById(id); + QmsInspectionStandardDetailVO detail = Objects.isNull(detailDTO) + ? new QmsInspectionStandardDetailVO() + : Convert.convert(QmsInspectionStandardDetailVO.class, detailDTO); // 填充基础字段 detail.setId(standard.getId()); @@ -289,7 +304,9 @@ public class QmsInspectionStandardControllerService { vo.setName(content.getName()); vo.setTestStandard(content.getTestStandard()); vo.setLegend(content.getLegend()); - vo.setPdfInfo(content.getPdfInfo()); + if (StrUtil.isNotBlank(content.getPdfInfo())) { + vo.setPdfInfo(JSONUtil.toBean(content.getPdfInfo(), TextPosition.class)); + } vo.setJudgmentType(content.getJudgmentType()); vo.setCreateUserName(content.getCreateUserName()); vo.setCreateTime(content.getCreateTime()); @@ -665,7 +682,7 @@ public class QmsInspectionStandardControllerService { content.setLegend(qo.getLegend()); } if (qo.getPdfInfo() != null) { - content.setPdfInfo(qo.getPdfInfo()); + content.setPdfInfo(JSONUtil.toJsonStr(qo.getPdfInfo())); } content.setJudgmentType(qo.getJudgmentType()); @@ -680,4 +697,17 @@ public class QmsInspectionStandardControllerService { content.setCreateTime(now); } } + + public List pdfExtractRegion(QmsPdfExtractRegionQO request) throws IOException { + List allResults = pdfExtractionService.extractAllDimensionsForRegion(request.getUrl()); + List filtered = regionFilterService.filterByRegion( + allResults, + request.getPageNum(), + request.getX(), + request.getY(), + request.getWidth(), + request.getHeight() + ); + return regionFilterService.mergeRegionResults(filtered); + } } diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardItemControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardItemControllerService.java index 62aeab67..58b1b2c1 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardItemControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsInspectionStandardItemControllerService.java @@ -1,13 +1,16 @@ package com.nflg.qms.admin.service; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import com.nflg.wms.common.exception.NflgException; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardItemContentVO; +import com.nflg.qms.admin.pojo.vo.QmsInspectionStandardItemContentVO; import com.nflg.wms.repository.entity.QmsInspectionStandardItem; import com.nflg.wms.repository.entity.QmsInspectionStandardItemContent; import com.nflg.wms.repository.service.IQmsInspectionStandardItemContentService; import com.nflg.wms.repository.service.IQmsInspectionStandardItemService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import model.TextPosition; import org.springframework.stereotype.Component; import java.util.List; @@ -59,7 +62,9 @@ public class QmsInspectionStandardItemControllerService { vo.setName(content.getName()); vo.setTestStandard(content.getTestStandard()); vo.setLegend(content.getLegend()); - vo.setPdfInfo(content.getPdfInfo()); + if (StrUtil.isNotBlank(content.getPdfInfo())) { + vo.setPdfInfo(JSONUtil.toBean(content.getPdfInfo(), TextPosition.class)); + } vo.setJudgmentType(content.getJudgmentType()); vo.setCreateUserName(content.getCreateUserName()); vo.setCreateTime(content.getCreateTime()); diff --git a/nflg-qms-pdf-extract/pom.xml b/nflg-qms-pdf-extract/pom.xml new file mode 100644 index 00000000..d1008b01 --- /dev/null +++ b/nflg-qms-pdf-extract/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + com.nflg + nflg-wms + 1.0.0-SNAPSHOT + + + nflg-qms-pdf-extract + 模块-qms pdf数据提取 + 从pdf中提取数据 + jar + + + + org.projectlombok + lombok + provided + true + + + org.apache.pdfbox + pdfbox + 3.0.4 + + + org.slf4j + slf4j-api + 2.0.12 + + + \ No newline at end of file diff --git a/nflg-qms-pdf-extract/src/main/java/extraction/DimensionIdentifier.java b/nflg-qms-pdf-extract/src/main/java/extraction/DimensionIdentifier.java new file mode 100644 index 00000000..649cebce --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/extraction/DimensionIdentifier.java @@ -0,0 +1,307 @@ +package extraction; + + +import model.DimensionResult; +import model.TextGroup; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DimensionIdentifier { + + // 尺寸 + 对称公差 + private static final Pattern PAT_DIM_SYM_TOL = Pattern.compile( + "([ΦφØ∅]?\\s*\\d+\\.?\\d*)\\s*[±]\\s*(\\d+\\.?\\d*)"); + + // 尺寸 + 非对称公差(斜线分隔) + private static final Pattern PAT_DIM_ASYM_TOL = Pattern.compile( + "([ΦφØ∅]?\\s*\\d+\\.?\\d*)\\s*([+-]\\d+\\.?\\d*)\\s*/\\s*([+-]\\d+\\.?\\d*)"); + + // 尺寸 + 非对称公差(空格分隔) + private static final Pattern PAT_DIM_LIMIT_TOL = Pattern.compile( + "([ΦφØ∅]?\\s*\\d+\\.?\\d*)\\s+([+-]\\d+\\.?\\d*)\\s+([+-]\\d+\\.?\\d*)"); + + // 尺寸 + 配合公差代号 + private static final Pattern PAT_DIM_FIT = Pattern.compile( + "([ΦφØ∅]?\\s*\\d+\\.?\\d*)\\s*([A-HJ-Zj-z]\\d{1,2})\\b"); + + // 螺纹标注(M型公制螺纹 + G型管螺纹 + Rc/NPT等) + private static final Pattern PAT_THREAD = Pattern.compile( + "(M\\d+\\.?\\d*(?:\\s*[xX×]\\s*\\d+\\.?\\d*)?|(?:G|Rc|Rp|NPT)\\s*\\d+(?:/\\d+)?)"); + + // 独立公差文本 + private static final Pattern PAT_TOLERANCE = Pattern.compile( + "[±]\\s*\\d+\\.?\\d*|[+-]\\s*\\d+\\.?\\d*"); + + // 复合公差文本 + private static final Pattern PAT_COMPOUND_TOL = Pattern.compile( + "^([+-]\\d+\\.?\\d*)\\s+(0|[+-]?\\d+\\.?\\d*)$"); + + // 纯尺寸数值 + private static final Pattern PAT_PLAIN_DIM = Pattern.compile( + "([ΦφØ∅]\\s*\\d+\\.?\\d*|[Rr]\\d+\\.?\\d*|[Cc]\\d+\\.?\\d*|\\d+\\.\\d+|\\d+)"); + + public List identifyDimensions(List groups) { + return identifyDimensions(groups, true); + } + + public List identifyDimensions(List groups, boolean toleranceOnly) { + List results = new ArrayList<>(); + Set processed = new HashSet<>(); + Set usedAsTolerance = new HashSet<>(); + + for (int i = 0; i < groups.size(); i++) { + if (processed.contains(i)) continue; + TextGroup g = groups.get(i); + + String text = TextNormalizer.normalizeText(g.getText().trim()); + + // --- 基本过滤(两种模式都适用)--- + if (text.length() > 40) continue; + if (text.isEmpty()) continue; + if (text.matches("^[A-Za-z\\s]+$")) continue; + if (TitleBlockFilter.isInTitleBlockRegion(g)) continue; + + if (toleranceOnly) { + // === toleranceOnly 模式:严格过滤 === + Matcher threadEarly = PAT_THREAD.matcher(text); + boolean isThreadText = threadEarly.find() && threadEarly.start() == 0; + if (!isThreadText && TitleBlockFilter.shouldSkipText(text)) continue; + if (TitleBlockFilter.isToleranceOnly(text)) continue; + if (TitleBlockFilter.isSurfaceRoughness(text)) continue; + if (TitleBlockFilter.isGdtTolerance(text)) continue; + if (text.matches(".*\\d+\\.\\d+\\d+\\.\\d+.*") && !text.contains("±") && !text.contains("/")) continue; + } + // === 区域模式(!toleranceOnly):不做内容过滤,直接进入模式匹配 === + + Matcher m; + + // 0) 复合公差文本 + m = PAT_COMPOUND_TOL.matcher(text); + if (m.matches()) { + processed.add(i); + continue; + } + + // 1) 对称公差 + m = PAT_DIM_SYM_TOL.matcher(text); + if (m.find()) { + results.add(new DimensionResult( + m.group(1).trim(), "±" + m.group(2), "dimension", g)); + processed.add(i); + continue; + } + + // 2) 非对称公差(斜线) + m = PAT_DIM_ASYM_TOL.matcher(text); + if (m.find()) { + results.add(new DimensionResult( + m.group(1).trim(), m.group(2) + "/" + m.group(3), "dimension", g)); + processed.add(i); + continue; + } + + // 3) 非对称公差(空格) + m = PAT_DIM_LIMIT_TOL.matcher(text); + if (m.find()) { + results.add(new DimensionResult( + m.group(1).trim(), m.group(2) + " " + m.group(3), "dimension", g)); + processed.add(i); + continue; + } + + // 4) 配合公差 + m = PAT_DIM_FIT.matcher(text); + if (m.find() && !text.contains("-") && !text.contains("/")) { + results.add(new DimensionResult( + m.group(1).trim(), m.group(2), "dimension", g)); + processed.add(i); + continue; + } + + // 5) 螺纹标注 - toleranceOnly 模式下跳过 + m = PAT_THREAD.matcher(text); + if (m.find() && m.start() == 0) { + if (!toleranceOnly) { + results.add(new DimensionResult(text, null, "dimension", g)); + processed.add(i); + } + continue; + } + + // 6) 纯尺寸数值 + m = PAT_PLAIN_DIM.matcher(text); + if (m.find()) { + String dim = m.group(1).trim(); + int maxExtra = toleranceOnly ? 3 : 15; + if (text.length() > dim.length() + maxExtra) { + // 区域模式下超长文本兜底输出全文 + if (!toleranceOnly) { + results.add(new DimensionResult(text, null, "dimension", g)); + processed.add(i); + } + continue; + } + + String numPart = dim.replaceAll("[^\\d.]", ""); + if (numPart.isEmpty()) continue; + double val; + try { + val = Double.parseDouble(numPart); + double minVal = toleranceOnly ? 0.5 : 0.001; + if (val < minVal || val > 9999) continue; + } catch (NumberFormatException e) { + continue; + } + + String nearbyTol = findNearbyTolerance(g, groups, i, usedAsTolerance); + + // toleranceOnly 模式下仅输出带公差的尺寸 + if (toleranceOnly && nearbyTol == null) continue; + // 非 toleranceOnly 模式下,单字符无公差无Φ符号 → 输出完整文本(而非跳过) + if (!toleranceOnly && nearbyTol == null && dim.length() == 1 && !hasNearbyPhiSymbol(g, groups)) { + if (text.length() > 1) { + results.add(new DimensionResult(text, null, "dimension", g)); + processed.add(i); + } + continue; + } + + // 区域模式下使用完整文本(含描述),toleranceOnly 模式只用尺寸值 + String dimText = (!toleranceOnly && text.length() > dim.length() + 3) ? text : dim; + results.add(new DimensionResult(dimText, nearbyTol, "dimension", g)); + processed.add(i); + continue; + } + + // 7) 区域模式兜底:未被任何模式匹配的文本,直接作为原始内容输出 + if (!toleranceOnly) { + results.add(new DimensionResult(text, null, "dimension", g)); + processed.add(i); + } + } + + return results; + } + + private boolean hasNearbyPhiSymbol(TextGroup dimGroup, List allGroups) { + float searchDist = dimGroup.getFontSize() * 3.0f; + for (TextGroup other : allGroups) { + if (other.getPageNum() != dimGroup.getPageNum()) continue; + String t = other.getText().trim(); + if (!t.equals("¡¤") && !t.equals("Φ") && !t.equals("φ") && !t.equals("Ø") && !t.equals("∅")) + continue; + float dx = Math.abs(other.getX() - dimGroup.getX()); + float dy = Math.abs(other.getY() - dimGroup.getY()); + if (dx < searchDist && dy < searchDist) return true; + } + return false; + } + + private String findNearbyTolerance(TextGroup dimGroup, List allGroups, + int dimIndex, Set usedAsTolerance) { + float effWidth = dimGroup.getWidth() > 0 ? dimGroup.getWidth() + : dimGroup.getFontSize() * dimGroup.getText().trim().length() * 0.5f; + + float searchXRight = dimGroup.getFontSize() * 2.5f; + float searchYRight = dimGroup.getFontSize() * 1.5f; + float searchXVert = dimGroup.getFontSize() * 1.0f; + float searchYVert = dimGroup.getFontSize() * 5.0f; + + List tolParts = new ArrayList<>(); + List tolIndices = new ArrayList<>(); + + for (int i = 0; i < allGroups.size(); i++) { + if (i == dimIndex) continue; + if (usedAsTolerance.contains(i)) continue; + TextGroup other = allGroups.get(i); + if (other.getPageNum() != dimGroup.getPageNum()) continue; + + float dxFromRight = other.getX() - (dimGroup.getX() + effWidth); + float absDxFromStart = Math.abs(other.getX() - dimGroup.getX()); + float dy = Math.abs(other.getY() - dimGroup.getY()); + + boolean rightZone = dxFromRight > -effWidth * 0.3f + && dxFromRight < searchXRight && dy < searchYRight; + boolean vertZone = absDxFromStart < searchXVert + && dy > searchYRight && dy < searchYVert; + + if (!rightZone && !vertZone) continue; + + if (rightZone && !vertZone) { + boolean hasBetterCandidate = false; + for (TextGroup cand : allGroups) { + if (cand == dimGroup || cand.getPageNum() != dimGroup.getPageNum()) continue; + if (Math.abs(cand.getFontSize() - dimGroup.getFontSize()) > 1.0f) continue; + String candText = TextNormalizer.normalizeText(cand.getText().trim()); + if (TitleBlockFilter.isSurfaceRoughness(candText) || TitleBlockFilter.isToleranceOnly(candText)) continue; + float candDxFromTol = Math.abs(other.getX() - cand.getX()); + float candDyFromTol = Math.abs(other.getY() - cand.getY()); + if (candDxFromTol < searchXVert + && candDyFromTol > searchYRight && candDyFromTol < searchYVert) { + hasBetterCandidate = true; + break; + } + } + if (hasBetterCandidate) continue; + } + + String otherText = TextNormalizer.normalizeText(other.getText().trim()); + + if (TitleBlockFilter.isSurfaceRoughness(otherText)) continue; + + boolean bareSmallDecimal = (rightZone || vertZone) && otherText.matches("^0\\.\\d{1,3}$"); + + if (TitleBlockFilter.isGdtTolerance(otherText) && !bareSmallDecimal) continue; + + if (other.getFontSize() <= dimGroup.getFontSize() * 0.9 || otherText.contains("±") || bareSmallDecimal) { + + Matcher cm = PAT_COMPOUND_TOL.matcher(otherText); + if (cm.matches()) { + tolParts.clear(); + tolIndices.clear(); + tolParts.add(cm.group(1) + " / " + cm.group(2)); + tolIndices.add(i); + break; + } + + Matcher tm = PAT_TOLERANCE.matcher(otherText); + if (tm.find()) { + if (tm.start() > 0 && Character.isDigit(otherText.charAt(tm.start() - 1))) { + continue; + } + tolParts.add(otherText); + tolIndices.add(i); + continue; + } + + if (otherText.equals("0") && other.getFontSize() < dimGroup.getFontSize() * 0.85) { + tolParts.add("0"); + tolIndices.add(i); + continue; + } + + if (bareSmallDecimal) { + tolParts.add("±" + otherText); + tolIndices.add(i); + continue; + } + } + } + + if (!tolParts.isEmpty()) { + usedAsTolerance.addAll(tolIndices); + tolParts.sort((a, b) -> { + boolean aPos = a.startsWith("+") || a.startsWith("±"); + boolean bPos = b.startsWith("+") || b.startsWith("±"); + return Boolean.compare(bPos, aPos); + }); + return String.join(" / ", tolParts); + } + return null; + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/extraction/PositionedTextStripper.java b/nflg-qms-pdf-extract/src/main/java/extraction/PositionedTextStripper.java new file mode 100644 index 00000000..4d45cdd1 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/extraction/PositionedTextStripper.java @@ -0,0 +1,59 @@ +package extraction; + +import model.TextElement; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.text.PDFTextStripper; +import org.apache.pdfbox.text.TextPosition; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class PositionedTextStripper extends PDFTextStripper { + private final List elements = new ArrayList<>(); + private int currentPage = 0; + private float currentPageWidth = 0; + private float currentPageHeight = 0; + + @Override + protected void startPage(PDPage page) throws IOException { + currentPage++; + PDRectangle mediaBox = page.getMediaBox(); + currentPageWidth = mediaBox.getWidth(); + currentPageHeight = mediaBox.getHeight(); + super.startPage(page); + } + + @Override + protected void writeString(String text, List textPositions) throws IOException { + if (textPositions == null || textPositions.isEmpty()) { + super.writeString(text, textPositions); + return; + } + + TextPosition first = textPositions.get(0); + TextPosition last = textPositions.get(textPositions.size() - 1); + + TextElement elem = new TextElement(); + elem.setText(text.trim()); + elem.setPageNum(currentPage); + elem.setX(first.getX()); + elem.setY(first.getY()); + elem.setWidth(Math.abs((last.getX() + last.getWidth()) - first.getX())); + elem.setHeight(Math.max(1, Math.abs(first.getHeight()))); + elem.setFontSize(first.getFontSizeInPt()); + elem.setPageWidth(currentPageWidth); + elem.setPageHeight(currentPageHeight); + + if (!elem.getText().isEmpty()) { + elements.add(elem); + } + + super.writeString(text, textPositions); + } + + public List getElements() { + return elements; + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/extraction/TextGrouper.java b/nflg-qms-pdf-extract/src/main/java/extraction/TextGrouper.java new file mode 100644 index 00000000..4bea69b4 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/extraction/TextGrouper.java @@ -0,0 +1,86 @@ +package extraction; + +import model.TextElement; +import model.TextGroup; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class TextGrouper { + + public List groupTextElements(List elements) { + if (elements.isEmpty()) return Collections.emptyList(); + + List sorted = new ArrayList<>(elements); + sorted.sort(Comparator + .comparingInt(TextElement::getPageNum) + .thenComparingDouble(TextElement::getY) + .thenComparingDouble(TextElement::getX)); + + List groups = new ArrayList<>(); + TextGroup current = null; + + for (TextElement elem : sorted) { + boolean merge = false; + if (current != null + && current.getPageNum() == elem.getPageNum() + && Math.abs(current.getY() - elem.getY()) < Math.max(elem.getHeight(), current.getHeight()) * 0.5 + && (elem.getX() - (current.getX() + current.getWidth())) < Math.max(elem.getFontSize(), current.getFontSize()) * 0.8 + && (elem.getX() - (current.getX() + current.getWidth())) > -Math.max(elem.getFontSize(), current.getFontSize()) * 2) { + + float maxFs = Math.max(current.getFontSize(), elem.getFontSize()); + float minFs = Math.min(current.getFontSize(), elem.getFontSize()); + if (maxFs > 0 && minFs / maxFs < 0.7f) { + merge = false; + } else { + boolean curEndsWithDigit = !current.getText().isEmpty() + && Character.isDigit(current.getText().charAt(current.getText().length() - 1)); + boolean elemStartsWithDigit = !elem.getText().isEmpty() + && Character.isDigit(elem.getText().charAt(0)); + if (curEndsWithDigit && elemStartsWithDigit) { + if (current.getText().contains(".") && elem.getText().contains(".")) { + merge = false; + } else if (current.getText().matches("\\d+\\.?\\d*")) { + merge = false; + } else { + merge = true; + } + } else { + merge = true; + } + } + } + + if (merge) { + float gap = elem.getX() - (current.getX() + current.getWidth()); + if (gap > elem.getFontSize() * 0.3) { + current.setText(current.getText() + " "); + } + current.setText(current.getText() + elem.getText()); + float newRight = Math.max(current.getX() + current.getWidth(), elem.getX() + elem.getWidth()); + float newLeft = Math.min(current.getX(), elem.getX()); + current.setX(newLeft); + current.setWidth(newRight - newLeft); + current.setHeight(Math.max(current.getHeight(), elem.getHeight())); + current.getElements().add(elem); + } else { + current = new TextGroup(); + current.setText(elem.getText()); + current.setPageNum(elem.getPageNum()); + current.setX(elem.getX()); + current.setY(elem.getY()); + current.setWidth(elem.getWidth()); + current.setHeight(elem.getHeight()); + current.setFontSize(elem.getFontSize()); + current.setPageWidth(elem.getPageWidth()); + current.setPageHeight(elem.getPageHeight()); + current.getElements().add(elem); + groups.add(current); + } + } + + return groups; + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/extraction/TextNormalizer.java b/nflg-qms-pdf-extract/src/main/java/extraction/TextNormalizer.java new file mode 100644 index 00000000..e6ffac66 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/extraction/TextNormalizer.java @@ -0,0 +1,16 @@ +package extraction; + +public class TextNormalizer { + + public static String normalizeText(String text) { + return text + .replace("\u00a1\u00a4", "\u03a6") + .replace("\u00a1\u00e3", "\u00b0") + .replace("\u00a1\u00c0", "\u00b1") + .replace("\u00a6\u00b5", "\u03a6") + .replace("\uffc3n\uffc3", "\u03a6") + .replace("\uffc3$\uffc3", "\u03a6") + .replace("\ufffdn\ufffd", "\u00d8") + .replace("\ufffd", ""); + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/extraction/TitleBlockFilter.java b/nflg-qms-pdf-extract/src/main/java/extraction/TitleBlockFilter.java new file mode 100644 index 00000000..778cefed --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/extraction/TitleBlockFilter.java @@ -0,0 +1,54 @@ +package extraction; + +import model.TextGroup; + +import java.util.regex.Pattern; + +public class TitleBlockFilter { + + private static final Pattern PAT_SKIP_TEXT = Pattern.compile( + ".*(" + + "GB/T|QT\\d{3}|CR\\d{3}|NF|" + + "比例|截面|技术要求|锪平|螺纹深度|通孔|配作|" + + "设\\s*计|校\\s*对|审|批\\s*准|工\\s*艺|" + + "\\d{2}-\\d{2}-\\d{4}|" + + "\\d{3}-[A-Z]\\d{2}|" + + "版本|序号|修\\s*订|编\\s*码|代\\s*号|" + + "重\\s*量|名\\s*称|材\\s*料|备\\s*注|数量|" + + "页|共|阶\\s*段|标\\s*记|分\\s*区|更改|" + + "级|涂层|膜厚|颜色|RAL|" + + "铸[件造]|拔模|未注|倒角|去毛刺|热处理|" + + "凸起|文字|Work in|JINRONG|" + + "螺栓|螺纹|圆柱销|轴承座|上盖|底座|分体|" + + "福建|南方|机械|有限公司|" + + "其余|首版|赖金荣|10\\.9级|" + + "单件|总计|腐蚀|丙烯酸|石墨烯|防腐|配套加工|" + + "检验|标准化|设计变更" + + ").*", Pattern.CASE_INSENSITIVE); + + public static boolean shouldSkipText(String text) { + return PAT_SKIP_TEXT.matcher(text).matches(); + } + + public static boolean isInTitleBlockRegion(TextGroup g) { + float relY = g.getY() / g.getPageHeight(); + float relX = g.getX() / g.getPageWidth(); + if (relX > 0.55 && relY > 0.60) return true; + return relY > 0.77; + } + + public static boolean isToleranceOnly(String text) { + String t = text.trim(); + return t.matches("^[+-]\\s*\\d+\\.?\\d*$"); + } + + public static boolean isSurfaceRoughness(String text) { + String t = text.trim(); + return t.matches("^(0\\.4|0\\.8|1\\.6|3\\.2|6\\.3|12\\.5|25|50)$"); + } + + public static boolean isGdtTolerance(String text) { + String t = text.trim(); + return t.matches("^0\\.\\d{1,3}(\\s+[A-Z]\\d?)?$"); + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/model/DimensionResult.java b/nflg-qms-pdf-extract/src/main/java/model/DimensionResult.java new file mode 100644 index 00000000..0f83f3ba --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/model/DimensionResult.java @@ -0,0 +1,31 @@ +package model; + +import lombok.Data; + +@Data +public class DimensionResult { + private String dimension; + private String tolerance; + private String type; + private double x, y; + private double width, height; + private int page; + private int sortOrder; + + public DimensionResult() {} + + public DimensionResult(String dimension, String tolerance, String type, TextGroup g) { + this.dimension = dimension; + this.tolerance = tolerance; + this.type = type; + this.x = round(g.getX()); + this.y = round(g.getY() - g.getHeight()); + this.width = round(g.getWidth()); + this.height = round(g.getHeight()); + this.page = g.getPageNum(); + } + + private static double round(float v) { + return Math.round(v * 100.0) / 100.0; + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/model/TextElement.java b/nflg-qms-pdf-extract/src/main/java/model/TextElement.java new file mode 100644 index 00000000..b94de722 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/model/TextElement.java @@ -0,0 +1,13 @@ +package model; + +import lombok.Data; + +@Data +public class TextElement { + private String text; + private int pageNum; + private float x, y; + private float width, height; + private float fontSize; + private float pageWidth, pageHeight; +} diff --git a/nflg-qms-pdf-extract/src/main/java/model/TextGroup.java b/nflg-qms-pdf-extract/src/main/java/model/TextGroup.java new file mode 100644 index 00000000..8a33c2fb --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/model/TextGroup.java @@ -0,0 +1,16 @@ +package model; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class TextGroup { + private String text; + private int pageNum; + private float x, y, width, height; + private float fontSize; + private float pageWidth, pageHeight; + private List elements = new ArrayList<>(); +} diff --git a/nflg-qms-pdf-extract/src/main/java/model/TextPosition.java b/nflg-qms-pdf-extract/src/main/java/model/TextPosition.java new file mode 100644 index 00000000..0d04e921 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/model/TextPosition.java @@ -0,0 +1,47 @@ +package model; + +import lombok.Data; + +@Data +public class TextPosition { + + /** + * 页码 + */ + private int pageNum; + + /** + * x轴起始位置 + */ + private float x; + + /** + * y轴起始位置 + */ + private float y; + + /** + * 宽度 + */ + private float width; + + /** + * 高度 + */ + private float height; + + /** + * 页宽 + */ + private float pageWidth; + + /** + * 页高 + */ + private float pageHeight; + + /** + * 序号 + */ + private int sortOrder; +} diff --git a/nflg-qms-pdf-extract/src/main/java/service/PdfExtractionService.java b/nflg-qms-pdf-extract/src/main/java/service/PdfExtractionService.java new file mode 100644 index 00000000..d1c8d3e3 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/service/PdfExtractionService.java @@ -0,0 +1,95 @@ +package service; + +import extraction.DimensionIdentifier; +import extraction.PositionedTextStripper; +import extraction.TextGrouper; +import lombok.extern.slf4j.Slf4j; +import model.DimensionResult; +import model.TextElement; +import model.TextGroup; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.net.URL; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; + +@Slf4j +public class PdfExtractionService { + + private final TextGrouper textGrouper; + private final DimensionIdentifier dimensionIdentifier; + + public PdfExtractionService(TextGrouper textGrouper, + DimensionIdentifier dimensionIdentifier) { + this.textGrouper = textGrouper; + this.dimensionIdentifier = dimensionIdentifier; + } + + public ExtractionResult extractDimensions(Path pdfPath, String fileId) throws IOException { + long start = System.currentTimeMillis(); + File file = pdfPath.toFile(); + + try (PDDocument document = Loader.loadPDF(file)) { + int totalPages = document.getNumberOfPages(); + + PositionedTextStripper stripper = new PositionedTextStripper(); + stripper.setSortByPosition(true); + StringWriter writer = new StringWriter(); + stripper.writeText(document, writer); + List allElements = stripper.getElements(); + + List groups = textGrouper.groupTextElements(allElements); + List dimensions = dimensionIdentifier.identifyDimensions(groups); + + long elapsed = System.currentTimeMillis() - start; + log.info("Extracted {} dimensions from {} in {}ms", dimensions.size(), pdfPath.getFileName(), elapsed); + + return new ExtractionResult(dimensions, totalPages); + } + } + + /** + * 区域提取:不限公差过滤,包含所有尺寸,不保存到数据库 + */ + public List extractAllDimensionsForRegion(String pdfUrl) throws IOException { + byte[] pdfBytes; + try (InputStream in = new URL(pdfUrl).openStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream()) { + byte[] chunk = new byte[8192]; + int len; + while ((len = in.read(chunk)) != -1) { + buffer.write(chunk, 0, len); + } + pdfBytes = buffer.toByteArray(); + } + try (PDDocument document = Loader.loadPDF(pdfBytes)) { + PositionedTextStripper stripper = new PositionedTextStripper(); + stripper.setSortByPosition(true); + StringWriter writer = new StringWriter(); + stripper.writeText(document, writer); + List allElements = stripper.getElements(); + List groups = textGrouper.groupTextElements(allElements); + return dimensionIdentifier.identifyDimensions(groups, false); + } + } + + public static class ExtractionResult { + private final List dimensions; + private final int totalPages; + + public ExtractionResult(List dimensions, int totalPages) { + this.dimensions = dimensions; + this.totalPages = totalPages; + } + + public List getDimensions() { return dimensions; } + public int getTotalPages() { return totalPages; } + } +} diff --git a/nflg-qms-pdf-extract/src/main/java/service/RegionFilterService.java b/nflg-qms-pdf-extract/src/main/java/service/RegionFilterService.java new file mode 100644 index 00000000..723d5021 --- /dev/null +++ b/nflg-qms-pdf-extract/src/main/java/service/RegionFilterService.java @@ -0,0 +1,90 @@ +package service; + + +import model.DimensionResult; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class RegionFilterService { + + public List filterByRegion(List all, + int page, double rx, double ry, double rw, double rh) { + return all.stream() + .filter(d -> d.getPage() == page) + .filter(d -> intersects(d, rx, ry, rw, rh)) + .collect(Collectors.toList()); + } + + private boolean intersects(DimensionResult d, double rx, double ry, double rw, double rh) { + return d.getX() + d.getWidth() >= rx + && d.getX() <= rx + rw + && d.getY() + d.getHeight() >= ry + && d.getY() <= ry + rh; + } + + private static final Set STANDALONE_SYMBOLS = Set.of("Φ", "φ", "Ø", "∅", "¡¤"); + + /** + * 将区域筛选后的多条结果合并为一条,按阅读顺序拼接文本、取并集边界框。 + */ + public List mergeRegionResults(List filtered) { + if (filtered == null || filtered.size() <= 1) { + return filtered; + } + + // 过滤掉独立装饰符号(单字符 Φ/Ø 等) + List meaningful = filtered.stream() + .filter(d -> { + String dim = d.getDimension() == null ? "" : d.getDimension().trim(); + return !STANDALONE_SYMBOLS.contains(dim); + }) + .collect(Collectors.toList()); + + if (meaningful.isEmpty()) { + return filtered; + } + if (meaningful.size() == 1) { + return meaningful; + } + + // 按阅读顺序排序:Y 升序,X 升序 + meaningful.sort(Comparator.comparingDouble(DimensionResult::getY) + .thenComparingDouble(DimensionResult::getX)); + + // 拼接文本 + StringBuilder sb = new StringBuilder(); + for (DimensionResult d : meaningful) { + String dim = d.getDimension() == null ? "" : d.getDimension().trim(); + sb.append(dim); + } + + // 合并 tolerance + List tols = meaningful.stream() + .map(DimensionResult::getTolerance) + .filter(t -> t != null && !t.isEmpty()) + .collect(Collectors.toList()); + String mergedTol = tols.isEmpty() ? null : String.join(" / ", tols); + + // 计算并集边界框 + double minX = meaningful.stream().mapToDouble(DimensionResult::getX).min().orElse(0); + double minY = meaningful.stream().mapToDouble(DimensionResult::getY).min().orElse(0); + double maxX = meaningful.stream().mapToDouble(d -> d.getX() + d.getWidth()).max().orElse(0); + double maxY = meaningful.stream().mapToDouble(d -> d.getY() + d.getHeight()).max().orElse(0); + + DimensionResult merged = new DimensionResult(); + merged.setDimension(sb.toString()); + merged.setTolerance(mergedTol); + merged.setType("dimension"); + merged.setX(minX); + merged.setY(minY); + merged.setWidth(maxX - minX); + merged.setHeight(maxY - minY); + merged.setPage(meaningful.get(0).getPage()); + + return Collections.singletonList(merged); + } +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/QmsInspectionStandardDetailDTO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/QmsInspectionStandardDetailDTO.java new file mode 100644 index 00000000..36789c21 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/QmsInspectionStandardDetailDTO.java @@ -0,0 +1,170 @@ +package com.nflg.wms.common.pojo.dto; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class QmsInspectionStandardDetailDTO { + + /** + * 检验标准ID + */ + private Long id; + + /** + * 物料ID + */ + private Long materialId; + + /** + * 物料编号 + */ + private String materialNo; + + /** + * 物料类别路径名称 + */ + private String materialCategoryCodePathName; + + /** + * 物料描述 + */ + private String materialDesc; + + /** + * 图号版本号 + */ + private String drawingNoVer; + + /** + * 图纸URL + */ + private String drawingUrl; + + /** + * 版本号 + */ + private String version; + + /** + * 是否启用 + */ + private Boolean isEnabled; + + /** + * 包装方式ID + */ + private Long packagingMethodId; + + /** + * 检验周期 + */ + private Integer inspectionCycle; + + /** + * 检测方式字典项ID + */ + private Long testingMethodDictItemId; + + /** + * 检测方式字典项名称 + */ + private String testingMethodDictItemName; + + /** + * 抽样方案ID + */ + private Long samplingPlanId; + + /** + * 抽样方案名称 + */ + private String samplingPlanName; + + /** + * 检验水平字典项ID + */ + private Long inspectionLevelDictItemId; + + /** + * 检验水平字典项名称 + */ + private String inspectionLevelDictItemName; + + /** + * AQL值字典项ID + */ + private Long aqlPriorityValueId; + + /** + * AQL值 + */ + private BigDecimal aqlPriorityValue; + + /** + * AQL类型字典项ID + */ + private Long aqlTypeDictItemId; + + /** + * AQL类型字典项名称 + */ + private String aqlTypeDictItemName; + + /** + * 发布状态:0-未发布,1-已发布 + */ + private Short publishStatus; + + /** + * 发布人ID + */ + private Long publishUserId; + + /** + * 发布人姓名 + */ + private String publishUserName; + + /** + * 发布时间 + */ + private LocalDateTime publishTime; + + /** + * 所属IQE姓名 + */ + private String iqeName; + + /** + * 创建人ID + */ + private Long createUserId; + + /** + * 创建人姓名 + */ + private String createUserName; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新人ID + */ + private Long updateUserId; + + /** + * 更新人姓名 + */ + private String updateUserName; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsInspectionStandardMapper.java b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsInspectionStandardMapper.java index eaf9d8fb..86f7d183 100644 --- a/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsInspectionStandardMapper.java +++ b/nflg-wms-repository/src/main/java/com/nflg/wms/repository/mapper/QmsInspectionStandardMapper.java @@ -3,9 +3,9 @@ package com.nflg.wms.repository.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.nflg.wms.common.pojo.dto.QmsInspectionStandardDetailDTO; import com.nflg.wms.common.pojo.qo.QmsInspectionStandardSearchQO; import com.nflg.wms.common.pojo.vo.QmsIncomingInspectionTaskCheckItemVO; -import com.nflg.wms.common.pojo.vo.QmsInspectionStandardDetailVO; import com.nflg.wms.common.pojo.vo.QmsInspectionStandardVO; import com.nflg.wms.repository.entity.QmsInspectionStandard; import org.apache.ibatis.annotations.Param; @@ -25,7 +25,7 @@ public interface QmsInspectionStandardMapper extends BaseMapper getItemsForCheck(Long id); } diff --git a/nflg-wms-repository/src/main/resources/mapper/QmsInspectionStandardMapper.xml b/nflg-wms-repository/src/main/resources/mapper/QmsInspectionStandardMapper.xml index dba2b567..f2e55b4d 100644 --- a/nflg-wms-repository/src/main/resources/mapper/QmsInspectionStandardMapper.xml +++ b/nflg-wms-repository/src/main/resources/mapper/QmsInspectionStandardMapper.xml @@ -53,7 +53,7 @@ - SELECT s.id, s.material_id AS materialId, diff --git a/pom.xml b/pom.xml index eb7c429f..5136f7d6 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ nflg-wms-srm-receive nflg-wms-shipment nflg-qms-admin + nflg-qms-pdf-extract 17 @@ -125,6 +126,11 @@ nflg-wms-repository ${project.version} + + com.nflg + nflg-qms-pdf-extract + ${project.version} +