package jnpf.dmsService;
|
|
import jnpf.base.UserInfo;
|
import jnpf.dmsEntity.permission.entity.DmsDocumentEntity;
|
import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
|
import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
|
import jnpf.dmsEntity.permission.enums.DmsResourceType;
|
import jnpf.dmsEntity.preview.model.DmsFilePreviewTicket;
|
import jnpf.dmsEntity.print.form.DmsFilePrintTicketRequest;
|
import jnpf.dmsEntity.print.form.DmsPrintOperationCreateForm;
|
import jnpf.dmsEntity.print.form.DmsPrintTargetForm;
|
import jnpf.dmsEntity.print.vo.DmsFilePrintTicketVO;
|
import jnpf.dmsEntity.storage.entity.DmsFileObjectEntity;
|
import jnpf.dmsMapper.DmsDocumentMapper;
|
import jnpf.dmsMapper.DmsFileObjectMapper;
|
import jnpf.dmsMapper.DmsFileVersionMapper;
|
import jnpf.dmsPermission.DmsCurrentIdentity;
|
import jnpf.dmsPermission.DmsFileControlPolicy;
|
import jnpf.dmsPermission.DmsPermissionError;
|
import jnpf.dmsPermission.DmsPermissionException;
|
import jnpf.dmsPermission.DmsPermissionExecutionContext;
|
import jnpf.dmsPermission.DmsPermissionGuard;
|
import jnpf.dmsPermission.DmsPermissionOperation;
|
import jnpf.dmsService.pdf.DmsPersistentPdfSources;
|
import jnpf.dmsService.pdf.DmsPdfGenerationTaskService;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.UUID;
|
|
@Service
|
@RequiredArgsConstructor
|
public class DmsFilePrintService {
|
static final long TICKET_TTL_SECONDS = 5L * 60L;
|
|
private final DmsCurrentIdentity currentIdentity;
|
private final DmsPermissionGuard permissionGuard;
|
private final DmsFileVersionMapper fileVersionMapper;
|
private final DmsFileObjectMapper fileObjectMapper;
|
private final DmsDocumentMapper documentMapper;
|
private final DmsFilePreviewTicketIssuer ticketIssuer;
|
private final DmsPrintOperationLogService printOperationLogService;
|
private final DmsWatermarkPreviewResolver watermarkPreviewResolver;
|
private final DmsPdfGenerationTaskService pdfGenerationTaskService;
|
|
@Transactional(rollbackFor = Exception.class)
|
public DmsFilePrintTicketVO createTicket(DmsFilePrintTicketRequest request) {
|
request.normalized();
|
UserInfo user = currentIdentity.requireUser();
|
String tenantId = currentIdentity.tenantId(user);
|
DmsFileVersionEntity resolvedVersion = resolveFileVersion(request, tenantId);
|
UUID fileVersionId = resolvedVersion.getId();
|
long expiresAtMillis = System.currentTimeMillis() + TICKET_TTL_SECONDS * 1000L;
|
|
PrintSource source = DmsFileControlPolicy.requiresPermissionCheck(
|
resolvedVersion.getShifouShoukong())
|
? loadPrintSourceWithPermission(request, tenantId, fileVersionId)
|
: loadPrintSource(tenantId, fileVersionId);
|
|
DmsFilePreviewTicket payload = payload(user, tenantId, source, expiresAtMillis, request);
|
if (Boolean.TRUE.equals(request.getRequireSerialWatermark())) {
|
if (request.getCustomBarcode() == null || request.getCustomBarcode().size() != 1
|
|| payload.getWatermarks() == null || payload.getWatermarks().stream().noneMatch(mark ->
|
Boolean.TRUE.equals(mark.getCustomBarcode())
|
&& java.util.Objects.equals(mark.getContent(), request.getCustomBarcode().getFirst().getBarValue())
|
&& java.util.Objects.equals(mark.getBarcodeText(), request.getCustomBarcode().getFirst().getBarText())
|
&& mark.getPositions() != null && !mark.getPositions().isEmpty())) {
|
throw new jnpf.exception.DataException("逐份流水水印未启用或未配置位置,已阻止发送无流水文件");
|
}
|
}
|
String accessTicket = ticketIssuer.issue(payload, TICKET_TTL_SECONDS);
|
recordPrint(request, source);
|
|
DmsFilePrintTicketVO result = new DmsFilePrintTicketVO();
|
result.setFileVersionId(fileVersionId);
|
result.setFileName(source.version.getFileName());
|
result.setMimeType(source.version.getMimeType());
|
result.setSizeBytes(source.version.getSizeBytes());
|
result.setCopies(request.getCopies());
|
result.setPrintPages(trimToNull(request.getPrintPages()));
|
result.setAccessTicket(accessTicket);
|
result.setExpiresAt(new Date(expiresAtMillis));
|
return result;
|
}
|
|
private DmsFileVersionEntity resolveFileVersion(DmsFilePrintTicketRequest request,
|
String tenantId) {
|
if (request.getResourceType() == DmsResourceType.DOCUMENT) {
|
DmsFileVersionEntity current = fileVersionMapper.selectCurrentEffective(
|
tenantId, request.getResourceId());
|
if (current == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
|
"文件没有现行有效版本");
|
}
|
return current;
|
}
|
if (request.getResourceType() == DmsResourceType.FILE_VERSION) {
|
DmsFileVersionEntity version = fileVersionMapper.selectReadableByTenantAndId(
|
tenantId, request.getResourceId());
|
if (version == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
|
"文件版本不存在");
|
}
|
return version;
|
}
|
throw DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST,
|
"仅支持打印 DOCUMENT 或 FILE_VERSION");
|
}
|
|
private PrintSource loadPrintSourceWithPermission(DmsFilePrintTicketRequest request,
|
String tenantId, UUID fileVersionId) {
|
DmsPermissionExecutionContext context = new DmsPermissionExecutionContext();
|
context.setResourceType(DmsResourceType.FILE_VERSION);
|
context.setResourceId(fileVersionId);
|
context.setActionCode(DmsPermissionAction.PRINT);
|
context.setOperationId(request.getOperationId());
|
return permissionGuard.execute(context, new DmsPermissionOperation<PrintSource>() {
|
@Override
|
public PrintSource execute() {
|
return loadPrintSource(tenantId, fileVersionId);
|
}
|
|
@Override
|
public PrintSource replay() {
|
return loadPrintSource(tenantId, fileVersionId);
|
}
|
});
|
}
|
|
private PrintSource loadPrintSource(String tenantId, UUID fileVersionId) {
|
DmsFileVersionEntity version = fileVersionMapper.selectReadableByTenantAndId(
|
tenantId, fileVersionId);
|
DmsFileObjectEntity object = fileObjectMapper.selectByTenantAndFileVersionId(
|
tenantId, fileVersionId);
|
DmsDocumentEntity document = version == null ? null
|
: documentMapper.selectByTenantAndId(tenantId, version.getDocumentId());
|
if (version == null || object == null || document == null) {
|
throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND,
|
"文件版本、文档或存储对象不存在");
|
}
|
return new PrintSource(version, object, document);
|
}
|
|
private DmsFilePreviewTicket payload(UserInfo user, String tenantId, PrintSource source,
|
long expiresAtMillis, DmsFilePrintTicketRequest request) {
|
DmsFilePreviewTicket payload = new DmsFilePreviewTicket();
|
payload.setScope(DmsFilePreviewTicket.PRINT_SCOPE);
|
payload.setTenantId(tenantId);
|
payload.setUserId(user.getUserId().trim());
|
payload.setFileVersionId(source.version.getId());
|
payload.setHistoricalAccess(source.version.getLifecycleStatus() != null
|
&& !"EFFECTIVE".equals(source.version.getLifecycleStatus()));
|
payload.setFileName(source.version.getFileName());
|
payload.setMimeType(source.version.getMimeType());
|
payload.setSizeBytes(source.version.getSizeBytes());
|
payload.setStoragePlatform(source.object.getStoragePlatform());
|
payload.setBucketName(source.object.getBucketName());
|
payload.setBasePath(source.object.getBasePath());
|
payload.setObjectPath(source.object.getObjectPath());
|
payload.setObjectName(source.object.getObjectName());
|
payload.setPdfSource(DmsPersistentPdfSources.valid(source.version, source.object));
|
if (payload.getPdfSource() == null) {
|
pdfGenerationTaskService.enqueueMissingEligible(tenantId, source.version.getId(),
|
source.version.getFileName(), source.version.getChecksumSha256());
|
}
|
payload.setPrintPages(trimToNull(request.getPrintPages()));
|
payload.setWatermarks(watermarkPreviewResolver.resolvePrint(
|
user, tenantId, source.version, request));
|
payload.setExpiresAt(expiresAtMillis);
|
return payload;
|
}
|
|
private void recordPrint(DmsFilePrintTicketRequest request, PrintSource source) {
|
String pages = trimToNull(request.getPrintPages());
|
String remark = pages == null ? null : "打印页码:" + pages;
|
String printName = trimToNull(source.document.getName());
|
if (printName == null) {
|
printName = source.version.getFileName();
|
}
|
|
DmsPrintTargetForm target = new DmsPrintTargetForm();
|
target.setTargetType("DOCUMENT");
|
target.setTargetId(source.document.getId().toString());
|
target.setDocumentId(source.document.getId().toString());
|
target.setDocumentCode(source.document.getDocumentNo());
|
target.setDocumentName(printName);
|
target.setVersionNo(versionText(source.version));
|
target.setRemark(remark);
|
|
DmsPrintOperationCreateForm form = new DmsPrintOperationCreateForm();
|
form.setClientEventId(request.getOperationId().toString());
|
form.setPrintType("CONTROLLED_DOCUMENT");
|
form.setSourceType("FILE_PREVIEW");
|
form.setCopies(request.getCopies());
|
form.setRemark(remark);
|
form.setPrintName(printName);
|
form.setTargets(Collections.singletonList(target));
|
printOperationLogService.create(form);
|
}
|
|
private String versionText(DmsFileVersionEntity version) {
|
String label = trimToNull(version.getVersionLabel());
|
return label == null && version.getVersionNo() != null
|
? String.valueOf(version.getVersionNo()) : label;
|
}
|
|
private String trimToNull(String value) {
|
return value == null || value.trim().isEmpty() ? null : value.trim();
|
}
|
|
private static final class PrintSource {
|
private final DmsFileVersionEntity version;
|
private final DmsFileObjectEntity object;
|
private final DmsDocumentEntity document;
|
|
private PrintSource(DmsFileVersionEntity version, DmsFileObjectEntity object,
|
DmsDocumentEntity document) {
|
this.version = version;
|
this.object = object;
|
this.document = document;
|
}
|
}
|
}
|