From 93fac8ec5ac0cbafb1bf2af67917fee667faabce Mon Sep 17 00:00:00 2001 From: YBP Date: Wed, 1 Apr 2026 17:23:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96onlyoffice=E5=9C=A8=E7=BA=BF?= =?UTF-8?q?=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/OnlyOfficeController.java | 17 +++-- .../service/OnlyOfficeServiceImpl.java | 67 ++++++++++++++++--- .../RecordFileAttachmentService.java | 2 + .../RecordFileAttachmentServiceImpl.java | 7 ++ .../recordrecord/RecordRecordServiceImpl.java | 64 +++++++++++++++++- 5 files changed, 137 insertions(+), 20 deletions(-) diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/controller/admin/OnlyOfficeController.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/controller/admin/OnlyOfficeController.java index 49dd0a46..c3ae5059 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/controller/admin/OnlyOfficeController.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/controller/admin/OnlyOfficeController.java @@ -1,7 +1,6 @@ package com.zt.plat.module.qms.resource.record.controller.admin.onlyOffice.controller.admin; -import com.zt.plat.framework.business.annotation.FileUploadController; import com.zt.plat.framework.business.controller.AbstractFileUploadController; import com.zt.plat.framework.business.interceptor.BusinessControllerMarker; import com.zt.plat.framework.common.enums.UserTypeEnum; @@ -12,7 +11,6 @@ import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils; import com.zt.plat.framework.tenant.core.aop.TenantIgnore; import com.zt.plat.module.qms.resource.record.controller.admin.onlyOffice.controller.vo.OnlyOfficeEditorConfigRespVO; import com.zt.plat.module.qms.resource.record.controller.admin.onlyOffice.service.OnlyOfficeService; -import com.zt.plat.module.qms.resource.record.controller.admin.recordrecord.RecordRecordController; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -34,15 +32,15 @@ import static com.zt.plat.framework.common.pojo.CommonResult.success; @RequestMapping("/qms/common/only-office") @Validated @DeptDataPermissionIgnore(enable = "true") -@FileUploadController(source = "qms.only-office", codeKey = "data.fileUploadBusinessCode") +//@FileUploadController(source = "qms.only-office", codeKey = "data.fileUploadBusinessCode") public class OnlyOfficeController extends AbstractFileUploadController implements BusinessControllerMarker { - static { - FileUploadController annotation = RecordRecordController.class.getAnnotation(FileUploadController.class); - if (annotation != null) { - setFileUploadInfo(annotation); - } - } +// static { +// FileUploadController annotation = RecordRecordController.class.getAnnotation(FileUploadController.class); +// if (annotation != null) { +// setFileUploadInfo(annotation); +// } +// } @Resource private OnlyOfficeService onlyOfficeService; @@ -57,6 +55,7 @@ public class OnlyOfficeController extends AbstractFileUploadController implement @GetMapping("/file-content") @Operation(summary = "获取文档文件内容") @PermitAll + @TenantIgnore public void getFileContent(@RequestParam("fileId") Long fileId, @RequestParam("token") String token, HttpServletResponse response) { diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/service/OnlyOfficeServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/service/OnlyOfficeServiceImpl.java index 71c72efd..1b6355c9 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/service/OnlyOfficeServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/controller/admin/onlyOffice/service/OnlyOfficeServiceImpl.java @@ -8,6 +8,8 @@ import com.zt.plat.module.infra.api.businessfile.BusinessFileApi; import com.zt.plat.module.infra.api.file.FileApi; import com.zt.plat.module.infra.api.file.dto.FileRespDTO; import com.zt.plat.module.qms.resource.record.controller.admin.onlyOffice.controller.vo.OnlyOfficeEditorConfigRespVO; +import com.zt.plat.module.qms.resource.record.dal.dataobject.recordfileattachment.RecordFileAttachmentDO; +import com.zt.plat.module.qms.resource.record.service.recordfileattachment.RecordFileAttachmentService; import com.zt.plat.module.system.api.user.AdminUserApi; import com.zt.plat.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; @@ -30,6 +32,9 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService{ @Resource private AdminUserApi adminUserApi; + @Resource + private RecordFileAttachmentService recordFileAttachmentService; + private static final String TEXT_DOCUMENT_EXTENSIONS = "doc,docx,odt,rtf,txt,html,htm,mht,pdf,djvu,fb2,epub,xps"; private static final String SPREADSHEET_EXTENSIONS = "xls,xlsx,ods,csv"; private static final String PRESENTATION_EXTENSIONS = "ppt,pptx,odp"; @@ -93,7 +98,11 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService{ @Override public OnlyOfficeEditorConfigRespVO getEditorConfig(Long id) { - +// RecordFileAttachmentDO recordFileAttachment = recordFileAttachmentService.getRecordFileAttachment(id); +// if (recordFileAttachment == null) { +// CommonResult.error(DOC_NOT_EXISTS); +// return null; +// } Long userId = SecurityFrameworkUtils.getLoginUserId(); OnlyOfficeEditorConfigRespVO resp = new OnlyOfficeEditorConfigRespVO(); @@ -114,8 +123,8 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService{ // 关键修复:使用基于文档版本的稳定key策略 // 只有当文档内容真正发生版本变更时,key才会改变 -// String documentKey = id + "_v" + data.getUpdateTime(); -// document.setKey(documentKey); + String documentKey = id + "_v" + System.currentTimeMillis(); + document.setKey(documentKey); document.setTitle(fileName); // log.info("生成文档key: docId={}, key={}, latestVersionId={}, userId={}", @@ -128,7 +137,7 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService{ String fileToken = generateFileToken(data.getId()); // 生成通过新接口访问文件的URL,包含JWT token - fileUrl = StrUtil.removeSuffix(onlyOfficeCallbackBaseUrl, "/") + "/admin-api/infra/doc-file/file-content?fileId=" + data.getId(); + fileUrl = StrUtil.removeSuffix(onlyOfficeCallbackBaseUrl, "/") + "/admin-api/qms/common/only-office/file-content?fileId=" + data.getId(); if (StrUtil.isNotBlank(fileToken)) { fileUrl += "&token=" + fileToken; } @@ -246,16 +255,58 @@ public class OnlyOfficeServiceImpl implements OnlyOfficeService{ return; } - // 获取文件内容 + // 获取文件内容:优先从 content 字段取,若为 null(文件存储在外网OSS时)则通过 URL 下载 byte[] content = file.getContent(); if (content == null) { - response.setStatus(HttpServletResponse.SC_NOT_FOUND); - return; + // 文件存储在外网(OSS/MinIO等),通过 URL 下载文件内容 + String fileUrl = file.getUrl(); + if (StrUtil.isBlank(fileUrl)) { + log.error("文件内容和URL均为空,无法提供文件: fileId={}", fileId); + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return; + } + log.info("文件content为空,通过URL下载: fileId={}, url={}", fileId, fileUrl); + try { + java.net.URL url = new java.net.URL(fileUrl); + java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection(); + conn.setConnectTimeout(10000); + conn.setReadTimeout(30000); + conn.setRequestMethod("GET"); + int statusCode = conn.getResponseCode(); + if (statusCode != 200) { + log.error("从外网URL下载文件失败: fileId={}, url={}, httpStatus={}", fileId, fileUrl, statusCode); + response.setStatus(HttpServletResponse.SC_BAD_GATEWAY); + return; + } + // 设置响应头 + response.setContentType(file.getType() != null ? file.getType() : "application/octet-stream"); + response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\""); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); + response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With"); + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "0"); + // 流式透传,避免大文件OOM + try (java.io.InputStream in = conn.getInputStream(); + OutputStream os = response.getOutputStream()) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + os.flush(); + } + return; + } catch (Exception e) { + log.error("从外网URL下载文件异常: fileId={}, url={}", fileId, fileUrl, e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } } // 设置响应头 response.setContentType(file.getType() != null ? file.getType() : "application/octet-stream"); -// response.setContentLength(content.length); response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\""); // 添加跨域头,允许 OnlyOffice 访问 response.setHeader("Access-Control-Allow-Origin", "*"); diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentService.java index bf360b4c..be68f1aa 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentService.java @@ -63,4 +63,6 @@ public interface RecordFileAttachmentService { PageResult getRecordFileAttachmentPage(RecordFileAttachmentPageReqVO pageReqVO); int createRecordFileAttachmentBatch(List createAttachmentReqVOList); + + void deleteRecordFileAttachmentByRecord(Long recordId); } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentServiceImpl.java index c993bba3..de09eed6 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordfileattachment/RecordFileAttachmentServiceImpl.java @@ -3,6 +3,7 @@ package com.zt.plat.module.qms.resource.record.service.recordfileattachment; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.jwt.JWT; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.zt.plat.framework.common.pojo.PageResult; import com.zt.plat.framework.common.util.object.BeanUtils; import com.zt.plat.module.qms.resource.record.controller.admin.recordfileattachment.vo.RecordFileAttachmentPageReqVO; @@ -97,6 +98,12 @@ public class RecordFileAttachmentServiceImpl implements RecordFileAttachmentServ return bean.size(); } + @Override + public void deleteRecordFileAttachmentByRecord(Long recordId) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(RecordFileAttachmentDO::getRecordId, recordId); + recordFileAttachmentMapper.delete(query); + } } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordrecord/RecordRecordServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordrecord/RecordRecordServiceImpl.java index faae55cf..6712f090 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordrecord/RecordRecordServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/record/service/recordrecord/RecordRecordServiceImpl.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Optional; import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception0; import static com.zt.plat.module.qms.enums.ErrorCodeConstants.*; /** @@ -96,7 +97,7 @@ public class RecordRecordServiceImpl implements RecordRecordService { // 添加文件记录附件 List files = createReqVO.getFiles(); - createFileAttachment(files,recordRecordDO.getId()); + createFileAttachment(files, recordRecordDO.getId()); } catch (Exception e) { throw new RuntimeException("create record error"); @@ -105,6 +106,11 @@ public class RecordRecordServiceImpl implements RecordRecordService { return BeanUtils.toBean(recordRecord, RecordRecordRespVO.class); } + // 删除附件,通过recordId + public void deleteFileAttachment(Long recordId) { + recordFileAttachmentService.deleteRecordFileAttachmentByRecord(recordId); + } + // 添加文件记录附件 public void createFileAttachment(List files, Long recordId) { // List files = createReqVO.getFiles(); @@ -178,7 +184,7 @@ public class RecordRecordServiceImpl implements RecordRecordService { recordRecordMapper.insert(recordRecordDO); // 添加文件记录附件 - createFileAttachment(createReqVO.getFiles(),recordRecordDO.getId()); + createFileAttachment(createReqVO.getFiles(), recordRecordDO.getId()); // 返回 return BeanUtils.toBean(recordRecordDO, RecordRecordRespVO.class); } catch (Exception e) { @@ -273,6 +279,57 @@ public class RecordRecordServiceImpl implements RecordRecordService { // return BeanUtils.toBean(recordRecordList, RecordRecordRespVO.class); // // } + // 文件提交,修改生效状态 + public void recordSubmitStatus(RecordRecordDO recordDO) { + Integer recordStatus = recordDO.getRecordStatus(); + if (recordStatus != null && recordStatus == 1) + throw exception0(RECORD_APPLY_NOT_EXISTS.getCode(), "文件已提交,无法提交申请"); +// RecordCategoryDO recordCategory = recordCategoryService.getRecordCategory(recordDO.getCategoryId()); + // 获取分类的根分类Id +// String idPath = recordCategory.getIdPath(); +// Optional segment = RecordCommonUtils.getSegment(idPath, 1); +// String s = segment.orElse(null); +// if (ObjectUtils.isEmpty(s)) +// throw exception(RECORD_APPLY_NOT_EXISTS); +// RecordCategoryDO category = recordCategoryService.getRecordCategory(Long.valueOf(s)); +// String customConfig = category.getCustomConfig(); +// if (ObjectUtils.isEmpty(customConfig)) { // 空,直接判断是否到生效日期 + // 判断是否到生效日期 +// RecordRecordDO effectiveRecordRecordDO = isEffective(recordDO); +// this.updateRecordRecordById(effectiveRecordRecordDO); +// return true; +// } +// JSONObject jsonObject = JSONObject.parseObject(customConfig); +// Integer submitFlag = jsonObject.getInteger("submitFlag"); +// if (submitFlag == 0) { + // 不允许提交,直接修改文件记录状态 +// recordDO.setRecordStatus(1); // 已生效 + RecordRecordDO effectiveRecordRecordDO = isEffective(recordDO); + this.updateRecordRecordById(effectiveRecordRecordDO); +// return true; +// } else { // 需要走流程 +// recordDO.setSubmitFlag(1); +// recordDO.setRecordStatus(0); +// this.updateRecordRecordById(recordDO); +// } + +// return false; + } + + // 判断文件记录生效状态 + public RecordRecordDO isEffective(RecordRecordDO recordDO) { + LocalDateTime effectiveDate = recordDO.getEffectiveDate(); + if (effectiveDate == null) { // 没有生效日期,立即生效 + recordDO.setRecordStatus(1); + } else { + recordDO.setRecordStatus(0); // 待生效 + LocalDateTime now = LocalDateTime.now(); + if (now.isAfter(effectiveDate) || now.isEqual(effectiveDate)) { + recordDO.setRecordStatus(1); // 已生效 + } + } + return recordDO; + } //通过跟分类的自定义属性判断文件状态 @@ -316,6 +373,7 @@ public class RecordRecordServiceImpl implements RecordRecordService { //删除附件 //TODO + deleteFileAttachment(updateObj.getId()); // 保存附件 List files = updateObj.getFiles(); createFileAttachment(files, updateObj.getId()); @@ -653,7 +711,7 @@ public class RecordRecordServiceImpl implements RecordRecordService { public PageResult getLookRecordList(RecordRecordPageReqVO pageReqVO) { Long categoryId = pageReqVO.getCategoryId(); if (categoryId == null) return PageResult.empty(); - PageResult recordRecordDOPageResult = selectRecordPage(pageReqVO,categoryId,null); + PageResult recordRecordDOPageResult = selectRecordPage(pageReqVO, categoryId, null); return BeanUtils.toBean(recordRecordDOPageResult, RecordRecordRespVO.class); }