From 8823952badc4fac1ad50204ee62c6a52b96d6c33 Mon Sep 17 00:00:00 2001 From: FCL Date: Thu, 12 Mar 2026 09:49:56 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E6=8A=A5=E5=91=8A?= =?UTF-8?q?=E7=BC=96=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ReportDocumentAssistService.java | 5 ++--- .../service/ReportDocumentMainService.java | 5 ++--- .../service/ReportDocumentMainServiceImpl.java | 15 ++++++++++++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java index d9de9d9b..87592bbe 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java @@ -56,10 +56,9 @@ public class ReportDocumentAssistService { @Resource private ReportDocumentTypeService reportDocumentTypeService; @Resource private ReportDocumentFileService reportDocumentFileService; @Resource private DataTemplateService dataTemplateService; - @Resource private SequenceUtil sequenceUtil; @Resource private FileApi fileApi; - private String sequenceKey = "QMS_REPORT_IWORK_CODE"; +// private String sequenceKey = "QMS_REPORT_IWORK_CODE"; // todo 判断是否更新pdf public boolean checkUpdateDocFile(JSONObject variables){ @@ -105,7 +104,7 @@ public class ReportDocumentAssistService { dto.setYysy("检测报告用印"); dto.setYysx("检测报告用印"); dto.setXyywjUrl(docFile.getUrl()); - dto.setYwxtdjbh(sequenceUtil.genCode(sequenceKey)); + dto.setYwxtdjbh(entity.getDocumentCode()); dto.setBizCallbackKey(ReportDocListenerConstant.IWORK_BIZ_CALL_BACK_KEY); //业务回调标识,回调分发使用 return iWorkIntegrationApi.createWorkflow(dto); } diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainService.java index dec48649..21794e17 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainService.java @@ -6,8 +6,7 @@ import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessAssayReportDat import com.zt.plat.module.qms.business.bus.dal.dataobject.BusinessSampleEntrustRegistrationDO; import com.zt.plat.module.qms.business.reportdoc.controller.vo.*; import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentMainDO; -import com.zt.plat.module.system.api.iwork.dto.IWorkOperationRespDTO; -import com.zt.plat.module.system.api.iwork.dto.IWorkWorkflowCreateReqDTO; +import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentTypeDO; import jakarta.validation.Valid; import java.util.List; @@ -31,7 +30,7 @@ public interface ReportDocumentMainService { //移除数据 CommonResult execRemoveData(ReportDocumentMainSaveReqVO reqVO); - void updateCommonField(ReportDocumentMainDO reportDocumentMainDO); + void updateCommonField(ReportDocumentMainDO reportDocumentMainDO, ReportDocumentTypeDO typeDO); //保存报告 void doSave(@Valid ReportDocumentMainSaveReqVO updateReqVO); diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java index baa8974d..2b5818c7 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java @@ -29,6 +29,7 @@ import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentTy import com.zt.plat.module.qms.business.reportdoc.dal.mapper.ReportDocumentMainMapper; import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentMainDO; import com.zt.plat.module.qms.common.data.service.DataKeyCheckService; +import com.zt.plat.module.qms.core.code.SequenceUtil; import com.zt.plat.module.qms.enums.QmsBpmConstant; import com.zt.plat.module.qms.enums.QmsCommonConstant; import jakarta.annotation.Resource; @@ -70,6 +71,7 @@ public class ReportDocumentMainServiceImpl implements ReportDocumentMainService, @Resource private BusinessSampleEntrustRegistrationService businessSampleEntrustRegistrationService; @Resource private ReportDocumentAssistService reportDocumentAssistService; @Resource private DataKeyCheckService dataKeyCheckService; + @Resource private SequenceUtil sequenceUtil; /* * 测试异步执行 @@ -190,14 +192,15 @@ public class ReportDocumentMainServiceImpl implements ReportDocumentMainService, if(!insertList.isEmpty()) reportDocumentDataService.insertBatch(insertList); ReportDocumentMainDO reportDocumentMainDO = reportDocumentMainMapper.selectById(id); - updateCommonField(reportDocumentMainDO); + ReportDocumentTypeDO typeDO = reportDocumentTypeService.getReportDocumentType(reportDocumentMainDO.getReportDocumentTypeId()); + updateCommonField(reportDocumentMainDO, typeDO); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String formData = reportDocumentMainDO.getFormData(); JSONObject formDataJson = new JSONObject(); if(!ObjectUtils.isEmpty(formData)) formDataJson = JSONObject.parseObject(formData); - ReportDocumentTypeDO typeDO = reportDocumentTypeService.getReportDocumentType(reportDocumentMainDO.getReportDocumentTypeId()); + String customConfig = typeDO.getCustomConfig(); String defaultConclusion = ""; if(!ObjectUtils.isEmpty(customConfig)){ @@ -262,9 +265,15 @@ public class ReportDocumentMainServiceImpl implements ReportDocumentMainService, } @Override - public void updateCommonField(ReportDocumentMainDO reportDocumentMainDO) { + public void updateCommonField(ReportDocumentMainDO reportDocumentMainDO, ReportDocumentTypeDO typeDO) { if(reportDocumentMainDO == null) return; + String documentCode = reportDocumentMainDO.getDocumentCode(); + if(ObjectUtils.isEmpty(documentCode)){ + String codeRule = typeDO.getCodeRule(); + documentCode = sequenceUtil.genCode(codeRule); + reportDocumentMainDO.setDocumentCode(documentCode); + } if(reportDocumentMainDO.getCancelFlag() == null || reportDocumentMainDO.getCancelFlag().equals("-1")) reportDocumentMainDO.setCancelFlag("0"); } From 199dd7715e5b05e80dccc91207bc7e7f2708401b Mon Sep 17 00:00:00 2001 From: FCL Date: Thu, 12 Mar 2026 14:20:07 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:iwork=E7=94=A8=E5=8D=B0=E5=9B=9E?= =?UTF-8?q?=E4=BC=A0=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reportdoc/constant/ReportDocConstant.java | 8 +++ .../service/ReportDocumentAssistService.java | 54 +++++++++++++++---- .../ReportDocumentMainServiceImpl.java | 10 ++-- .../rpc/config/RpcConfiguration.java | 3 +- 4 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/constant/ReportDocConstant.java diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/constant/ReportDocConstant.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/constant/ReportDocConstant.java new file mode 100644 index 00000000..03eaaf54 --- /dev/null +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/constant/ReportDocConstant.java @@ -0,0 +1,8 @@ +package com.zt.plat.module.qms.business.reportdoc.constant; + +public class ReportDocConstant { + + public static final String REPORT_DOCUMENT_BUSINESS_FILE_SOURCE_QMS = "qms.reportdoc"; + public static final String REPORT_DOCUMENT_BUSINESS_FILE_SOURCE_IWORK = "iwork"; + +} diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java index 87592bbe..c5b485c0 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentAssistService.java @@ -9,9 +9,12 @@ import com.zt.plat.framework.common.pojo.CommonResult; import com.zt.plat.framework.common.util.object.BeanUtils; import com.zt.plat.framework.security.core.LoginUser; import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils; +import com.zt.plat.module.infra.api.businessfile.BusinessFileApi; +import com.zt.plat.module.infra.api.businessfile.dto.BusinessFileSaveReqDTO; import com.zt.plat.module.infra.api.file.FileApi; import com.zt.plat.module.infra.api.file.dto.FileCreateReqDTO; import com.zt.plat.module.infra.api.file.dto.FileRespDTO; +import com.zt.plat.module.qms.business.reportdoc.constant.ReportDocConstant; import com.zt.plat.module.qms.business.reportdoc.controller.vo.ReportDocumentFileSaveReqVO; import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentFileDO; import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentMainDO; @@ -28,6 +31,8 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.IOUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; import java.io.IOException; import java.io.InputStream; @@ -57,6 +62,7 @@ public class ReportDocumentAssistService { @Resource private ReportDocumentFileService reportDocumentFileService; @Resource private DataTemplateService dataTemplateService; @Resource private FileApi fileApi; + @Resource private BusinessFileApi businessFileApi; // private String sequenceKey = "QMS_REPORT_IWORK_CODE"; @@ -77,6 +83,8 @@ public class ReportDocumentAssistService { JSONObject extension = bpmFieldExtensions.getJSONObject(i); String fieldName = extension.getString("fieldName"); String stringValue = extension.getString("stringValue"); + if(ObjectUtils.isEmpty(stringValue)) + stringValue = ""; if(fieldName.equalsIgnoreCase("createiworkflow") && stringValue.equals("1")){ createIworkWorkflowFlag = true; break; @@ -95,10 +103,17 @@ public class ReportDocumentAssistService { LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); IWorkWorkflowCreateReqDTO dto = new IWorkWorkflowCreateReqDTO(); - dto.setOperatorUserId(String.valueOf(loginUser.getId())); - dto.setJbr(String.valueOf(loginUser.getId())); - dto.setYybm(String.valueOf(loginUser.getVisitDeptId())); - dto.setFb(String.valueOf(loginUser.getVisitCompanyId())); + + String operatorUserId = "455"; //iWork 操作人用户编号 + String jbr = "455"; //用印申请人 + String yybm = "1055"; //用印部门 + String fb = "170"; //用印单位 + + + dto.setOperatorUserId(operatorUserId); + dto.setJbr(jbr); + dto.setYybm(yybm); + dto.setFb(fb); dto.setSqsj(sdf.format(new Date())); dto.setYyqx("检测报告用印"); dto.setYysy("检测报告用印"); @@ -113,6 +128,7 @@ public class ReportDocumentAssistService { * 生成新版pdf文件 * 在reportDocumentFile创建新pdf文件 * */ + @Transactional(rollbackFor = Exception.class) public ReportDocumentFileDO generatePdf(ReportDocumentMainDO mainDO) throws IOException { String pageFlag = "1"; //分页处理 Long typeId = mainDO.getReportDocumentTypeId(); @@ -133,11 +149,20 @@ public class ReportDocumentAssistService { .execute(); log.info("html2pdf--end at {}", LocalDateTime.now()); InputStream inputStream = response.bodyStream(); // 关键:返回原始 InputStream - - //尝试从响应头中提取文件名 - String documentCode = mainDO.getDocumentCode(); - if(documentCode == null) documentCode = ""; - String filename = documentCode + "检测报告.pdf"; + String formDataStr = mainDO.getFormData(); + JSONObject formData = JSONObject.parseObject(formDataStr); + String entrustCode = ""; + String sampleCategory = ""; + String filename = "检测报告"; + if(!ObjectUtils.isEmpty(formData)){ + entrustCode = formData.getString("entrustCode"); + sampleCategory = formData.getString("sampleCategory"); + if(!ObjectUtils.isEmpty(entrustCode)) + filename = entrustCode; + if(!ObjectUtils.isEmpty(sampleCategory)) + filename = filename + "(" + sampleCategory + ")"; + } + filename += ".pdf"; byte[] fileBytes = IOUtils.toByteArray(inputStream); //上传到文件服务 @@ -151,6 +176,17 @@ public class ReportDocumentAssistService { throw new ServiceException(REPORT_DOCUMENT_FILE_NOT_EXISTS.getCode(), "通过文件服务创建附件失败: " + Optional.ofNullable(fileResult).map(CommonResult::getMsg).orElse("未知错误")); } FileRespDTO fileRespDTO = fileResult.getData(); + //创建businessFile + BusinessFileSaveReqDTO businessFileSaveReqDTO = BusinessFileSaveReqDTO.builder() + .businessId(mainDO.getId()) + .businessCode(mainDO.getDocumentCode()) + .fileName(filename) + .fileId(fileRespDTO.getId()) + .source(ReportDocConstant.REPORT_DOCUMENT_BUSINESS_FILE_SOURCE_QMS) + .status(1) + .build(); + businessFileApi.createBusinessFile(businessFileSaveReqDTO); + //写入ReportDocumentFile ReportDocumentFileSaveReqVO fileSaveReqVO = new ReportDocumentFileSaveReqVO(); fileSaveReqVO.setMainId(mainDO.getId()); diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java index 2b5818c7..81c2c5a7 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/business/reportdoc/service/ReportDocumentMainServiceImpl.java @@ -471,11 +471,15 @@ public class ReportDocumentMainServiceImpl implements ReportDocumentMainService, String firstActivityFlag = "0"; if(!fieldExtensions.isEmpty()){ for(int i = 0; i < fieldExtensions.size(); i++){ - JSONObject fieldExtension = fieldExtensions.getJSONObject(i); - if(fieldExtension.getString("fieldName").equalsIgnoreCase(QmsBpmConstant.BPM_LAST_ACTIVITY_FLAG)){ + JSONObject extension = fieldExtensions.getJSONObject(i); + String fieldName = extension.getString("fieldName"); + String stringValue = extension.getString("stringValue"); + if(ObjectUtils.isEmpty(stringValue)) + stringValue = ""; + if(fieldName.equalsIgnoreCase(QmsBpmConstant.BPM_LAST_ACTIVITY_FLAG) && stringValue.equals("1")){ lastActivityFlag = "1"; } - if(fieldExtension.getString("fieldName").equalsIgnoreCase(QmsBpmConstant.BPM_FIRST_ACTIVITY_FLAG)){ + if(fieldName.equalsIgnoreCase(QmsBpmConstant.BPM_FIRST_ACTIVITY_FLAG) && stringValue.equals("1")){ firstActivityFlag = "1"; } } diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/rpc/config/RpcConfiguration.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/rpc/config/RpcConfiguration.java index 85e35704..486a931a 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/rpc/config/RpcConfiguration.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/rpc/config/RpcConfiguration.java @@ -2,6 +2,7 @@ package com.zt.plat.module.qms.framework.rpc.config; import com.zt.plat.module.bpm.api.task.BpmProcessInstanceApi; import com.zt.plat.module.bpm.api.task.BpmTaskApi; +import com.zt.plat.module.infra.api.businessfile.BusinessFileApi; import com.zt.plat.module.infra.api.file.FileApi; import com.zt.plat.module.system.api.dept.DeptApi; import com.zt.plat.module.system.api.iwork.IWorkIntegrationApi; @@ -13,6 +14,6 @@ import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; @Configuration(value = "qmsRpcConfiguration", proxyBeanMethods = false) -@EnableFeignClients(clients = {FileApi.class, SequenceApi.class, AdminUserApi.class, DeptApi.class, BpmProcessInstanceApi.class, BpmTaskApi.class, PermissionApi.class, IWorkIntegrationApi.class}) +@EnableFeignClients(clients = {FileApi.class, BusinessFileApi.class, SequenceApi.class, AdminUserApi.class, DeptApi.class, BpmProcessInstanceApi.class, BpmTaskApi.class, PermissionApi.class, IWorkIntegrationApi.class}) public class RpcConfiguration { } From 4c28b21454eb9eb5be3187c22e03caa5fdd69fcd Mon Sep 17 00:00:00 2001 From: shusir <497819738@qq.com> Date: Thu, 12 Mar 2026 14:31:26 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=A4=84=E7=90=86=EF=BC=9Aself=E4=B8=BAtrue?= =?UTF-8?q?=E6=89=8D=E5=85=81=E8=AE=B8=E6=9F=A5=E8=AF=A2=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=EF=BC=8C=E9=83=A8=E9=97=A8id?= =?UTF-8?q?=E4=B8=8D=E7=A9=BA=E6=89=8D=E8=BF=9B=E8=A1=8C=E9=83=A8=E9=97=A8?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=9A=94=E7=A6=BB=EF=BC=88=E5=8F=AF=E7=9C=8B?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=9D=83=E9=99=90=E8=A1=A8=E8=BE=BE=E5=BC=8F?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qms/core/aspect/QmsPermissionAspect.java | 3 +- .../core/aspect/annotation/QmsPermission.java | 2 + .../QMSMultiDataPermissionHandler.java | 131 ++++++++++++++++-- .../QMSPermissionContextHolder.java | 14 +- .../dal/mapper/MaterialBatchMapper.java | 2 +- .../service/MaterialBatchServiceImpl.java | 31 +++-- 6 files changed, 155 insertions(+), 28 deletions(-) diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/QmsPermissionAspect.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/QmsPermissionAspect.java index 37c1bcab..cc876d80 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/QmsPermissionAspect.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/QmsPermissionAspect.java @@ -61,7 +61,8 @@ public class QmsPermissionAspect { QmsPermission annotation = getAnnotationByJoinPoint(joinPoint); if(annotation == null) return; - QMSPermissionContextHolder.setContext(true, annotation.deptDataRoleCodes(), annotation.moduleDataRoleCodes(), annotation.deptIdColumn(), annotation.userIdColumn(), annotation.custom()); + QMSPermissionContextHolder.setContext(true, annotation.deptDataRoleCodes(), annotation.moduleDataRoleCodes(), + annotation.deptIdColumn(), annotation.userIdColumn(), annotation.self(), annotation.custom()); } private QmsPermission getAnnotationByJoinPoint(JoinPoint joinPoint) { diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/annotation/QmsPermission.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/annotation/QmsPermission.java index 29379bc2..5ef381ca 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/annotation/QmsPermission.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/core/aspect/annotation/QmsPermission.java @@ -21,6 +21,8 @@ public @interface QmsPermission { String userIdColumn() default "CREATOR"; //人员id列 + boolean self() default false; //是否可查看自己创建的数据 + //todo 考虑支持模块自定义扩展。参数传入表达式,通过表达式计算权限 String custom() default ""; diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSMultiDataPermissionHandler.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSMultiDataPermissionHandler.java index 3cfc3d7b..c8fe6e7f 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSMultiDataPermissionHandler.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSMultiDataPermissionHandler.java @@ -3,7 +3,6 @@ package com.zt.plat.module.qms.framework.datapermission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler; import com.zt.plat.framework.common.biz.system.permission.PermissionCommonApi; import com.zt.plat.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO; @@ -15,11 +14,9 @@ import com.zt.plat.framework.security.core.LoginUser; import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils; //import com.zt.plat.module.qms.core.aspect.annotation.QmsPermission; import com.zt.plat.framework.tenant.core.context.DeptContextHolder; +import com.zt.plat.module.qms.core.aspect.annotation.QmsPermission; import lombok.extern.slf4j.Slf4j; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.LongValue; -import net.sf.jsqlparser.expression.NullValue; +import net.sf.jsqlparser.expression.*; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.conditional.OrExpression; import net.sf.jsqlparser.expression.operators.relational.*; @@ -31,6 +28,9 @@ import net.sf.jsqlparser.statement.select.SelectItem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -63,13 +63,21 @@ public class QMSMultiDataPermissionHandler implements MultiDataPermissionHandler @Override public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) { - log.error("QMSMultiDataPermissionHandler: Expression={}", where); + log.info("QMSMultiDataPermissionHandler - table={}, Expression={}, mappedStatementId={}", + table.getName(), where, mappedStatementId); + + // 判断是否应该对该表应用权限(只处理主表) + boolean applyPermission = shouldApplyPermission(table, mappedStatementId); + if (!applyPermission) { + return null; + } //获取注解 if(!QMSPermissionContextHolder.shouldExecute()) return null; try{ Expression expression = buildExpression(table, where); + log.info("QMSMultiDataPermissionHandler 权限表达式:{}", expression); return expression; }catch (Exception e){ log.error("QMSMultiDataPermissionHandler: Expression={}", where); @@ -79,6 +87,88 @@ public class QMSMultiDataPermissionHandler implements MultiDataPermissionHandler return EXPRESSION_NULL; } + /** + * 判断是否应该对当前表应用权限控制(只针对主表) + * 通过解析 mappedStatementId 找到对应的 Mapper 接口和实体类,然后判断当前表是否是主表 + * + */ + private boolean shouldApplyPermission(Table table, String mappedStatementId) { + try{ + // mappedStatementId 格式:com.zt.plat.module.qms.resource.material.dal.mapper.MaterialBatchMapper.selectPageWithPdtInfo + int lastDotIndex = mappedStatementId.lastIndexOf('.'); + if (lastDotIndex == -1) { + return true; + } + + String mapperClassName = mappedStatementId.substring(0, lastDotIndex); + Class mapperClass = Class.forName(mapperClassName); + // 获取方法上的@QmsPermission 注解 + Method[] methods = mapperClass.getMethods(); + boolean applyPermission = false; + for (Method method : methods) { + if (method.isAnnotationPresent(QmsPermission.class)) { + // 获取主表的表名(通过实体类) + String mainTableName = getMainTableName(mapperClass); + String currentTableName = MyBatisUtils.getTableName(table); + Alias tableAlias = table.getAlias(); + String aliasName = tableAlias != null ? tableAlias.getName() : null; + // 只处理主表,且别名为 t 的表(避免自关联或重复应用) + if (mainTableName != null && mainTableName.equalsIgnoreCase(currentTableName)) { + // 如果有别名,检查别名是否为 "t" + if (aliasName != null) { + applyPermission = "t".equals(aliasName); + } else { + applyPermission = true; + } + } + } + } + return applyPermission; + } catch (Exception e) { + log.warn("QMSMultiDataPermissionHandler 解析 mappedStatementId 失败:{}", mappedStatementId, e); + } + + return false; + } + + /** + * 获取主表的表名 + * 通过 Mapper 接口的泛型参数找到对应的实体类,然后从@TableName 注解中获取表名 + * + */ + private String getMainTableName(Class mapperClass) { + try{ + // 1. 获取泛型接口列表 + Type[] genericInterfaces = mapperClass.getGenericInterfaces(); + if (genericInterfaces.length == 0) return null; + // 2. 遍历泛型接口 + for (Type type : genericInterfaces) { + // 3. 检查是否是参数化类型 + if (!(type instanceof ParameterizedType parameterizedType)) continue; + // 4. 获取泛型参数数组 + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + if (actualTypeArguments.length == 0) continue; + // 5. 获取第一个泛型参数(实体类) + Type firstTypeArg = actualTypeArguments[0]; + if (!(firstTypeArg instanceof Class entityClass)) continue; + // 6. 检查是否有 @TableName 注解 + com.baomidou.mybatisplus.annotation.TableName tableNameAnnotation = + entityClass.getAnnotation(com.baomidou.mybatisplus.annotation.TableName.class); + + if (tableNameAnnotation == null) continue; + + // 7. 返回表名 + return tableNameAnnotation.value(); + } + // 8. 未找到符合条件的表名 + log.debug("[getMainTableName] {} 未找到带@TableName 的实体类", mapperClass.getSimpleName()); + return null; + + } catch (Exception e) { + log.warn("[getMainTableName] 获取主表名失败:{}", mapperClass.getName(), e); + return null; + } + } /* * 构建权限sql*/ private Expression buildExpression(Table table, Expression where) { @@ -92,6 +182,7 @@ public class QMSMultiDataPermissionHandler implements MultiDataPermissionHandler } String deptIdCol = QMSPermissionContextHolder.getDeptIdColumn(); //部门id列 String userIdCol = QMSPermissionContextHolder.getUserIdColumn(); //人员id列 + Boolean self = QMSPermissionContextHolder.getSelf(); String deptDataRoleCodes = QMSPermissionContextHolder.getDeptDataRoleCode(); //部门数据权限角色。具有该角色,然后按角色的权限属性判断。从而获得人员允许查看的部门数据 String moduleDataRoleCodes = QMSPermissionContextHolder.getModuleDataRoleCodes(); //模块数据权限角色。 String custom = QMSPermissionContextHolder.getCustom(); //todo 自定义权限 @@ -149,7 +240,11 @@ public class QMSMultiDataPermissionHandler implements MultiDataPermissionHandler // 情况三,拼接 Dept 和 Company User 的条件,最后组合 Expression deptExpression = buildDeptExpression(tableName, deptIdCol, tableAlias, effectiveDeptIds); - Expression userExpression = buildUserExpression(tableName, userIdCol, tableAlias, effectiveSelf, loginUser.getId()); + // 只有当 userIdCol 不为空且 self 为 true 时,才构建用户表达式 + Expression userExpression = null; + if (StrUtil.isNotEmpty(userIdCol) && Boolean.TRUE.equals(self)) { + userExpression = buildUserExpression(tableName, userIdCol, tableAlias, effectiveSelf, loginUser.getId()); + } if (deptExpression == null && userExpression == null) { // TODO:获得不到条件的时候,暂时不抛出异常,而是不返回数据 log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]", @@ -165,7 +260,7 @@ public class QMSMultiDataPermissionHandler implements MultiDataPermissionHandler return deptExpression; } // 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE (dept_id IN ? OR user_id = ?) - return new ParenthesedExpressionList(new OrExpression(deptExpression, userExpression)); + return new ParenthesedExpressionList<>(new OrExpression(deptExpression, userExpression)); } private Expression buildDeptExpression(String tableName, String columnName, Alias tableAlias, Set deptIds) { @@ -205,10 +300,26 @@ public class QMSMultiDataPermissionHandler implements MultiDataPermissionHandler if (CollUtil.isEmpty(deptIds)) { return null; } - // 拼接条件 + /*// 拼接条件 return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), // Parenthesis 的目的,是提供 (1,2,3) 的 () 左右括号 - new ParenthesedExpressionList(new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new)))); + new ParenthesedExpressionList( + new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new))));*/ + // 构建:(dept_id IS NULL OR dept_id IN (?, ?, ?)) + // 含义:部门 ID 为空的数据允许所有人查看,部门 ID 不为空的数据只允许指定部门查看 + Column column = MyBatisUtils.buildColumn(tableName, tableAlias, columnName); + + // 构建 IS NULL 条件(允许部门 ID 为空的数据) + IsNullExpression isNullExpr = new IsNullExpression(column); + + // 构建 IN 条件(限制部门 ID 不为空的数据) + InExpression inExpression = new InExpression(column, + new ParenthesedExpressionList<>( + new ExpressionList<>(CollectionUtils.convertList(deptIds, LongValue::new)))); + + // 组合:IS NULL OR IN (...) + OrExpression orExpression = new OrExpression(isNullExpr, inExpression); + return new ParenthesedExpressionList<>(orExpression); } private Expression buildUserExpression(String tableName, String columnName, Alias tableAlias, Boolean self, Long userId) { diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSPermissionContextHolder.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSPermissionContextHolder.java index 192bae82..ed663811 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSPermissionContextHolder.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/framework/datapermission/QMSPermissionContextHolder.java @@ -11,6 +11,7 @@ public class QMSPermissionContextHolder { private static final ThreadLocal moduleDataRoleCodes = new TransmittableThreadLocal<>(); //模块数据权限 private static final ThreadLocal deptIdColumn = new TransmittableThreadLocal<>(); //部门id列 private static final ThreadLocal userIdColumn = new TransmittableThreadLocal<>(); //人员id列 + private static final ThreadLocal self = new TransmittableThreadLocal<>(); private static final ThreadLocal custom = new TransmittableThreadLocal<>(); //人员id列 public static void setEnable(Boolean ignore) { @@ -21,12 +22,14 @@ public class QMSPermissionContextHolder { return Boolean.TRUE.equals(enable.get()); } - public static void setContext(boolean enable, String deptDataRoleCode, String moduleDataRoleCode, String deptIdColumn, String userIdColumn, String custom){ + public static void setContext(boolean enable, String deptDataRoleCode, String moduleDataRoleCode, + String deptIdColumn, String userIdColumn, Boolean self, String custom){ QMSPermissionContextHolder.setEnable(enable); QMSPermissionContextHolder.deptDataRoleCodes.set(deptDataRoleCode); QMSPermissionContextHolder.moduleDataRoleCodes.set(moduleDataRoleCode); QMSPermissionContextHolder.deptIdColumn.set(deptIdColumn); QMSPermissionContextHolder.userIdColumn.set(userIdColumn); + QMSPermissionContextHolder.self.set(self); QMSPermissionContextHolder.custom.set(custom); } @@ -62,6 +65,15 @@ public class QMSPermissionContextHolder { return userIdColumn.get(); } + // 新增 self 的 getter 和 setter + public static void setSelf(Boolean self) { + QMSPermissionContextHolder.self.set(self); + } + + public static Boolean getSelf() { + return self.get(); + } + public static void setCustom(String custom) { QMSPermissionContextHolder.custom.set(custom); } diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialBatchMapper.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialBatchMapper.java index 72b581d5..b215d9fb 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialBatchMapper.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/dal/mapper/MaterialBatchMapper.java @@ -48,7 +48,7 @@ public interface MaterialBatchMapper extends BaseMapperX { .orderByDesc(MaterialBatchDO::getId)); } - // @QmsPermission(deptDataRoleCodes = "ytjyDeptAndSub", moduleDataRoleCodes = "qms_material_manager") + @QmsPermission(moduleDataRoleCodes = "ytjyAdmin", deptIdColumn = "ASN_DEPT_ID") default PageResult selectPageWithPdtInfo(MaterialBatchPageReqVO reqVO, List pdtIds) { MPJLambdaWrapper wrapper = new MPJLambdaWrapperX() diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java index 376afb53..8a846903 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java @@ -392,21 +392,7 @@ public class MaterialBatchServiceImpl implements MaterialBatchService { pageResult = materialBatchMapper.selectPageWithPdtInfo(pageReqVO, List.of()); } - // 查全部 - if (StrUtil.isEmpty(pageReqVO.getDataType())) { - List respVOS = pageResult.getList(); - if (CollUtil.isNotEmpty(respVOS)) { - List batIds = respVOS.stream().map(MaterialBatchRespVO::getId).toList(); - List gongs = materialBatchMapper.selectList(Wrappers.lambdaQuery(MaterialBatchDO.class) - .in(MaterialBatchDO::getParentId, batIds)); - if (CollUtil.isNotEmpty(gongs)) { - List gongRespVOs = gongs.stream().map(gong -> BeanUtils.toBean(gong, MaterialBatchRespVO.class)).toList(); - respVOS.addAll(gongRespVOs); - pageResult.setList(respVOS); - } - } - } - + // 给批次设置顶级分类的json配置 if (StrUtil.isEmpty(pageReqVO.getDataType()) || MaterialBatchGongType.batch.name().equals(pageReqVO.getDataType())) { List batches = pageResult.getList(); if (CollUtil.isNotEmpty(batches)) { @@ -428,6 +414,21 @@ public class MaterialBatchServiceImpl implements MaterialBatchService { } } + // 查全部 + if (StrUtil.isEmpty(pageReqVO.getDataType())) { + List respVOS = pageResult.getList(); + if (CollUtil.isNotEmpty(respVOS)) { + List batIds = respVOS.stream().map(MaterialBatchRespVO::getId).toList(); + List gongs = materialBatchMapper.selectList(Wrappers.lambdaQuery(MaterialBatchDO.class) + .in(MaterialBatchDO::getParentId, batIds)); + if (CollUtil.isNotEmpty(gongs)) { + List gongRespVOs = gongs.stream().map(gong -> BeanUtils.toBean(gong, MaterialBatchRespVO.class)).toList(); + respVOS.addAll(gongRespVOs); + pageResult.setList(respVOS); + } + } + } + // 需要组装children if (!MaterialBatchGongType.gong.name().equals(pageReqVO.getDataType()) && pageReqVO.getChildren()) { List voList = pageResult.getList();