diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/preview/DocumentPreviewController.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/preview/DocumentPreviewController.java new file mode 100644 index 0000000..52c2e15 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/preview/DocumentPreviewController.java @@ -0,0 +1,84 @@ +package cn.craftlabs.platform.api.preview; + +import cn.craftlabs.platform.api.persistence.attachment.PlatformContractAttachment; +import cn.craftlabs.platform.api.persistence.attachment.PlatformContractAttachmentMapper; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.util.Map; + +@RestController +@RequestMapping("/api/v1/preview") +public class DocumentPreviewController { + + private final PlatformContractAttachmentMapper attachmentMapper; + + @Value("${onlyoffice.url:http://craftsupport.cn:8088}") + private String onlyofficeUrl; + + public DocumentPreviewController(PlatformContractAttachmentMapper attachmentMapper) { + this.attachmentMapper = attachmentMapper; + } + + @GetMapping("/{attachmentId}") + public ResponseEntity> getPreviewConfig(@PathVariable("attachmentId") Long attachmentId) { + PlatformContractAttachment attachment = attachmentMapper.selectById(attachmentId); + if (attachment == null) { + throw new ResponseStatusException(org.springframework.http.HttpStatus.NOT_FOUND, "附件不存在"); + } + + String ext = ""; + String fileName = attachment.getFileName(); + if (fileName != null && fileName.contains(".")) { + ext = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase(); + } + + Map config = new java.util.LinkedHashMap<>(); + config.put("document", Map.of( + "fileType", ext, + "key", "attachment_" + attachmentId, + "title", attachment.getFileName(), + "url", getFileUrl(attachmentId), + "permissions", Map.of("download", false, "edit", false, "print", false) + )); + config.put("editorConfig", Map.of( + "mode", "view", + "customization", Map.of("autosave", false, "chat", false, "compactHeader", true) + )); + config.put("documentServerUrl", onlyofficeUrl); + + return ResponseEntity.ok(config); + } + + @GetMapping("/{attachmentId}/file") + public ResponseEntity getFile(@PathVariable("attachmentId") Long attachmentId) { + PlatformContractAttachment attachment = attachmentMapper.selectById(attachmentId); + if (attachment == null) { + throw new ResponseStatusException(org.springframework.http.HttpStatus.NOT_FOUND, "附件不存在"); + } + + java.io.File file = new java.io.File(attachment.getFilePath()); + if (!file.exists()) { + throw new ResponseStatusException(org.springframework.http.HttpStatus.NOT_FOUND, "文件不存在"); + } + + FileSystemResource resource = new FileSystemResource(file); + String contentType = attachment.getContentType(); + if (contentType == null) contentType = "application/octet-stream"; + + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType(contentType)) + .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + attachment.getFileName() + "\"") + .body(resource); + } + + private String getFileUrl(Long attachmentId) { + return "/api/v1/preview/" + attachmentId + "/file"; + } +} diff --git a/web/delivery-platform-ui/src/views/ContractDetailView.vue b/web/delivery-platform-ui/src/views/ContractDetailView.vue index 4846efa..e6c015d 100644 --- a/web/delivery-platform-ui/src/views/ContractDetailView.vue +++ b/web/delivery-platform-ui/src/views/ContractDetailView.vue @@ -86,9 +86,18 @@ + + + + +