package jnpf.bizcommon.onlyoffice.service.impl; import jnpf.base.UserInfo; import jnpf.bizcommon.onlyoffice.entity.DmsPrintRenderItem; import jnpf.bizcommon.onlyoffice.entity.DmsPrintRenderRequest; import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeProperties; import jnpf.dmsEntity.preview.model.DmsFilePreviewTicket; import jnpf.exception.DataException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.UUID; @Service @RequiredArgsConstructor public class DmsOnlyOfficePrintService { private final DmsOnlyOfficePrintTicketValidator validator; private final OnlyOfficeDmsPrintRenderer renderer; private final DmsOnlyOfficePrintPdfComposer composer; private final OnlyOfficeProperties properties; public byte[] render(DmsPrintRenderRequest request, UserInfo user) { List items = items(request); UUID fileVersionId = items.get(0).getFileVersionId(); String fileName = items.get(0).getFileName(); Set accessTickets = new HashSet<>(); List tickets = new ArrayList<>(items.size()); for (DmsPrintRenderItem item : items) { if (!fileVersionId.equals(item.getFileVersionId()) || !fileName.equals(item.getFileName()) || !accessTickets.add(item.getAccessTicket())) { throw new DataException("批量打印必须使用同一文件且每份使用独立票据"); } DmsFilePreviewTicket ticket = validator.validate(item, user); applyPageSubset(ticket, item.getPrintPages()); tickets.add(ticket); } DmsPrintRenderItem sourceItem = request.sourceItem(); DmsFilePreviewTicket sourceTicket; if (sameItem(sourceItem, items.get(0))) { sourceTicket = tickets.get(0); } else { sourceTicket = validator.validate(sourceItem, user); if (!fileVersionId.equals(sourceItem.getFileVersionId()) || !fileName.equals(sourceItem.getFileName())) { throw new DataException("基础打印文件与批次文件不一致"); } } byte[] basePdf = renderer.renderBase(sourceTicket, sourceItem.getAccessTicket()); return composer.compose(basePdf, tickets); } private List items(DmsPrintRenderRequest request) { if (request == null) { throw new DataException("缺少 DMS 打印转换参数"); } boolean hasItems = request.getItems() != null; boolean hasLegacy = request.getFileVersionId() != null || !ObjectUtils.isEmpty(request.getFileName()) || !ObjectUtils.isEmpty(request.getAccessTicket()); if (hasItems == hasLegacy) { throw new DataException("单份打印参数和批量打印 items 必须且只能使用一种"); } List items = hasItems ? request.getItems() : List.of(request.legacyItem()); if (items.isEmpty() || items.size() > properties.getDmsPrint().getMaxBatchItems()) { throw new DataException("批量打印份数超过系统限制"); } for (DmsPrintRenderItem item : items) { if (item == null || item.getFileVersionId() == null || ObjectUtils.isEmpty(item.getFileName()) || ObjectUtils.isEmpty(item.getAccessTicket())) { throw new DataException("DMS 打印转换参数不完整"); } } return items; } private boolean sameItem(DmsPrintRenderItem left, DmsPrintRenderItem right) { return left != null && right != null && java.util.Objects.equals(left.getFileVersionId(), right.getFileVersionId()) && java.util.Objects.equals(left.getFileName(), right.getFileName()) && java.util.Objects.equals(left.getAccessTicket(), right.getAccessTicket()); } private void applyPageSubset(DmsFilePreviewTicket ticket, String requestedPages) { if (ObjectUtils.isEmpty(requestedPages)) return; Set requested = parsePages(requestedPages); if (!ObjectUtils.isEmpty(ticket.getPrintPages()) && !parsePages(ticket.getPrintPages()).containsAll(requested)) { throw new DataException("批次打印页码超出票据授权范围"); } ticket.setPrintPages(requestedPages.trim()); } private Set parsePages(String value) { Set pages = new LinkedHashSet<>(); for (String raw : value.split(",", -1)) { String token = raw.trim(); if (!token.matches("\\d+(?:\\s*-\\s*\\d+)?")) { throw new DataException("批次打印页码格式无效"); } String[] bounds = token.split("\\s*-\\s*"); int start; int end; try { start = Integer.parseInt(bounds[0]); end = bounds.length == 1 ? start : Integer.parseInt(bounds[1]); } catch (NumberFormatException exception) { throw new DataException("批次打印页码格式无效"); } if (start < 1 || end < start || end - start + 1L + pages.size() > properties.getDmsPrint().getMaxPages()) { throw new DataException("批次打印页码超过系统限制"); } for (int page = start; page <= end; page++) pages.add(page); } return pages; } }