package jnpf.dmsService; import jnpf.audit.sdk.annotation.AuditLog; import jnpf.base.UserInfo; import jnpf.dmsEntity.compare.DmsCompareRequest; import jnpf.dmsEntity.compare.DmsCompareTicket; import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity; import jnpf.dmsEntity.permission.enums.DmsPermissionAction; import jnpf.dmsEntity.permission.enums.DmsResourceType; import jnpf.dmsEntity.preview.form.DmsFilePreviewTicketRequest; import jnpf.dmsEntity.preview.vo.DmsFilePreviewTicketVO; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.exception.DataException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.UUID; @Service @RequiredArgsConstructor public class DmsFileCompareService { private final DmsCurrentIdentity identity; private final DmsPermissionDecisionService permissions; private final DmsFileVersionMapper versions; private final DmsFilePreviewService previews; private final DmsCompareTicketIssuer issuer; @AuditLog(action = "FILE_VERSION_COMPARE", label = "文件版本比较", bizModule = "DMS", bizCodeExpr = "#p0.documentId", extraExpr = "{'historicalVersionId': #p0.historicalVersionId, 'currentVersionId': #p0.currentVersionId}") public String createTicket(DmsCompareRequest request) { UserInfo user = identity.requireUser(); String tenant = identity.tenantId(user); permissions.requireAllowed(DmsResourceType.FILE_VERSION, request.getCurrentVersionId(), DmsPermissionAction.READ); permissions.requireAllowed(DmsResourceType.FILE_VERSION, request.getHistoricalVersionId(), DmsPermissionAction.READ); DmsFileVersionEntity current = versions.selectCurrentEffective(tenant, request.getDocumentId()); DmsFileVersionEntity historical = versions.selectReadableByTenantAndId(tenant, request.getHistoricalVersionId()); validatePair(request, current, historical); DmsCompareTicket ticket = new DmsCompareTicket(); ticket.setTenantId(tenant); ticket.setUserId(user.getUserId()); ticket.setDocumentId(request.getDocumentId()); ticket.setHistoricalLabel(label(historical)); ticket.setCurrentLabel(label(current)); ticket.setHistorical(preview(historical.getId(), request.getOperationId(), "historical")); ticket.setCurrent(preview(current.getId(), request.getOperationId(), "current")); ticket.setExpiresAt(Math.min(ticket.getHistorical().getExpiresAt().getTime(), ticket.getCurrent().getExpiresAt().getTime())); return issuer.issue(ticket, Math.max(1, (ticket.getExpiresAt() - System.currentTimeMillis()) / 1000)); } static void validatePair(DmsCompareRequest request, DmsFileVersionEntity current, DmsFileVersionEntity historical) { if (current == null || !current.getId().equals(request.getCurrentVersionId())) { throw new DataException("现行版本已变化,请刷新文件列表后重新比较"); } if (historical == null || !request.getDocumentId().equals(current.getDocumentId()) || !request.getDocumentId().equals(historical.getDocumentId()) || historical.getId().equals(current.getId()) || historical.getVersionNo() == null || current.getVersionNo() == null || historical.getVersionNo() >= current.getVersionNo()) { throw new DataException("请选择同一文件之前修订的历史版本"); } if (!isDocx(current.getFileName()) || !isDocx(historical.getFileName())) { throw new DataException("版本比较目前仅支持 DOCX 文件"); } } private DmsFilePreviewTicketVO preview(UUID id, UUID operationId, String side) { DmsFilePreviewTicketRequest request = new DmsFilePreviewTicketRequest(); request.setResourceType(DmsResourceType.FILE_VERSION); request.setResourceId(id); request.setOperationId(UUID.nameUUIDFromBytes((operationId + ":compare:" + side + ":" + id).getBytes(StandardCharsets.UTF_8))); return previews.createTicket(request); } private static boolean isDocx(String name) { return name != null && name.toLowerCase(Locale.ROOT).endsWith(".docx"); } private static String label(DmsFileVersionEntity version) { return version.getVersionLabel() == null || version.getVersionLabel().trim().isEmpty() ? "v" + version.getVersionNo() : version.getVersionLabel(); } }