From 3bab9748db4d7e0661afaf365b3789966223145d Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 09:20:47 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=EF=BC=9A=E4=BD=BF=E7=94=A8=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=20starter=20=E7=9A=84=E6=96=B9=E5=BC=8F=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E9=9B=86=E6=88=90=20mzt-biz-log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 2 +- .../pom.xml | 7 ++++ .../YudaoOperateLogV2Configuration.java | 28 +++++++++++++++ .../operatelogv2/core/package-info.java | 1 + .../core}/service/ILogRecordServiceImpl.java | 31 ++++++++--------- .../core/vo/OperateLogV2PageReqVO.java | 20 +++++++++++ .../framework/operatelogv2/package-info.java | 1 + ...ot.autoconfigure.AutoConfiguration.imports | 3 +- .../module/crm/enums/LogRecordConstants.java | 1 - .../yudao-module-system-api/pom.xml | 20 ----------- .../system/api/logger/OperateLogApi.java | 21 ++++++++---- .../logger/dto/OperateLogV2CreateReqDTO.java} | 19 ++++++----- .../logger/dto/OperateLogV2PageReqDTO.java | 28 +++++++++++++++ .../api/logger/dto/OperateLogV2RespDTO.java | 27 ++++----------- .../system/api/logger/OperateLogApiImpl.java | 34 +++++++++++++------ .../convert/logger/OperateLogConvert.java | 8 +++++ .../dal/dataobject/logger/OperateLogV2DO.java | 7 ++-- .../dal/mysql/logger/OperateLogV2Mapper.java | 13 +++---- .../YudaoOperateLogV2Configuration.java | 16 --------- .../service/logger/OperateLogService.java | 17 ++++------ .../service/logger/OperateLogServiceImpl.java | 11 +++--- 21 files changed, 187 insertions(+), 128 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java rename {yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog => yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core}/service/ILogRecordServiceImpl.java (68%) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java rename yudao-module-system/{yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java => yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java} (80%) create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index da0c4e735..4c1e671a3 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -26,7 +26,7 @@ 3.5.4.1 3.5.4.1 4.2.0 - 1.4.7.2 + 1.4.8.1 3.25.0 8.1.3.62 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml index 5792b4cb4..51ea2e04f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml @@ -46,6 +46,13 @@ com.google.guava guava + + + + io.github.mouzt + bizlog-sdk + + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java new file mode 100644 index 000000000..fa907c8f6 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.operatelogv2.config; + +import cn.iocoder.yudao.framework.operatelogv2.core.service.ILogRecordServiceImpl; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import com.mzt.logapi.service.ILogRecordService; +import com.mzt.logapi.starter.annotation.EnableLogRecord; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +/** + * mzt-biz-log 配置类 + * + * @author HUIHUI + */ +@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 +@AutoConfiguration +@Slf4j +public class YudaoOperateLogV2Configuration { + + @Bean + @Primary + public ILogRecordService iLogRecordServiceImpl(OperateLogApi operateLogApi) { + return new ILogRecordServiceImpl(operateLogApi); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java new file mode 100644 index 000000000..2cc0c2835 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelogv2.core; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java similarity index 68% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java rename to yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java index 07b25343e..903f5de72 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java @@ -1,38 +1,35 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.service; +package cn.iocoder.yudao.framework.operatelogv2.core.service; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.module.system.service.logger.OperateLogService; -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import com.mzt.logapi.beans.LogRecord; import com.mzt.logapi.service.ILogRecordService; -import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; -// TODO @puhui999:这个应该搞到 operatelog 组件里哈; /** * 操作日志 ILogRecordService 实现类 * - * 基于 {@link OperateLogService} 实现,记录操作日志 + * 基于 {@link OperateLogApi} 实现,记录操作日志 * * @author HUIHUI */ @Slf4j -@Service +@RequiredArgsConstructor public class ILogRecordServiceImpl implements ILogRecordService { - @Resource - private OperateLogService operateLogService; + private final OperateLogApi operateLogApi; @Override public void record(LogRecord logRecord) { - OperateLogV2CreateReqBO reqBO = new OperateLogV2CreateReqBO(); + OperateLogV2CreateReqDTO reqBO = new OperateLogV2CreateReqDTO(); // 补全通用字段 reqBO.setTraceId(TracerUtils.getTraceId()); // 补充用户信息 @@ -42,24 +39,24 @@ public class ILogRecordServiceImpl implements ILogRecordService { // 补全请求信息 fillRequestFields(reqBO); // 异步记录日志 - operateLogService.createOperateLogV2(reqBO); + operateLogApi.createOperateLogV2(reqBO); log.info("操作日志 ===> {}", reqBO); } - private static void fillUserFields(OperateLogV2CreateReqBO reqBO) { + private static void fillUserFields(OperateLogV2CreateReqDTO reqBO) { reqBO.setUserId(WebFrameworkUtils.getLoginUserId()); reqBO.setUserType(WebFrameworkUtils.getLoginUserType()); } - public static void fillModuleFields(OperateLogV2CreateReqBO reqBO, LogRecord logRecord) { - reqBO.setModule(logRecord.getType()); // 大模块类型如 crm-客户 - reqBO.setName(logRecord.getSubType());// 操作名称如 转移客户 + public static void fillModuleFields(OperateLogV2CreateReqDTO reqBO, LogRecord logRecord) { + reqBO.setType(logRecord.getType()); // 大模块类型如 crm-客户 + reqBO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} } - private static void fillRequestFields(OperateLogV2CreateReqBO reqBO) { + private static void fillRequestFields(OperateLogV2CreateReqDTO reqBO) { // 获得 Request 对象 HttpServletRequest request = ServletUtils.getRequest(); if (request == null) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java new file mode 100644 index 000000000..8d7a535ad --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.operatelogv2.core.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 操作日志分页 Request VO") +@Data +public class OperateLogV2PageReqVO extends PageParam { + + @Schema(description = "模块数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long bizId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long userId; + + @Schema(description = "模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String bizType; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java new file mode 100644 index 000000000..439ddc3de --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelogv2; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 04ccab1cd..3fb6d2cc9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ -cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration \ No newline at end of file +cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration +cn.iocoder.yudao.framework.operatelogv2.config.YudaoOperateLogV2Configuration \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index ae8c795ab..9435ec27d 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -22,6 +22,5 @@ public interface LogRecordConstants { //======================= 客户转移操作日志 ======================= String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; - String TRANSFER_CUSTOMER_LOG_FAIL = ""; // TODO @puhui999:这个可以删除哈,一般不搞失败的日志 } diff --git a/yudao-module-system/yudao-module-system-api/pom.xml b/yudao-module-system/yudao-module-system-api/pom.xml index 2a60b20b8..c98baf3dd 100644 --- a/yudao-module-system/yudao-module-system-api/pom.xml +++ b/yudao-module-system/yudao-module-system-api/pom.xml @@ -22,32 +22,12 @@ yudao-common - - - - - io.github.mouzt - bizlog-sdk - - - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - org.springframework.boot spring-boot-starter-validation true - diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java index ad42c87f7..509d3f0a1 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.module.system.api.logger; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import jakarta.validation.Valid; -import java.util.List; - /** * 操作日志 API 接口 * @@ -21,12 +22,18 @@ public interface OperateLogApi { void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); /** - * 获取指定模块的指定数据的操作日志 + * 创建操作日志 * - * @param module 操作模块 - * @param bizId 操作模块编号 - * @return 操作日志 + * @param createReqDTO 请求 */ - List getOperateLogByModuleAndBizId(String module, Long bizId); + void createOperateLogV2(@Valid OperateLogV2CreateReqDTO createReqDTO); + + /** + * 获取指定模块的指定数据的操作日志分页 + * + * @param pageReqVO 请求 + * @return 操作日志分页 + */ + PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java similarity index 80% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java index d6c44604c..8904bf072 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java @@ -1,7 +1,8 @@ -package cn.iocoder.yudao.module.system.service.logger.bo; +package cn.iocoder.yudao.module.system.api.logger.dto; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.Data; /** @@ -10,7 +11,7 @@ import lombok.Data; * @author HUIHUI */ @Data -public class OperateLogV2CreateReqBO { +public class OperateLogV2CreateReqDTO { /** * 链路追踪编号 @@ -23,29 +24,29 @@ public class OperateLogV2CreateReqBO { * * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 */ - @NotEmpty(message = "用户编号不能为空") + @NotNull(message = "用户编号不能为空") private Long userId; /** * 用户类型 * * 关联 {@link UserTypeEnum} */ - @NotEmpty(message = "用户类型不能为空") + @NotNull(message = "用户类型不能为空") private Integer userType; /** - * 操作模块 + * 操作模块类型 */ - @NotEmpty(message = "操作模块不能为空") - private String module; + @NotEmpty(message = "操作模块类型不能为空") + private String type; /** * 操作名 */ @NotEmpty(message = "操作名不能为空") - private String name; + private String subType; /** * 操作模块业务编号 */ - @NotEmpty(message = "操作模块业务编号不能为空") + @NotNull(message = "操作模块业务编号不能为空") private Long bizId; /** * 操作内容,记录整个操作的明细 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java new file mode 100644 index 000000000..aa54c3f5c --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.api.logger.dto; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import lombok.Data; + +/** + * 操作日志分页 Request DTO + * + * @author HUIHUI + */ +@Data +public class OperateLogV2PageReqDTO extends PageParam { + + /** + * 模块类型 + */ + private String bizType; + /** + * 模块数据编号 + */ + private Long bizId; + + /** + * 用户编号 + */ + private Long userId; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index a7670541d..2a3ca002c 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -1,14 +1,7 @@ package cn.iocoder.yudao.module.system.api.logger.dto; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; - /** * 系统操作日志 Resp DTO * @@ -25,6 +18,10 @@ public class OperateLogV2RespDTO { * 用户编号 */ private Long userId; + /** + * 用户名称 + */ + private String userName; /** * 用户类型 */ @@ -68,20 +65,8 @@ public class OperateLogV2RespDTO { private String userAgent; /** - * 创建时间 + * 创建时间, 直接返回字符串 */ - // TODO puhui999: 木得效果怎么肥事 - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private LocalDateTime createTime; - - // TODO @puhui999:下面 2 个字段不用返回;用 userId 哈;返回一个 userName - /** - * 创建者 - */ - private String creator; - /** - * 创建者名称 - */ - private String creatorName; + private String createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index d748bcc23..4e0ff0397 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -1,18 +1,22 @@ package cn.iocoder.yudao.module.system.api.logger; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; +import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import jakarta.annotation.Resource; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -39,21 +43,31 @@ public class OperateLogApiImpl implements OperateLogApi { } @Override - public List getOperateLogByModuleAndBizId(String module, Long bizId) { - List logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId); - if (CollUtil.isEmpty(logList)) { - return Collections.emptyList(); + @Async + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO) { + operateLogService.createOperateLogV2(createReqDTO); + } + + @Override + public PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { + PageResult operateLogPage = operateLogService.getOperateLogPage(pageReqVO); + if (CollUtil.isEmpty(operateLogPage.getList())) { + return PageResult.empty(); } // 获取用户 - List userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator()))); + List userList = adminUserService.getUserList(convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId)); + return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); + } + + private static List setUserInfo(List logList, List userList) { Map userMap = convertMap(userList, AdminUserDO::getId); return convertList(logList, item -> { - OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class); - findAndThen(userMap, Long.parseLong(item.getCreator()), user -> { - bean.setCreatorName(user.getNickname()); + OperateLogV2RespDTO respDTO = OperateLogConvert.INSTANCE.convert(item); + findAndThen(userMap, item.getUserId(), user -> { + respDTO.setUserName(user.getNickname()); }); - return bean; + return respDTO; }); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index 7b3aff8c0..eebbedc7d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -3,15 +3,20 @@ package cn.iocoder.yudao.module.system.convert.logger; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + @Mapper public interface OperateLogConvert { @@ -25,4 +30,7 @@ public interface OperateLogConvert { }); } + @Mapping(target = "createTime", source = "logV2DO.createTime", dateFormat = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + OperateLogV2RespDTO convert(OperateLogV2DO logV2DO); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java index 10035c8e9..56845b131 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -42,15 +42,14 @@ public class OperateLogV2DO extends BaseDO { * 关联 {@link UserTypeEnum} */ private Integer userType; - // TODO @puhui999:module 改成 type,name 改成 subType; /** - * 操作模块 + * 操作模块类型 */ - private String module; + private String type; /** * 操作名 */ - private String name; + private String subType; /** * 操作模块业务编号 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java index 362f0d2c4..0b2458106 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java @@ -3,28 +3,29 @@ package cn.iocoder.yudao.module.system.dal.mysql.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; -import java.util.List; @Mapper public interface OperateLogV2Mapper extends BaseMapperX { default PageResult selectPage(OperateLogPageReqVO reqVO, Collection userIds) { LambdaQueryWrapperX query = new LambdaQueryWrapperX() - .likeIfPresent(OperateLogV2DO::getModule, reqVO.getModule()) + .likeIfPresent(OperateLogV2DO::getType, reqVO.getModule()) .inIfPresent(OperateLogV2DO::getUserId, userIds); query.orderByDesc(OperateLogV2DO::getId); // 降序 return selectPage(reqVO, query); } - default List selectListByModuleAndBizId(String module, Long bizId) { - return selectList(new LambdaQueryWrapperX() - .eq(OperateLogV2DO::getModule, module) - .eq(OperateLogV2DO::getBizId, bizId) + default PageResult selectPage(OperateLogV2PageReqDTO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eqIfPresent(OperateLogV2DO::getType, pageReqVO.getBizType()) + .eqIfPresent(OperateLogV2DO::getBizId, pageReqVO.getBizId()) + .eqIfPresent(OperateLogV2DO::getUserId, pageReqVO.getUserId()) .orderByDesc(OperateLogV2DO::getCreateTime)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java deleted file mode 100644 index a5f3a9eaa..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.config; - -import com.mzt.logapi.starter.annotation.EnableLogRecord; -import org.springframework.context.annotation.Configuration; - -// TODO @puhui999:挪到 yudao-spring-boot-starter-biz-operatelog 下,搞个 cn.iocoder.yudao.framework.operatelogv2;跑通后,我们直接就删除老的实现了; -/** - * mzt-biz-log 配置类 - * - * @author HUIHUI - */ -@Configuration(proxyBeanMethods = false) -@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 -public class YudaoOperateLogV2Configuration { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java index 971685857..27ced45a0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java @@ -2,12 +2,11 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; - -import java.util.List; /** * 操作日志 Service 接口 @@ -38,16 +37,14 @@ public interface OperateLogService { * * @param createReqBO 创建请求 */ - void createOperateLogV2(OperateLogV2CreateReqBO createReqBO); + void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO); - // TODO @puhui999:module 改成 type /** - * 获取指定模块的指定数据的操作日志 + * 获得操作日志分页列表 * - * @param module 操作模块 - * @param bizId 操作模块编号 - * @return 操作日志 + * @param pageReqVO 分页条件 + * @return 操作日志分页列表 */ - List getOperateLogByModuleAndBizId(String module, Long bizId); + PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index 39c84ed33..f66e9a0ae 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -6,13 +6,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper; -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -20,7 +21,6 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.Collection; -import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; @@ -69,14 +69,15 @@ public class OperateLogServiceImpl implements OperateLogService { // ======================= LOG V2 ======================= @Override - public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) { + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); operateLogV2Mapper.insert(log); } + @Override - public List getOperateLogByModuleAndBizId(String module, Long bizId) { - return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId); + public PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { + return operateLogV2Mapper.selectPage(pageReqVO); } } From 3e91ac73c4fd1bcebe2c608675324d6cf2df5c5a Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 10:29:41 +0800 Subject: [PATCH 2/7] =?UTF-8?q?CRM=EF=BC=9A=E5=AE=8C=E5=96=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E6=9E=84=E9=80=A0=20CrmQueryWrapperUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../permission/CrmPermissionRoleCodeEnum.java | 27 +++++++ .../admin/customer/CrmCustomerController.http | 4 +- .../admin/customer/CrmCustomerController.java | 22 +++--- .../dal/mysql/business/CrmBusinessMapper.java | 5 +- .../crm/dal/mysql/clue/CrmClueMapper.java | 5 +- .../dal/mysql/contact/CrmContactMapper.java | 5 +- .../dal/mysql/contract/CrmContractMapper.java | 5 +- .../dal/mysql/customer/CrmCustomerMapper.java | 5 +- .../mysql/receivable/CrmReceivableMapper.java | 5 +- .../receivable/CrmReceivablePlanMapper.java | 5 +- .../module/crm/util/CrmQueryWrapperUtils.java | 72 +++++++++---------- .../src/main/resources/application-local.yaml | 1 + .../src/main/resources/application.yaml | 12 +++- 13 files changed, 91 insertions(+), 82 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java new file mode 100644 index 000000000..c9a51057b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.enums.permission; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Crm 数据权限角色枚举 + * + * @author HUIHUI + */ +@Getter +@AllArgsConstructor +public enum CrmPermissionRoleCodeEnum { + + CRM_ADMIN("crm_admin", "CRM 管理员"); + + /** + * 角色标识 + */ + private String code; + /** + * 角色名称 + */ + private String name; + +} + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http index 6a5c6774c..9a6cb93a8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http @@ -1,8 +1,8 @@ ### 请求 /transfer PUT {{baseUrl}}/crm/customer/transfer -Content-Type: application/json +Content-Type: application/-id: {{adminTenentId}}json Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} +tenant { "id": 10, diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 0882ea72c..1a9b75ad2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelogv2.core.vo.OperateLogV2PageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -12,6 +14,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -135,23 +138,14 @@ public class CrmCustomerController { return success(true); } - // TODO @puhui999:operate-log-list 或者 operate-log-page 如果分页 - @GetMapping("/operate-log") + @GetMapping("/operate-log-page") @Operation(summary = "获得客户操作日志") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:customer:query')") - // TODO @puhui999:最好有读权限;方法名改成 getCustomerOperateLog - public CommonResult> getOperateLog(@RequestParam("id") Long id) { - // 1. 获取客户 - // TODO @puhui999:这个校验可以去掉哈; - CrmCustomerDO customer = customerService.getCustomer(id); - if (customer == null) { - return success(null); - } - - // 2. 获取操作日志 - // TODO @puhui999:操作日志,返回可能要分页哈; - return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id)); + public CommonResult> getCustomerOperateLog(OperateLogV2PageReqVO reqVO) { + reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 + reqVO.setBizType(CRM_CUSTOMER); + return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); } // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java index 6dfdf8fad..eb9d50a64 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -38,11 +38,8 @@ public interface CrmBusinessMapper extends BaseMapperX { default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmBusinessDO.class) .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index cd558dce4..2253e69f6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -30,11 +30,8 @@ public interface CrmClueMapper extends BaseMapperX { default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmClueDO.class) .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java index adc4ced87..1d387149c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java @@ -43,11 +43,8 @@ public interface CrmContactMapper extends BaseMapperX { default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmContactDO.class) .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index 60a5ab785..dfb3e6236 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -41,11 +41,8 @@ public interface CrmContractMapper extends BaseMapperX { default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 mpjLambdaWrapperX.selectAll(CrmContractDO.class) .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index b399ca7df..77304575c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -30,11 +30,8 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class) .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index fca4e30e2..a20da86a6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -39,11 +39,8 @@ public interface CrmReceivableMapper extends BaseMapperX { default PageResult selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmReceivableDO.class) .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index e22c920b9..ed578f1fd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -38,11 +38,8 @@ public interface CrmReceivablePlanMapper extends BaseMapperX selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmReceivablePlanDO.class) .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index 161bff845..cbe43e683 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -7,9 +7,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; import com.github.yulichang.wrapper.MPJLambdaWrapper; import java.util.Collection; @@ -33,46 +36,41 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 * @param sceneType 场景类型 * @param pool 公海 - * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) */ - // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少;是不是把 bizId 传入就好啦? - public static , S> boolean appendPermissionCondition(T query, Integer bizType, SFunction bizId, - Long userId, Integer sceneType, Boolean pool) { + public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId, + Long userId, Integer sceneType, Boolean pool) { + final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 + if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) - .eq(CrmPermissionDO::getBizId, bizId) + .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 .eq(CrmPermissionDO::getUserId, userId)); } // 2.1 场景一:我负责的数据 if (CrmSceneTypeEnum.isOwner(sceneType)) { - query.eq("owner_user_id", userId); + query.eq(ownerUserIdField, userId); } // 2.2 场景二:我参与的数据 if (CrmSceneTypeEnum.isInvolved(sceneType)) { - query.ne("owner_user_id", userId) - // TODO @puhui999:IN 是不是更合适哈; - .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel()) - .or() - .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel())); + query.ne(ownerUserIdField, userId) + .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel()); } // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { - // TODO @puhui999:要不如果没有下属,拼一个 owner_user_id in null,不返回结果就好啦; - List subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); + List subordinateUsers = SingletonManager.getAdminUserApi().getUserListBySubordinate(userId); if (CollUtil.isEmpty(subordinateUsers)) { - return false; + query.eq(ownerUserIdField, -1); // 不返回任何结果 + } else { + query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId)); } - query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); } // 3. 拼接公海的查询条件 if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 - query.isNull("owner_user_id"); + query.isNull(ownerUserIdField); } else { // 情况二:不是公海 - query.isNotNull("owner_user_id"); + query.isNotNull(ownerUserIdField); } - return true; } /** @@ -93,38 +91,38 @@ public class CrmQueryWrapperUtils { .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } - private static AdminUserApi getAdminUserApi() { - return AdminUserApiHolder.ADMIN_USER_API; - } - /** - * 校验用户是否是管理员 + * 校验用户是否是 CRM 管理员 * * @param userId 用户编号 * @return 是/否 */ private static boolean validateAdminUser(Long userId) { - // TODO 查询权限配置表用户的角色信息 - // TODO @puhui999:查询用户的角色;CRM_ADMIN("crm_admin", "CRM 管理员"), - //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); - //if (permissionConfig == null) { - // return false; - //} - //// 校验是否为管理员 - //if (permissionConfig.getIsAdmin()){ - // return true; - //} - return false; + return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } /** - * 静态内部类实现 AdminUserApi 单例获取 + * 静态内部类实现单例获取 * * @author HUIHUI */ - private static class AdminUserApiHolder { + private static class SingletonManager { private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); + + public static AdminUserApi getAdminUserApi() { + return ADMIN_USER_API; + } + + public static PermissionApi getPermissionApi() { + return PERMISSION_API; + } + + public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { + return MYBATIS_PLUS_JOIN_PROPERTIES; + } } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 900656ecf..3e2a7ed6a 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -188,6 +188,7 @@ logging: cn.iocoder.yudao.module.trade.dal.mysql: debug cn.iocoder.yudao.module.promotion.dal.mysql: debug cn.iocoder.yudao.module.statistics.dal.mysql: debug + cn.iocoder.yudao.module.crm.dal.mysql: debug debug: false diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 627028bdd..21b2d48c3 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -79,7 +79,17 @@ mybatis-plus: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 mybatis-plus-join: - banner: false # 关闭控制台的 Banner 打印 + #是否打印 mybatis plus join banner 默认true + banner: false + #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除 + sub-table-logic: true + #拦截器MappedStatement缓存(默认true) + ms-cache: true + #表别名(默认 t) + table-alias: t + #副表逻辑删除条件的位置,支持where、on + #默认ON (1.4.7.2及之前版本默认为where) + logic-del-type: on # Spring Data Redis 配置 spring: From 55a215da44481a9116bdae824d018dda45afaacd Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 10:43:45 +0800 Subject: [PATCH 3/7] =?UTF-8?q?CRM-=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=A1=A5=E5=85=A8=E7=AE=A1=E7=90=86=E5=91=98=E5=92=8C=E5=85=AC?= =?UTF-8?q?=E6=B5=B7=E7=9B=B8=E5=85=B3=E6=83=85=E5=86=B5=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../permission/CrmPermissionController.java | 6 +- .../crm/framework/core/package-info.java | 1 - .../core/annotations/CrmPermission.java | 2 +- .../core/aop/CrmPermissionAspect.java | 71 ++++++++++++++----- .../permission/core/package-info.java | 1 + .../framework/permission/package-info.java | 1 + .../business/CrmBusinessServiceImpl.java | 2 +- .../crm/service/clue/CrmClueServiceImpl.java | 2 +- .../contact/CrmContactServiceImpl.java | 2 +- .../CrmContactBusinessLinkServiceImpl.java | 2 +- .../contract/CrmContractServiceImpl.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 2 +- .../CrmReceivablePlanServiceImpl.java | 2 +- .../receivable/CrmReceivableServiceImpl.java | 2 +- 14 files changed, 67 insertions(+), 31 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{ => permission}/core/annotations/CrmPermission.java (93%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{ => permission}/core/aop/CrmPermissionAspect.java (68%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 32d4a1ab7..5dc3807f5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionR import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; @@ -21,12 +21,12 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java deleted file mode 100644 index 4a3e65722..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.crm.framework.core; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java similarity index 93% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java index f92371f2b..9ef6d4d02 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.core.annotations; +package cn.iocoder.yudao.module.crm.framework.permission.core.annotations; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java similarity index 68% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java index 3e1cf87b2..ddd44edff 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java @@ -1,32 +1,34 @@ -package cn.iocoder.yudao.module.crm.framework.core.aop; +package cn.iocoder.yudao.module.crm.framework.permission.core.aop; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; -import jakarta.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS; -// TODO 这个包,改成 permission,然后搞 config 和 core 包,这个类在 core 包里;目的是:framework 最好分类下 /** * Crm 数据权限校验 AOP 切面 * @@ -42,10 +44,6 @@ public class CrmPermissionAspect { @Before("@annotation(crmPermission)") public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { - // TODO 芋艿:临时,方便大家调试 - //if (true) { - // return; - //} // 获取相关属性值 Map expressionValues = parseExpressions(joinPoint, crmPermission); Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? @@ -53,16 +51,28 @@ public class CrmPermissionAspect { Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号 Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 - // TODO 如果是超级管理员则直接通过 - //if (superAdmin){ - // return; - //} - - // 1. 获取数据权限 - List bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); - if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在 - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType)); + // 1.1 如果是超级管理员则直接通过 + if (validateAdminUser(getUserId())) { + return; } + // 1.2 获取数据权限 + List bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); + if (CollUtil.isEmpty(bizPermissions)) { // 没有数据权限的情况 + // 公海数据如果没有团队成员大家也因该有读权限才对 + if (CrmPermissionLevelEnum.isRead(permissionLevel)) { + return; + } + + // 没有数据权限的情况下超出了读权限直接报错,避免后面校验空指针 + throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType)); + } else { // 有数据权限但是没有负责人的情况 + if (!anyMatch(bizPermissions, item -> CrmPermissionLevelEnum.isOwner(item.getLevel()))) { + if (CrmPermissionLevelEnum.isRead(permissionLevel)) { + return; + } + } + } + // 2.1 情况一:如果自己是负责人,则默认有所有权限 CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId())); if (userPermission != null) { @@ -110,4 +120,29 @@ public class CrmPermissionAspect { return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings); } + /** + * 校验用户是否是 CRM 管理员 + * + * @param userId 用户编号 + * @return 是/否 + */ + private static boolean validateAdminUser(Long userId) { + return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); + } + + /** + * 静态内部类实现单例获取 + * + * @author HUIHUI + */ + private static class SingletonManager { + + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + + public static PermissionApi getPermissionApi() { + return PERMISSION_API; + } + + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java new file mode 100644 index 000000000..d895fe969 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.permission.core; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java new file mode 100644 index 000000000..44f408016 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.permission; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index f2db01b83..5281084b9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 414a52d17..c3af9e414 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 50b1bd4be..5edf22a2e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java index 0a9512ffb..94de4d7be 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContact import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 6f2fc16ab..00d6c5e4c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import jakarta.annotation.Resource; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index e53dc1a46..a4ea82323 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index edfb6c70a..e6940e793 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 38bf5266e..6071c2615 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -18,7 +18,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; From 1fae341cae3ab3667757c2c766b3606fc78bf9e6 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 16:29:13 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YudaoOperateLogAutoConfiguration.java | 23 +- .../YudaoOperateLogV2Configuration.java | 11 +- .../core/aop/OperateLogV2Aspect.java | 325 ++++++++++++++++++ .../core/enums/OperateLogV2Constants.java | 34 ++ .../core/service/ILogRecordServiceImpl.java | 54 +-- .../admin/customer/CrmCustomerController.java | 4 +- .../crm/framework/bizlog/package-info.java | 1 - .../function/CrmIndustryParseFunction.java | 3 +- .../function/CrmLevelParseFunction.java | 2 +- .../function/CrmSourceParseFunction.java | 2 +- .../framework/operatelog/package-info.java | 1 + .../logger/dto/OperateLogV2CreateReqDTO.java | 39 ++- .../api/logger/dto/OperateLogV2RespDTO.java | 6 +- .../system/api/logger/OperateLogApiImpl.java | 3 +- .../convert/logger/OperateLogConvert.java | 8 - .../dal/dataobject/logger/OperateLogV2DO.java | 62 +++- .../dal/mysql/logger/OperateLogV2Mapper.java | 11 - .../system/framework/bizlog/package-info.java | 1 - .../function/AdminUserParseFunction.java | 2 +- .../function/AreaParseFunction.java | 2 +- .../framework/operatelog/package-info.java | 1 + .../service/logger/OperateLogServiceImpl.java | 2 + 22 files changed, 491 insertions(+), 106 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{bizlog => operatelog}/function/CrmIndustryParseFunction.java (89%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{bizlog => operatelog}/function/CrmLevelParseFunction.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{bizlog => operatelog}/function/CrmSourceParseFunction.java (94%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/{bizlog => operatelog}/function/AdminUserParseFunction.java (95%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/{bizlog => operatelog}/function/AreaParseFunction.java (92%) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java index 441ec6bbd..0f4f48eeb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -1,23 +1,18 @@ package cn.iocoder.yudao.framework.operatelog.config; -import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.context.annotation.Bean; @AutoConfiguration public class YudaoOperateLogAutoConfiguration { - @Bean - public OperateLogAspect operateLogAspect() { - return new OperateLogAspect(); - } - - @Bean - public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { - return new OperateLogFrameworkServiceImpl(operateLogApi); - } + //@Bean + //public OperateLogAspect operateLogAspect() { + // return new OperateLogAspect(); + //} + // + //@Bean + //public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { + // return new OperateLogFrameworkServiceImpl(operateLogApi); + //} } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java index fa907c8f6..a7aa3a379 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.operatelogv2.config; +import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; import cn.iocoder.yudao.framework.operatelogv2.core.service.ILogRecordServiceImpl; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import com.mzt.logapi.service.ILogRecordService; import com.mzt.logapi.starter.annotation.EnableLogRecord; import lombok.extern.slf4j.Slf4j; @@ -21,8 +21,13 @@ public class YudaoOperateLogV2Configuration { @Bean @Primary - public ILogRecordService iLogRecordServiceImpl(OperateLogApi operateLogApi) { - return new ILogRecordServiceImpl(operateLogApi); + public ILogRecordService iLogRecordServiceImpl() { + return new ILogRecordServiceImpl(); + } + + @Bean + public OperateLogV2Aspect operateLogV2Aspect() { + return new OperateLogV2Aspect(); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java new file mode 100644 index 000000000..2f11d96b5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -0,0 +1,325 @@ +package cn.iocoder.yudao.framework.operatelogv2.core.aop; + +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import com.google.common.collect.Maps; +import com.mzt.logapi.beans.LogRecord; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.multipart.MultipartFile; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.IntStream; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; +import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; + +/** + * 拦截使用 @Operation 注解 + * + * @author HUIHUI + */ +@Aspect +@Slf4j +public class OperateLogV2Aspect { + + /** + * 用于记录操作内容的上下文 + * + * @see OperateLogV2CreateReqDTO#getContent() + */ + private static final ThreadLocal CONTENT = new ThreadLocal<>(); + /** + * 用于记录拓展字段的上下文 + * + * @see OperateLogV2CreateReqDTO#getExtra() + */ + private static final ThreadLocal> EXTRA = new ThreadLocal<>(); + + @Resource + private OperateLogApi operateLogApi; + + @Around("@annotation(operation)") + public Object around(ProceedingJoinPoint joinPoint, Operation operation) throws Throwable { + RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); + if (requestMethod == RequestMethod.GET) { // 跳过 get 方法 + return joinPoint.proceed(); + } + + // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录 + Integer userType = WebFrameworkUtils.getLoginUserType(); + if (ObjUtil.notEqual(userType, UserTypeEnum.ADMIN.getValue())) { + return joinPoint.proceed(); + } + + // 记录开始时间 + LocalDateTime startTime = LocalDateTime.now(); + try { + // 执行原有方法 + Object result = joinPoint.proceed(); + // 记录正常执行时的操作日志 + this.log(joinPoint, operation, startTime, result, null); + return result; + } catch (Throwable exception) { + this.log(joinPoint, operation, startTime, null, exception); + throw exception; + } finally { + clearThreadLocal(); + } + } + + public static void setContent(LogRecord content) { + CONTENT.set(content); + } + + public static void addExtra(String key, Object value) { + if (EXTRA.get() == null) { + EXTRA.set(new HashMap<>()); + } + EXTRA.get().put(key, value); + } + + public static void addExtra(Map extra) { + if (EXTRA.get() == null) { + EXTRA.set(new HashMap<>()); + } + EXTRA.get().putAll(extra); + } + + private static void clearThreadLocal() { + CONTENT.remove(); + EXTRA.remove(); + } + + private void log(ProceedingJoinPoint joinPoint, Operation operation, + LocalDateTime startTime, Object result, Throwable exception) { + try { + // 判断不记录的情况(默认没有值就是记录) + if (EXTRA.get() != null && EXTRA.get().get(ENABLE) != null) { + return; + } + // 真正记录操作日志 + this.log0(joinPoint, operation, startTime, result, exception); + } catch (Throwable ex) { + log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) apiOperation({}) result({}) exception({}) ]", + joinPoint, operation, result, exception, ex); + } + } + + private void log0(ProceedingJoinPoint joinPoint, Operation operation, + LocalDateTime startTime, Object result, Throwable exception) { + OperateLogV2CreateReqDTO reqDTO = new OperateLogV2CreateReqDTO(); + // 补全通用字段 + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setStartTime(startTime); + // 补充用户信息 + fillUserFields(reqDTO); + // 补全模块信息 + fillModuleFields(reqDTO, joinPoint, operation); + // 补全请求信息 + fillRequestFields(reqDTO); + // 补全方法信息 + fillMethodFields(reqDTO, joinPoint, startTime, result, exception); + + // 异步记录日志 + operateLogApi.createOperateLogV2(reqDTO); + } + + private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { + reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); + reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); + } + + private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, Operation operation) { + LogRecord logRecord = CONTENT.get(); + reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 + reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + if (EXTRA.get() != null) { + reqDTO.setExtra((Map) EXTRA.get().get(EXTRA_KEY)); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} + } + + // type 属性 + if (logRecord.getType() != null) { + reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 + } + if (StrUtil.isEmpty(reqDTO.getType())) { + Tag tag = getClassAnnotation(joinPoint, Tag.class); + if (tag != null) { + // 优先读取 @Tag 的 name 属性 + if (StrUtil.isNotEmpty(tag.name())) { + reqDTO.setType(tag.name()); + } + // 没有的话,读取 @API 的 description 属性 + if (StrUtil.isEmpty(reqDTO.getType()) && ArrayUtil.isNotEmpty(tag.description())) { + reqDTO.setType(tag.description()); + } + } + } + // subType 属性 + if (logRecord.getSubType() != null) { + reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 + } + if (StrUtil.isEmpty(reqDTO.getSubType()) && operation != null) { + reqDTO.setSubType(operation.summary()); + } + + } + + private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { + // 获得 Request 对象 + HttpServletRequest request = ServletUtils.getRequest(); + if (request == null) { + return; + } + // 补全请求信息 + reqDTO.setRequestMethod(request.getMethod()); + reqDTO.setRequestUrl(request.getRequestURI()); + reqDTO.setUserIp(ServletUtils.getClientIP(request)); + reqDTO.setUserAgent(ServletUtils.getUserAgent(request)); + } + + private static void fillMethodFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, LocalDateTime startTime, + Object result, Throwable exception) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + reqDTO.setJavaMethod(methodSignature.toString()); + if (EXTRA.get().get(IS_LOG_ARGS) == null) { + reqDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); + } + if (EXTRA.get().get(IS_LOG_RESULT_DATA) == null) { + reqDTO.setResultData(obtainResultData(result)); + } + reqDTO.setDuration((int) (LocalDateTimeUtil.between(startTime, LocalDateTime.now()).toMillis())); + // (正常)处理 resultCode 和 resultMsg 字段 + if (result instanceof CommonResult) { + CommonResult commonResult = (CommonResult) result; + reqDTO.setResultCode(commonResult.getCode()); + reqDTO.setResultMsg(commonResult.getMsg()); + } else { + reqDTO.setResultCode(SUCCESS.getCode()); + } + // (异常)处理 resultCode 和 resultMsg 字段 + if (exception != null) { + reqDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); + reqDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); + } + } + + @SuppressWarnings("SameParameterValue") + private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { + return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); + } + + private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { + // TODO 提升:参数脱敏和忽略 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + String[] argNames = methodSignature.getParameterNames(); + Object[] argValues = joinPoint.getArgs(); + // 拼接参数 + Map args = Maps.newHashMapWithExpectedSize(argValues.length); + for (int i = 0; i < argNames.length; i++) { + String argName = argNames[i]; + Object argValue = argValues[i]; + // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 + args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); + } + return JsonUtils.toJsonString(args); + } + + private static String obtainResultData(Object result) { + // TODO 提升:结果脱敏和忽略 + if (result instanceof CommonResult) { + result = ((CommonResult) result).getData(); + } + return JsonUtils.toJsonString(result); + } + + private static boolean isIgnoreArgs(Object object) { + Class clazz = object.getClass(); + // 处理数组的情况 + if (clazz.isArray()) { + return IntStream.range(0, Array.getLength(object)) + .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); + } + // 递归,处理数组、Collection、Map 的情况 + if (Collection.class.isAssignableFrom(clazz)) { + return ((Collection) object).stream() + .anyMatch((Predicate) OperateLogV2Aspect::isIgnoreArgs); + } + if (Map.class.isAssignableFrom(clazz)) { + return isIgnoreArgs(((Map) object).values()); + } + // obj + return object instanceof MultipartFile + || object instanceof HttpServletRequest + || object instanceof HttpServletResponse + || object instanceof BindingResult; + } + + private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + // 优先,匹配最优的 POST、PUT、DELETE + RequestMethod result = obtainFirstLogRequestMethod(requestMethods); + if (result != null) { + return result; + } + // 然后,匹配次优的 GET + result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) + .findFirst().orElse(null); + if (result != null) { + return result; + } + // 兜底,获得第一个 + return requestMethods[0]; + } + + private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { + RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 + ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); + return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; + } + + private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + return Arrays.stream(requestMethods).filter(requestMethod -> + requestMethod == RequestMethod.POST + || requestMethod == RequestMethod.PUT + || requestMethod == RequestMethod.DELETE) + .findFirst().orElse(null); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java new file mode 100644 index 000000000..b0cfe43b3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.operatelogv2.core.enums; + +/** + * 操作日志常量接口 + * + * @author HUIHUI + */ +public interface OperateLogV2Constants { + + // ========== 开关字段-如果没有值默认就是记录 ========== + + /** + * 是否记录日志 + */ + String ENABLE = "enable"; + + /** + * 是否记录方法参数 + */ + String IS_LOG_ARGS = "isLogArgs"; + + /** + * 是否记录方法结果的数据 + */ + String IS_LOG_RESULT_DATA = "isLogResultData"; + + // ========== 扩展 ========== + + /** + * 扩展信息 + */ + String EXTRA_KEY = "extra"; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java index 903f5de72..b54e0b4f1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java @@ -1,14 +1,9 @@ package cn.iocoder.yudao.framework.operatelogv2.core.service; -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; import com.mzt.logapi.beans.LogRecord; +import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.ILogRecordService; -import jakarta.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.util.Collections; @@ -17,56 +12,17 @@ import java.util.List; /** * 操作日志 ILogRecordService 实现类 * - * 基于 {@link OperateLogApi} 实现,记录操作日志 + * 基于 {@link OperateLogV2Aspect} 实现,记录操作日志 * * @author HUIHUI */ @Slf4j -@RequiredArgsConstructor public class ILogRecordServiceImpl implements ILogRecordService { - private final OperateLogApi operateLogApi; - @Override public void record(LogRecord logRecord) { - OperateLogV2CreateReqDTO reqBO = new OperateLogV2CreateReqDTO(); - // 补全通用字段 - reqBO.setTraceId(TracerUtils.getTraceId()); - // 补充用户信息 - fillUserFields(reqBO); - // 补全模块信息 - fillModuleFields(reqBO, logRecord); - // 补全请求信息 - fillRequestFields(reqBO); - // 异步记录日志 - operateLogApi.createOperateLogV2(reqBO); - log.info("操作日志 ===> {}", reqBO); - } - - private static void fillUserFields(OperateLogV2CreateReqDTO reqBO) { - reqBO.setUserId(WebFrameworkUtils.getLoginUserId()); - reqBO.setUserType(WebFrameworkUtils.getLoginUserType()); - } - - public static void fillModuleFields(OperateLogV2CreateReqDTO reqBO, LogRecord logRecord) { - reqBO.setType(logRecord.getType()); // 大模块类型如 crm-客户 - reqBO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 - reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 - reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 - reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} - } - - private static void fillRequestFields(OperateLogV2CreateReqDTO reqBO) { - // 获得 Request 对象 - HttpServletRequest request = ServletUtils.getRequest(); - if (request == null) { - return; - } - // 补全请求信息 - reqBO.setRequestMethod(request.getMethod()); - reqBO.setRequestUrl(request.getRequestURI()); - reqBO.setUserIp(ServletUtils.getClientIP(request)); - reqBO.setUserAgent(ServletUtils.getUserAgent(request)); + OperateLogV2Aspect.setContent(logRecord); // 操作日志 + OperateLogV2Aspect.addExtra(LogRecordContext.getVariables()); // 扩展信息 } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 1a9b75ad2..2580f9584 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -67,7 +67,7 @@ public class CrmCustomerController { } @PutMapping("/update") - //@Operation(summary = "更新客户") + @Operation(summary = "更新客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { customerService.updateCustomer(updateReqVO); @@ -131,7 +131,7 @@ public class CrmCustomerController { } @PutMapping("/transfer") - //@Operation(summary = "客户转移") + @Operation(summary = "客户转移") @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { customerService.transferCustomer(reqVO, getLoginUserId()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java deleted file mode 100644 index b756f540d..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java similarity index 89% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java index f963b533a..c2972a4b1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; @@ -8,7 +8,6 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; -// TODO @puhui999:包名使用 operatelog 更合适哈; /** * 自定义函数-通过行业编号获取行业信息 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java index 15af42d5e..25865d9b1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java index 0a630dfe6..9c1a62f5d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java new file mode 100644 index 000000000..975a2eb51 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.operatelog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java index 8904bf072..bab21a0dc 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java @@ -5,6 +5,9 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.time.LocalDateTime; +import java.util.Map; + /** * 系统操作日志 Create Req BO * @@ -58,7 +61,7 @@ public class OperateLogV2CreateReqDTO { * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) * 例如说,记录订单编号,{ orderId: "1"} */ - private String extra; + private Map extra; /** * 请求方法名 @@ -81,4 +84,38 @@ public class OperateLogV2CreateReqDTO { @NotEmpty(message = "浏览器 UA 不能为空") private String userAgent; + /** + * Java 方法名 + */ + private String javaMethod; + /** + * Java 方法的参数 + */ + private String javaMethodArgs; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + + /** + * 结果码 + */ + private Integer resultCode; + + /** + * 结果提示 + */ + private String resultMsg; + + /** + * 结果数据 + */ + private String resultData; + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index 2a3ca002c..cdeab0456 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.api.logger.dto; import lombok.Data; +import java.time.LocalDateTime; + /** * 系统操作日志 Resp DTO * @@ -65,8 +67,8 @@ public class OperateLogV2RespDTO { private String userAgent; /** - * 创建时间, 直接返回字符串 + * 创建时间 */ - private String createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index 4e0ff0397..ffe10b9c8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; -import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; @@ -63,7 +62,7 @@ public class OperateLogApiImpl implements OperateLogApi { private static List setUserInfo(List logList, List userList) { Map userMap = convertMap(userList, AdminUserDO::getId); return convertList(logList, item -> { - OperateLogV2RespDTO respDTO = OperateLogConvert.INSTANCE.convert(item); + OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); findAndThen(userMap, item.getUserId(), user -> { respDTO.setUserName(user.getNickname()); }); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index eebbedc7d..7b3aff8c0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -3,20 +3,15 @@ package cn.iocoder.yudao.module.system.convert.logger; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; -import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - @Mapper public interface OperateLogConvert { @@ -30,7 +25,4 @@ public interface OperateLogConvert { }); } - @Mapping(target = "createTime", source = "logV2DO.createTime", dateFormat = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - OperateLogV2RespDTO convert(OperateLogV2DO logV2DO); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java index 56845b131..656331c52 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -1,13 +1,19 @@ package cn.iocoder.yudao.module.system.dal.dataobject.logger; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; +import java.time.LocalDateTime; +import java.util.Map; + /** * 操作日志表 V2 * @@ -19,6 +25,16 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class OperateLogV2DO extends BaseDO { + /** + * {@link #javaMethodArgs} 的最大长度 + */ + public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 8000; + + /** + * {@link #resultData} 的最大长度 + */ + public static final Integer RESULT_MAX_LENGTH = 4000; + /** * 日志主键 */ @@ -65,8 +81,8 @@ public class OperateLogV2DO extends BaseDO { * * 例如说,记录订单编号,{ orderId: "1"} */ - // TODO @puhui999:看看能不能类似 exts 搞 json 格式; - private String extra; + @TableField(typeHandler = JacksonTypeHandler.class) + private Map extra; /** * 请求方法名 */ @@ -84,9 +100,43 @@ public class OperateLogV2DO extends BaseDO { */ private String userAgent; - // TODO @芋艿:requestUrl、requestMethod - // TODO @芋艿:javaMethod、javaMethodArgs - // TODO @芋艿:startTime、duration - // TODO @芋艿:resultMsg、resultData + /** + * Java 方法名 + */ + private String javaMethod; + /** + * Java 方法的参数 + * + * 实际格式为 Map + * 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败 + * 其中,key 为参数名,value 为参数值 + */ + private String javaMethodArgs; + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + /** + * 结果码 + * + * 目前使用的 {@link CommonResult#getCode()} 属性 + */ + private Integer resultCode; + /** + * 结果提示 + * + * 目前使用的 {@link CommonResult#getMsg()} 属性 + */ + private String resultMsg; + /** + * 结果数据 + * + * 如果是对象,则使用 JSON 格式化 + */ + private String resultData; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java index 0b2458106..acf14478f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java @@ -4,23 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import org.apache.ibatis.annotations.Mapper; -import java.util.Collection; - @Mapper public interface OperateLogV2Mapper extends BaseMapperX { - default PageResult selectPage(OperateLogPageReqVO reqVO, Collection userIds) { - LambdaQueryWrapperX query = new LambdaQueryWrapperX() - .likeIfPresent(OperateLogV2DO::getType, reqVO.getModule()) - .inIfPresent(OperateLogV2DO::getUserId, userIds); - query.orderByDesc(OperateLogV2DO::getId); // 降序 - return selectPage(reqVO, query); - } - default PageResult selectPage(OperateLogV2PageReqDTO pageReqVO) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eqIfPresent(OperateLogV2DO::getType, pageReqVO.getBizType()) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java deleted file mode 100644 index c96f3a0c1..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.system.framework.bizlog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java similarity index 95% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java index a88073d4e..2e7d6498a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.function; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java similarity index 92% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java index f486a49fa..e6815a742 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java new file mode 100644 index 000000000..978444e17 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.system.framework.operatelog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index f66e9a0ae..76532af87 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -71,6 +71,8 @@ public class OperateLogServiceImpl implements OperateLogService { @Override public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); + log.setJavaMethodArgs(StrUtils.maxLength(log.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); + log.setResultData(StrUtils.maxLength(log.getResultData(), RESULT_MAX_LENGTH)); operateLogV2Mapper.insert(log); } From f56d8a2751e61c2436f774083962f53c05b0363b Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 18:34:51 +0800 Subject: [PATCH 5/7] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/aop/OperateLogV2Aspect.java | 42 +++++++++--------- .../CrmIndustryParseFunction.java | 2 +- .../CrmLevelParseFunction.java | 2 +- .../CrmSourceParseFunction.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 30 ++++++------- .../permission/CrmPermissionServiceImpl.java | 1 - .../api/logger/dto/OperateLogV2RespDTO.java | 43 +++++++++++++++++-- .../AdminUserParseFunction.java | 2 +- .../AreaParseFunction.java | 2 +- 9 files changed, 78 insertions(+), 48 deletions(-) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{function => parse}/CrmIndustryParseFunction.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{function => parse}/CrmLevelParseFunction.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{function => parse}/CrmSourceParseFunction.java (94%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/{function => parse}/AdminUserParseFunction.java (95%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/{function => parse}/AreaParseFunction.java (92%) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java index 2f11d96b5..99d33dc71 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import com.google.common.collect.Maps; import com.mzt.logapi.beans.LogRecord; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -46,7 +45,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; /** - * 拦截使用 @Operation 注解 + * 拦截使用 @Operation 注解, 获取操作类型、开始时间、持续时间、方法相关信息、执行结果等信息 + * 对 mzt-biz-log 日志信息进行增强 * * @author HUIHUI */ @@ -165,27 +165,9 @@ public class OperateLogV2Aspect { LogRecord logRecord = CONTENT.get(); reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 - if (EXTRA.get() != null) { - reqDTO.setExtra((Map) EXTRA.get().get(EXTRA_KEY)); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} - } // type 属性 - if (logRecord.getType() != null) { - reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 - } - if (StrUtil.isEmpty(reqDTO.getType())) { - Tag tag = getClassAnnotation(joinPoint, Tag.class); - if (tag != null) { - // 优先读取 @Tag 的 name 属性 - if (StrUtil.isNotEmpty(tag.name())) { - reqDTO.setType(tag.name()); - } - // 没有的话,读取 @API 的 description 属性 - if (StrUtil.isEmpty(reqDTO.getType()) && ArrayUtil.isNotEmpty(tag.description())) { - reqDTO.setType(tag.description()); - } - } - } + reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 // subType 属性 if (logRecord.getSubType() != null) { reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 @@ -194,6 +176,24 @@ public class OperateLogV2Aspect { reqDTO.setSubType(operation.summary()); } + // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} + Map objectMap = EXTRA.get(); + if (objectMap != null) { + Object object = objectMap.get(EXTRA_KEY); + if (object instanceof Map extraMap) { + if (extraMap.keySet().stream().allMatch(String.class::isInstance)) { + @SuppressWarnings("unchecked") + Map extra = (Map) extraMap; + reqDTO.setExtra(extra); + return; + } + } + // 激进一点不是 map 直接当 value 处理 + Map extra = Maps.newHashMapWithExpectedSize(1); + extra.put(EXTRA_KEY, object); + reqDTO.setExtra(extra); + } + } private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java index c2972a4b1..45c98918b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java index 25865d9b1..bb0e23205 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java index 9c1a62f5d..eeb5a5674 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index a4ea82323..d20512917 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; @@ -65,17 +66,21 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); - // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); // 更新 CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); customerMapper.updateById(updateObj); + + // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); + HashMap extra = new HashMap<>(); + extra.put("tips", "随便记录一点啦"); + LogRecordContext.putVariable(OperateLogV2Constants.EXTRA_KEY, extra); } @Override @@ -125,27 +130,17 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { */ @Override public void validateCustomer(Long customerId) { - // 校验客户是否存在 - if (customerId == null) { - throw exception(CUSTOMER_NOT_EXISTS); - } - CrmCustomerDO customer = customerMapper.selectById(customerId); - if (Objects.isNull(customer)) { - throw exception(CUSTOMER_NOT_EXISTS); - } + validateCustomerExists(customerId); } @Override @Transactional(rollbackFor = Exception.class) - // TODO @puhui999:@LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) - @LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}") + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 - validateCustomer(reqVO.getId()); - // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 - // TODO @puhui999:customer 不用查询,从 1. 拿到哈;然后 put这个动作,可以放到 3.;这样逻辑结构就是,校验、逻辑、日志,更加清晰 - LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); + CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId()); + // 2.1 数据权限转移 crmPermissionService.transferPermission( CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); @@ -153,6 +148,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); // 3. TODO 记录转移日志 + LogRecordContext.putVariable("crmCustomer", customerDO); } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 14fb966c5..a686ffc6a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -138,7 +138,6 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { } @Override - @Transactional(rollbackFor = Exception.class) // TODO @puhui999:这里不用加的,就一个操作哈; public void deletePermission(Integer bizType, Long bizId) { int deletedCount = crmPermissionMapper.deletePermission(bizType, bizId); if (deletedCount == 0) { diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index cdeab0456..17dfeb491 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.api.logger.dto; import lombok.Data; import java.time.LocalDateTime; +import java.util.Map; /** * 系统操作日志 Resp DTO @@ -29,13 +30,13 @@ public class OperateLogV2RespDTO { */ private Integer userType; /** - * 操作模块 + * 操作模块类型 */ - private String module; + private String type; /** * 操作名 */ - private String name; + private String subType; /** * 操作模块业务编号 */ @@ -47,7 +48,7 @@ public class OperateLogV2RespDTO { /** * 拓展字段 */ - private String extra; + private Map extra; /** * 请求方法名 @@ -66,6 +67,40 @@ public class OperateLogV2RespDTO { */ private String userAgent; + /** + * Java 方法名 + */ + private String javaMethod; + /** + * Java 方法的参数 + */ + private String javaMethodArgs; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + + /** + * 结果码 + */ + private Integer resultCode; + + /** + * 结果提示 + */ + private String resultMsg; + + /** + * 结果数据 + */ + private String resultData; + /** * 创建时间 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java similarity index 95% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java index 2e7d6498a..5685dda75 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.operatelog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.parse; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java similarity index 92% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java index e6815a742..b63083a38 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.operatelog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; From e8ade5f1fe36f1a7102822b5ed3e7b2444711174 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 23 Dec 2023 20:10:40 +0800 Subject: [PATCH 6/7] =?UTF-8?q?crm=EF=BC=9A=E5=AE=8C=E5=96=84=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E9=81=97=E7=95=99=E7=9A=84=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/aop/OperateLogV2Aspect.java | 8 +++- .../core/aop/CrmPermissionAspect.java | 31 +----------- .../core/util/CrmPermissionUtils.java | 48 +++++++++++++++++++ .../customer/CrmCustomerServiceImpl.java | 7 +++ .../permission/CrmPermissionServiceImpl.java | 4 +- .../module/crm/util/CrmQueryWrapperUtils.java | 22 ++------- 6 files changed, 68 insertions(+), 52 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java index 99d33dc71..a4129c37c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -129,6 +129,10 @@ public class OperateLogV2Aspect { if (EXTRA.get() != null && EXTRA.get().get(ENABLE) != null) { return; } + if (CONTENT.get() == null) { // 没有值说明没有日志需要记录 + return; + } + // 真正记录操作日志 this.log0(joinPoint, operation, startTime, result, exception); } catch (Throwable ex) { @@ -146,7 +150,7 @@ public class OperateLogV2Aspect { // 补充用户信息 fillUserFields(reqDTO); // 补全模块信息 - fillModuleFields(reqDTO, joinPoint, operation); + fillModuleFields(reqDTO, operation); // 补全请求信息 fillRequestFields(reqDTO); // 补全方法信息 @@ -161,7 +165,7 @@ public class OperateLogV2Aspect { reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); } - private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, Operation operation) { + private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, Operation operation) { LogRecord logRecord = CONTENT.get(); reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java index ddd44edff..40bae7b98 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java @@ -3,16 +3,14 @@ package cn.iocoder.yudao.module.crm.framework.permission.core.aop; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; @@ -52,7 +50,7 @@ public class CrmPermissionAspect { Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 // 1.1 如果是超级管理员则直接通过 - if (validateAdminUser(getUserId())) { + if (CrmPermissionUtils.validateAdminUser()) { return; } // 1.2 获取数据权限 @@ -120,29 +118,4 @@ public class CrmPermissionAspect { return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings); } - /** - * 校验用户是否是 CRM 管理员 - * - * @param userId 用户编号 - * @return 是/否 - */ - private static boolean validateAdminUser(Long userId) { - return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); - } - - /** - * 静态内部类实现单例获取 - * - * @author HUIHUI - */ - private static class SingletonManager { - - private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); - - public static PermissionApi getPermissionApi() { - return PERMISSION_API; - } - - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java new file mode 100644 index 000000000..80a1654a8 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.crm.framework.permission.core.util; + +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; + +/** + * 数据权限工具类 + * + * @author HUIHUI + */ +public class CrmPermissionUtils { + + /** + * 校验用户是否是 CRM 管理员 + * + * @return 是/否 + */ + public static boolean validateAdminUser() { + return SingletonManager.getPermissionApi().hasAnyRoles(getUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); + } + + /** + * 获得用户编号 + * + * @return 用户编号 + */ + private static Long getUserId() { + return WebFrameworkUtils.getLoginUserId(); + } + + /** + * 静态内部类实现单例获取 + * + * @author HUIHUI + */ + private static class SingletonManager { + + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + + public static PermissionApi getPermissionApi() { + return PERMISSION_API; + } + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index d20512917..5d8dd36b2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -53,6 +53,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#customerId}}", success = "创建了客户") public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { // 插入 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); @@ -61,6 +62,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 创建数据权限 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + + // 添加日志上下文所需 + LogRecordContext.putVariable("customerId", customer.getId()); return customer.getId(); } @@ -85,6 +89,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "删除了客户") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteCustomer(Long id) { // 校验存在 @@ -152,6 +157,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 validateCustomerExists(updateReqVO.getId()); @@ -165,6 +171,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "将客户放入了公海") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void putCustomerPool(Long id) { // 1. 校验存在 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index a686ffc6a..e3cc4a24b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -89,8 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); - // TODO 校验是否为超级管理员 || 1 - if (oldPermission == null || !isOwner(oldPermission.getLevel())) { + if (oldPermission == null || !isOwner(oldPermission.getLevel()) || !CrmPermissionUtils.validateAdminUser()) { throw exception(CRM_PERMISSION_DENIED, bizTypeName); } // 1.1 校验转移对象是否已经是该负责人 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index cbe43e683..0e1ba5471 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -7,8 +7,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; @@ -41,7 +40,7 @@ public class CrmQueryWrapperUtils { Long userId, Integer sceneType, Boolean pool) { final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 + if (ObjUtil.notEqual(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 .eq(CrmPermissionDO::getUserId, userId)); @@ -82,7 +81,7 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 */ public static > void appendPermissionCondition(T query, Integer bizType, Collection bizIds, Long userId) { - if (ObjUtil.equal(validateAdminUser(userId), Boolean.TRUE)) {// 管理员不需要数据权限 + if (ObjUtil.equal(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE)) {// 管理员不需要数据权限 return; } @@ -91,16 +90,6 @@ public class CrmQueryWrapperUtils { .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } - /** - * 校验用户是否是 CRM 管理员 - * - * @param userId 用户编号 - * @return 是/否 - */ - private static boolean validateAdminUser(Long userId) { - return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); - } - /** * 静态内部类实现单例获取 * @@ -109,17 +98,12 @@ public class CrmQueryWrapperUtils { private static class SingletonManager { private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); - private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); public static AdminUserApi getAdminUserApi() { return ADMIN_USER_API; } - public static PermissionApi getPermissionApi() { - return PERMISSION_API; - } - public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { return MYBATIS_PLUS_JOIN_PROPERTIES; } From 60e684c4556c7796032d14845d6db8b5971fcd34 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 24 Dec 2023 00:32:17 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E8=90=A5=E9=94=80=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=EF=BC=9A=E8=8E=B7=E5=8F=96=E5=95=86=E5=93=81=E8=BF=91=E6=9C=9F?= =?UTF-8?q?=E5=8F=82=E4=B8=8E=E7=9A=84=E6=AF=8F=E4=B8=AA=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=BB=A1=E5=87=8F=E9=80=81=E5=92=8C=E9=99=90?= =?UTF-8?q?=E6=97=B6=E6=8A=98=E6=89=A3=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/activity/AppActivityController.java | 147 +++++++++++++----- .../discount/DiscountActivityMapper.java | 18 ++- .../mysql/discount/DiscountProductMapper.java | 18 +++ .../mysql/reward/RewardActivityMapper.java | 31 ++++ .../discount/DiscountActivityService.java | 13 +- .../discount/DiscountActivityServiceImpl.java | 22 ++- .../service/reward/RewardActivityService.java | 13 +- .../reward/RewardActivityServiceImpl.java | 22 ++- 8 files changed, 238 insertions(+), 46 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java index 16233bef3..6c5cec14a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java @@ -7,26 +7,33 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; +import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 @RestController @@ -40,6 +47,10 @@ public class AppActivityController { private SeckillActivityService seckillActivityService; @Resource private BargainActivityService bargainActivityService; + @Resource + private DiscountActivityService discountActivityService; + @Resource + private RewardActivityService rewardActivityService; @GetMapping("/list-by-spu-id") @Operation(summary = "获得单个商品,近期参与的每个活动") @@ -64,45 +75,105 @@ public class AppActivityController { if (CollUtil.isEmpty(spuIds)) { return new ArrayList<>(); } + LocalDateTime now = LocalDateTime.now(); + // 获取开启的且开始的且没有结束的活动 List activityList = new ArrayList<>(); - - // 1. 拼团活动 - 获取开启的且开始的且没有结束的活动 - List combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(combinationActivities)) { - combinationActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); - } - - // 2. 秒杀活动 - 获取开启的且开始的且没有结束的活动 - List seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(seckillActivities)) { - seckillActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); - } - - // 3. 砍价活动 - 获取开启的且开始的且没有结束的活动 - List bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(bargainActivities)) { - bargainActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); - } - - // TODO 芋艿:满减送活动 - // TODO 芋艿:限时折扣活动 + // 1. 拼团活动 + getCombinationActivities(spuIds, now, activityList); + // 2. 秒杀活动 + getSeckillActivities(spuIds, now, activityList); + // 3. 砍价活动 + getBargainActivities(spuIds, now, activityList); + // 4. 限时折扣活动 + getDiscountActivities(spuIds, now, activityList); + // 5. 满减送活动 + getRewardActivities(spuIds, now, activityList); return activityList; } + private void getCombinationActivities(Collection spuIds, LocalDateTime now, List activityList) { + List combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isEmpty(combinationActivities)) { + return; + } + + combinationActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getSeckillActivities(Collection spuIds, LocalDateTime now, List activityList) { + List seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isEmpty(seckillActivities)) { + return; + } + + seckillActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getBargainActivities(Collection spuIds, LocalDateTime now, List activityList) { + List bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isNotEmpty(bargainActivities)) { + return; + } + + bargainActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getDiscountActivities(Collection spuIds, LocalDateTime now, List activityList) { + List discountActivities = discountActivityService.getDiscountActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isEmpty(discountActivities)) { + return; + } + + List products = discountActivityService.getDiscountProductsByActivityId( + convertSet(discountActivities, DiscountActivityDO::getId)); + Map productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); + discountActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getRewardActivities(Collection spuIds, LocalDateTime now, List activityList) { + List rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now); + if (CollUtil.isEmpty(rewardActivityList)) { + return; + } + + Map> spuIdAndActivityMap = spuIds.stream() + .collect(Collectors.toMap( + spuId -> spuId, + spuId -> rewardActivityList.stream() + .filter(activity -> activity.getProductSpuIds().contains(spuId)) + .max(Comparator.comparing(RewardActivityDO::getCreateTime)))); + for (Long supId : spuIdAndActivityMap.keySet()) { + if (spuIdAndActivityMap.get(supId).isEmpty()) { + continue; + } + + RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get(); + activityList.add(new AppActivityRespVO().setId(rewardActivityDO.getId()) + .setType(PromotionTypeEnum.REWARD_ACTIVITY.getType()).setName(rewardActivityDO.getName()) + .setSpuId(supId).setStartTime(rewardActivityDO.getStartTime()).setEndTime(rewardActivityDO.getEndTime())); + } + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java index 534ce627a..efd4e4d25 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java @@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; -import java.util.Set; /** * 限时折扣活动 Mapper @@ -27,4 +27,20 @@ public interface DiscountActivityMapper extends BaseMapperX .orderByDesc(DiscountActivityDO::getId)); } + /** + * 获取指定活动编号的活动列表且 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表 + * + * @param ids 活动编号 + * @param dateTime 指定日期 + * @return 活动列表 + */ + default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { + return selectList(new LambdaQueryWrapperX() + .in(DiscountActivityDO::getId, ids) + .lt(DiscountActivityDO::getStartTime, dateTime) + .gt(DiscountActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 + .orderByDesc(DiscountActivityDO::getCreateTime)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java index 10df2ce3a..5257b836d 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java @@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.discount; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; +import java.util.Map; /** * 限时折扣商城 Mapper @@ -30,4 +32,20 @@ public interface DiscountProductMapper extends BaseMapperX { // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 List getMatchDiscountProductList(@Param("skuIds") Collection skuIds); + + /** + * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 + * + * @param spuIds spu 编号 + * @param status 状态 + * @return 包含 spuId 和 activityId 的 map 对象列表 + */ + default List> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(Collection spuIds, Integer status) { + return selectMaps(new QueryWrapper() + .select("spu_id AS spuId, MAX(DISTINCT(activity_id)) AS activityId") + .in("spu_id", spuIds) + .eq("activity_status", status) + .groupBy("spu_id")); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java index 2ee879823..ca9e9668f 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java @@ -1,14 +1,19 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.reward; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 满减送活动 Mapper @@ -35,4 +40,30 @@ public interface RewardActivityMapper extends BaseMapperX { .eq(RewardActivityDO::getStatus, status)); } + default List selectListBySpuIdsAndStatus(Collection spuIds, Integer status) { + Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream() + .map(id -> StrUtil.format("FIND_IN_SET({}, product_spu_ids) ", id)) + .collect(Collectors.joining(" OR ")); + return selectList(new QueryWrapper() + .eq("status", status) + .apply(productScopeValuesFindInSetFunc.apply(spuIds))); + } + + /** + * 获取指定活动编号的活动列表且 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表 + * + * @param ids 活动编号 + * @param dateTime 指定日期 + * @return 活动列表 + */ + default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { + return selectList(new LambdaQueryWrapperX() + .in(RewardActivityDO::getId, ids) + .lt(RewardActivityDO::getStartTime, dateTime) + .gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 + .orderByDesc(RewardActivityDO::getCreateTime) + ); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index 05ad13eed..d754d0d9f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; - import jakarta.validation.Valid; + +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -89,4 +90,14 @@ public interface DiscountActivityService { */ List getDiscountProductsByActivityId(Collection activityIds); + /** + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 + * + * @param spuIds spu 编号 + * @param status 状态 + * @param dateTime 当前日期时间 + * @return 折扣活动列表 + */ + List getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java index b8b496fdb..f103cf553 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.discount; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; @@ -15,16 +16,20 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapp import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; /** @@ -109,7 +114,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { /** * 校验商品是否冲突 * - * @param id 编号 + * @param id 编号 * @param products 商品列表 */ private void validateDiscountActivityProductConflicts(Long id, List products) { @@ -184,4 +189,17 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { return discountProductMapper.selectList("activity_id", activityIds); } + @Override + public List getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) { + // 1. 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 + List> spuIdAndActivityIdMaps = discountProductMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); + if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { + return Collections.emptyList(); + } + + // 2. 查询活动详情 + return discountActivityMapper.selectListByIdsAndDateTimeLt( + convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java index 7176e980b..e2e225608 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; - import jakarta.validation.Valid; + +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -71,4 +72,14 @@ public interface RewardActivityService { */ List getMatchRewardActivityList(Collection spuIds); + /** + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 + * + * @param spuIds spu 编号 + * @param status 状态 + * @param dateTime 当前日期时间 + * @return 满减送活动列表 + */ + List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java index 723dda933..e896eab92 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java @@ -11,14 +11,17 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static java.util.Arrays.asList; @@ -100,10 +103,11 @@ public class RewardActivityServiceImpl implements RewardActivityService { } // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; + /** * 校验商品参加的活动是否冲突 * - * @param id 活动编号 + * @param id 活动编号 * @param spuIds 商品 SPU 编号数组 */ private void validateRewardActivitySpuConflicts(Long id, Collection spuIds) { @@ -125,7 +129,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { /** * 获得商品参加的满减送活动的数组 * - * @param spuIds 商品 SPU 编号数组 + * @param spuIds 商品 SPU 编号数组 * @param statuses 活动状态数组 * @return 商品参加的满减送活动的数组 */ @@ -163,4 +167,16 @@ public class RewardActivityServiceImpl implements RewardActivityService { return null; } + @Override + public List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) { + // 1. 查询出指定 spuId 的 spu 参加的活动 + List rewardActivityList = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, status); + if (CollUtil.isEmpty(rewardActivityList)) { + return Collections.emptyList(); + } + + // 2. 查询活动详情 + return rewardActivityMapper.selectListByIdsAndDateTimeLt(convertSet(rewardActivityList, RewardActivityDO::getId), dateTime); + } + }