Commit 82a25474f60be3a89186e53e4ee46ccd4b3e016d
Merge remote-tracking branch 'origin/develop' into develop
Showing
70 changed files
with
1135 additions
and
408 deletions
yudao-dependencies/pom.xml
| @@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
| 26 | <mybatis-plus.version>3.5.4.1</mybatis-plus.version> | 26 | <mybatis-plus.version>3.5.4.1</mybatis-plus.version> |
| 27 | <mybatis-plus-generator.version>3.5.4.1</mybatis-plus-generator.version> | 27 | <mybatis-plus-generator.version>3.5.4.1</mybatis-plus-generator.version> |
| 28 | <dynamic-datasource.version>4.2.0</dynamic-datasource.version> | 28 | <dynamic-datasource.version>4.2.0</dynamic-datasource.version> |
| 29 | - <mybatis-plus-join.version>1.4.7.2</mybatis-plus-join.version> | 29 | + <mybatis-plus-join.version>1.4.8.1</mybatis-plus-join.version> |
| 30 | <redisson.version>3.25.0</redisson.version> | 30 | <redisson.version>3.25.0</redisson.version> |
| 31 | <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version> | 31 | <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version> |
| 32 | <!-- 消息队列 --> | 32 | <!-- 消息队列 --> |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml
| @@ -46,6 +46,13 @@ | @@ -46,6 +46,13 @@ | ||
| 46 | <groupId>com.google.guava</groupId> | 46 | <groupId>com.google.guava</groupId> |
| 47 | <artifactId>guava</artifactId> | 47 | <artifactId>guava</artifactId> |
| 48 | </dependency> | 48 | </dependency> |
| 49 | + <!-- Springboot-注解-通用操作日志组件 --> | ||
| 50 | + <!-- 此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 --> | ||
| 51 | + <dependency> | ||
| 52 | + <groupId>io.github.mouzt</groupId> | ||
| 53 | + <artifactId>bizlog-sdk</artifactId> | ||
| 54 | + </dependency> | ||
| 55 | + | ||
| 49 | </dependencies> | 56 | </dependencies> |
| 50 | 57 | ||
| 51 | </project> | 58 | </project> |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java
| 1 | package cn.iocoder.yudao.framework.operatelog.config; | 1 | package cn.iocoder.yudao.framework.operatelog.config; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; | ||
| 4 | -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; | ||
| 5 | -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl; | ||
| 6 | -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | ||
| 7 | import org.springframework.boot.autoconfigure.AutoConfiguration; | 3 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 8 | -import org.springframework.context.annotation.Bean; | ||
| 9 | 4 | ||
| 10 | @AutoConfiguration | 5 | @AutoConfiguration |
| 11 | public class YudaoOperateLogAutoConfiguration { | 6 | public class YudaoOperateLogAutoConfiguration { |
| 12 | 7 | ||
| 13 | - @Bean | ||
| 14 | - public OperateLogAspect operateLogAspect() { | ||
| 15 | - return new OperateLogAspect(); | ||
| 16 | - } | ||
| 17 | - | ||
| 18 | - @Bean | ||
| 19 | - public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { | ||
| 20 | - return new OperateLogFrameworkServiceImpl(operateLogApi); | ||
| 21 | - } | 8 | + //@Bean |
| 9 | + //public OperateLogAspect operateLogAspect() { | ||
| 10 | + // return new OperateLogAspect(); | ||
| 11 | + //} | ||
| 12 | + // | ||
| 13 | + //@Bean | ||
| 14 | + //public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { | ||
| 15 | + // return new OperateLogFrameworkServiceImpl(operateLogApi); | ||
| 16 | + //} | ||
| 22 | 17 | ||
| 23 | } | 18 | } |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.operatelogv2.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; | ||
| 4 | +import cn.iocoder.yudao.framework.operatelogv2.core.service.ILogRecordServiceImpl; | ||
| 5 | +import com.mzt.logapi.service.ILogRecordService; | ||
| 6 | +import com.mzt.logapi.starter.annotation.EnableLogRecord; | ||
| 7 | +import lombok.extern.slf4j.Slf4j; | ||
| 8 | +import org.springframework.boot.autoconfigure.AutoConfiguration; | ||
| 9 | +import org.springframework.context.annotation.Bean; | ||
| 10 | +import org.springframework.context.annotation.Primary; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * mzt-biz-log 配置类 | ||
| 14 | + * | ||
| 15 | + * @author HUIHUI | ||
| 16 | + */ | ||
| 17 | +@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 | ||
| 18 | +@AutoConfiguration | ||
| 19 | +@Slf4j | ||
| 20 | +public class YudaoOperateLogV2Configuration { | ||
| 21 | + | ||
| 22 | + @Bean | ||
| 23 | + @Primary | ||
| 24 | + public ILogRecordService iLogRecordServiceImpl() { | ||
| 25 | + return new ILogRecordServiceImpl(); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + @Bean | ||
| 29 | + public OperateLogV2Aspect operateLogV2Aspect() { | ||
| 30 | + return new OperateLogV2Aspect(); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | +} |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.operatelogv2.core.aop; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.date.LocalDateTimeUtil; | ||
| 4 | +import cn.hutool.core.exceptions.ExceptionUtil; | ||
| 5 | +import cn.hutool.core.util.ArrayUtil; | ||
| 6 | +import cn.hutool.core.util.ObjUtil; | ||
| 7 | +import cn.hutool.core.util.StrUtil; | ||
| 8 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 10 | +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 11 | +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | ||
| 12 | +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | ||
| 13 | +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||
| 14 | +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | ||
| 15 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; | ||
| 16 | +import com.google.common.collect.Maps; | ||
| 17 | +import com.mzt.logapi.beans.LogRecord; | ||
| 18 | +import io.swagger.v3.oas.annotations.Operation; | ||
| 19 | +import jakarta.annotation.Resource; | ||
| 20 | +import jakarta.servlet.http.HttpServletRequest; | ||
| 21 | +import jakarta.servlet.http.HttpServletResponse; | ||
| 22 | +import lombok.extern.slf4j.Slf4j; | ||
| 23 | +import org.aspectj.lang.ProceedingJoinPoint; | ||
| 24 | +import org.aspectj.lang.annotation.Around; | ||
| 25 | +import org.aspectj.lang.annotation.Aspect; | ||
| 26 | +import org.aspectj.lang.reflect.MethodSignature; | ||
| 27 | +import org.springframework.core.annotation.AnnotationUtils; | ||
| 28 | +import org.springframework.validation.BindingResult; | ||
| 29 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 30 | +import org.springframework.web.bind.annotation.RequestMethod; | ||
| 31 | +import org.springframework.web.multipart.MultipartFile; | ||
| 32 | + | ||
| 33 | +import java.lang.annotation.Annotation; | ||
| 34 | +import java.lang.reflect.Array; | ||
| 35 | +import java.time.LocalDateTime; | ||
| 36 | +import java.util.Arrays; | ||
| 37 | +import java.util.Collection; | ||
| 38 | +import java.util.HashMap; | ||
| 39 | +import java.util.Map; | ||
| 40 | +import java.util.function.Predicate; | ||
| 41 | +import java.util.stream.IntStream; | ||
| 42 | + | ||
| 43 | +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; | ||
| 44 | +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; | ||
| 45 | +import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; | ||
| 46 | + | ||
| 47 | +/** | ||
| 48 | + * 拦截使用 @Operation 注解, 获取操作类型、开始时间、持续时间、方法相关信息、执行结果等信息 | ||
| 49 | + * 对 mzt-biz-log 日志信息进行增强 | ||
| 50 | + * | ||
| 51 | + * @author HUIHUI | ||
| 52 | + */ | ||
| 53 | +@Aspect | ||
| 54 | +@Slf4j | ||
| 55 | +public class OperateLogV2Aspect { | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * 用于记录操作内容的上下文 | ||
| 59 | + * | ||
| 60 | + * @see OperateLogV2CreateReqDTO#getContent() | ||
| 61 | + */ | ||
| 62 | + private static final ThreadLocal<LogRecord> CONTENT = new ThreadLocal<>(); | ||
| 63 | + /** | ||
| 64 | + * 用于记录拓展字段的上下文 | ||
| 65 | + * | ||
| 66 | + * @see OperateLogV2CreateReqDTO#getExtra() | ||
| 67 | + */ | ||
| 68 | + private static final ThreadLocal<Map<String, Object>> EXTRA = new ThreadLocal<>(); | ||
| 69 | + | ||
| 70 | + @Resource | ||
| 71 | + private OperateLogApi operateLogApi; | ||
| 72 | + | ||
| 73 | + @Around("@annotation(operation)") | ||
| 74 | + public Object around(ProceedingJoinPoint joinPoint, Operation operation) throws Throwable { | ||
| 75 | + RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); | ||
| 76 | + if (requestMethod == RequestMethod.GET) { // 跳过 get 方法 | ||
| 77 | + return joinPoint.proceed(); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录 | ||
| 81 | + Integer userType = WebFrameworkUtils.getLoginUserType(); | ||
| 82 | + if (ObjUtil.notEqual(userType, UserTypeEnum.ADMIN.getValue())) { | ||
| 83 | + return joinPoint.proceed(); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + // 记录开始时间 | ||
| 87 | + LocalDateTime startTime = LocalDateTime.now(); | ||
| 88 | + try { | ||
| 89 | + // 执行原有方法 | ||
| 90 | + Object result = joinPoint.proceed(); | ||
| 91 | + // 记录正常执行时的操作日志 | ||
| 92 | + this.log(joinPoint, operation, startTime, result, null); | ||
| 93 | + return result; | ||
| 94 | + } catch (Throwable exception) { | ||
| 95 | + this.log(joinPoint, operation, startTime, null, exception); | ||
| 96 | + throw exception; | ||
| 97 | + } finally { | ||
| 98 | + clearThreadLocal(); | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + public static void setContent(LogRecord content) { | ||
| 103 | + CONTENT.set(content); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + public static void addExtra(String key, Object value) { | ||
| 107 | + if (EXTRA.get() == null) { | ||
| 108 | + EXTRA.set(new HashMap<>()); | ||
| 109 | + } | ||
| 110 | + EXTRA.get().put(key, value); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + public static void addExtra(Map<String, Object> extra) { | ||
| 114 | + if (EXTRA.get() == null) { | ||
| 115 | + EXTRA.set(new HashMap<>()); | ||
| 116 | + } | ||
| 117 | + EXTRA.get().putAll(extra); | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + private static void clearThreadLocal() { | ||
| 121 | + CONTENT.remove(); | ||
| 122 | + EXTRA.remove(); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + private void log(ProceedingJoinPoint joinPoint, Operation operation, | ||
| 126 | + LocalDateTime startTime, Object result, Throwable exception) { | ||
| 127 | + try { | ||
| 128 | + // 判断不记录的情况(默认没有值就是记录) | ||
| 129 | + if (EXTRA.get() != null && EXTRA.get().get(ENABLE) != null) { | ||
| 130 | + return; | ||
| 131 | + } | ||
| 132 | + if (CONTENT.get() == null) { // 没有值说明没有日志需要记录 | ||
| 133 | + return; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // 真正记录操作日志 | ||
| 137 | + this.log0(joinPoint, operation, startTime, result, exception); | ||
| 138 | + } catch (Throwable ex) { | ||
| 139 | + log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) apiOperation({}) result({}) exception({}) ]", | ||
| 140 | + joinPoint, operation, result, exception, ex); | ||
| 141 | + } | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + private void log0(ProceedingJoinPoint joinPoint, Operation operation, | ||
| 145 | + LocalDateTime startTime, Object result, Throwable exception) { | ||
| 146 | + OperateLogV2CreateReqDTO reqDTO = new OperateLogV2CreateReqDTO(); | ||
| 147 | + // 补全通用字段 | ||
| 148 | + reqDTO.setTraceId(TracerUtils.getTraceId()); | ||
| 149 | + reqDTO.setStartTime(startTime); | ||
| 150 | + // 补充用户信息 | ||
| 151 | + fillUserFields(reqDTO); | ||
| 152 | + // 补全模块信息 | ||
| 153 | + fillModuleFields(reqDTO, operation); | ||
| 154 | + // 补全请求信息 | ||
| 155 | + fillRequestFields(reqDTO); | ||
| 156 | + // 补全方法信息 | ||
| 157 | + fillMethodFields(reqDTO, joinPoint, startTime, result, exception); | ||
| 158 | + | ||
| 159 | + // 异步记录日志 | ||
| 160 | + operateLogApi.createOperateLogV2(reqDTO); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { | ||
| 164 | + reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); | ||
| 165 | + reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); | ||
| 166 | + } | ||
| 167 | + | ||
| 168 | + private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, Operation operation) { | ||
| 169 | + LogRecord logRecord = CONTENT.get(); | ||
| 170 | + reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 | ||
| 171 | + reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 | ||
| 172 | + | ||
| 173 | + // type 属性 | ||
| 174 | + reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 | ||
| 175 | + // subType 属性 | ||
| 176 | + if (logRecord.getSubType() != null) { | ||
| 177 | + reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 | ||
| 178 | + } | ||
| 179 | + if (StrUtil.isEmpty(reqDTO.getSubType()) && operation != null) { | ||
| 180 | + reqDTO.setSubType(operation.summary()); | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} | ||
| 184 | + Map<String, Object> objectMap = EXTRA.get(); | ||
| 185 | + if (objectMap != null) { | ||
| 186 | + Object object = objectMap.get(EXTRA_KEY); | ||
| 187 | + if (object instanceof Map<?, ?> extraMap) { | ||
| 188 | + if (extraMap.keySet().stream().allMatch(String.class::isInstance)) { | ||
| 189 | + @SuppressWarnings("unchecked") | ||
| 190 | + Map<String, Object> extra = (Map<String, Object>) extraMap; | ||
| 191 | + reqDTO.setExtra(extra); | ||
| 192 | + return; | ||
| 193 | + } | ||
| 194 | + } | ||
| 195 | + // 激进一点不是 map 直接当 value 处理 | ||
| 196 | + Map<String, Object> extra = Maps.newHashMapWithExpectedSize(1); | ||
| 197 | + extra.put(EXTRA_KEY, object); | ||
| 198 | + reqDTO.setExtra(extra); | ||
| 199 | + } | ||
| 200 | + | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { | ||
| 204 | + // 获得 Request 对象 | ||
| 205 | + HttpServletRequest request = ServletUtils.getRequest(); | ||
| 206 | + if (request == null) { | ||
| 207 | + return; | ||
| 208 | + } | ||
| 209 | + // 补全请求信息 | ||
| 210 | + reqDTO.setRequestMethod(request.getMethod()); | ||
| 211 | + reqDTO.setRequestUrl(request.getRequestURI()); | ||
| 212 | + reqDTO.setUserIp(ServletUtils.getClientIP(request)); | ||
| 213 | + reqDTO.setUserAgent(ServletUtils.getUserAgent(request)); | ||
| 214 | + } | ||
| 215 | + | ||
| 216 | + private static void fillMethodFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, LocalDateTime startTime, | ||
| 217 | + Object result, Throwable exception) { | ||
| 218 | + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); | ||
| 219 | + reqDTO.setJavaMethod(methodSignature.toString()); | ||
| 220 | + if (EXTRA.get().get(IS_LOG_ARGS) == null) { | ||
| 221 | + reqDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); | ||
| 222 | + } | ||
| 223 | + if (EXTRA.get().get(IS_LOG_RESULT_DATA) == null) { | ||
| 224 | + reqDTO.setResultData(obtainResultData(result)); | ||
| 225 | + } | ||
| 226 | + reqDTO.setDuration((int) (LocalDateTimeUtil.between(startTime, LocalDateTime.now()).toMillis())); | ||
| 227 | + // (正常)处理 resultCode 和 resultMsg 字段 | ||
| 228 | + if (result instanceof CommonResult) { | ||
| 229 | + CommonResult<?> commonResult = (CommonResult<?>) result; | ||
| 230 | + reqDTO.setResultCode(commonResult.getCode()); | ||
| 231 | + reqDTO.setResultMsg(commonResult.getMsg()); | ||
| 232 | + } else { | ||
| 233 | + reqDTO.setResultCode(SUCCESS.getCode()); | ||
| 234 | + } | ||
| 235 | + // (异常)处理 resultCode 和 resultMsg 字段 | ||
| 236 | + if (exception != null) { | ||
| 237 | + reqDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); | ||
| 238 | + reqDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); | ||
| 239 | + } | ||
| 240 | + } | ||
| 241 | + | ||
| 242 | + @SuppressWarnings("SameParameterValue") | ||
| 243 | + private static <T extends Annotation> T getClassAnnotation(ProceedingJoinPoint joinPoint, Class<T> annotationClass) { | ||
| 244 | + return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { | ||
| 248 | + // TODO 提升:参数脱敏和忽略 | ||
| 249 | + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); | ||
| 250 | + String[] argNames = methodSignature.getParameterNames(); | ||
| 251 | + Object[] argValues = joinPoint.getArgs(); | ||
| 252 | + // 拼接参数 | ||
| 253 | + Map<String, Object> args = Maps.newHashMapWithExpectedSize(argValues.length); | ||
| 254 | + for (int i = 0; i < argNames.length; i++) { | ||
| 255 | + String argName = argNames[i]; | ||
| 256 | + Object argValue = argValues[i]; | ||
| 257 | + // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 | ||
| 258 | + args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); | ||
| 259 | + } | ||
| 260 | + return JsonUtils.toJsonString(args); | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + private static String obtainResultData(Object result) { | ||
| 264 | + // TODO 提升:结果脱敏和忽略 | ||
| 265 | + if (result instanceof CommonResult) { | ||
| 266 | + result = ((CommonResult<?>) result).getData(); | ||
| 267 | + } | ||
| 268 | + return JsonUtils.toJsonString(result); | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + private static boolean isIgnoreArgs(Object object) { | ||
| 272 | + Class<?> clazz = object.getClass(); | ||
| 273 | + // 处理数组的情况 | ||
| 274 | + if (clazz.isArray()) { | ||
| 275 | + return IntStream.range(0, Array.getLength(object)) | ||
| 276 | + .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); | ||
| 277 | + } | ||
| 278 | + // 递归,处理数组、Collection、Map 的情况 | ||
| 279 | + if (Collection.class.isAssignableFrom(clazz)) { | ||
| 280 | + return ((Collection<?>) object).stream() | ||
| 281 | + .anyMatch((Predicate<Object>) OperateLogV2Aspect::isIgnoreArgs); | ||
| 282 | + } | ||
| 283 | + if (Map.class.isAssignableFrom(clazz)) { | ||
| 284 | + return isIgnoreArgs(((Map<?, ?>) object).values()); | ||
| 285 | + } | ||
| 286 | + // obj | ||
| 287 | + return object instanceof MultipartFile | ||
| 288 | + || object instanceof HttpServletRequest | ||
| 289 | + || object instanceof HttpServletResponse | ||
| 290 | + || object instanceof BindingResult; | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { | ||
| 294 | + if (ArrayUtil.isEmpty(requestMethods)) { | ||
| 295 | + return null; | ||
| 296 | + } | ||
| 297 | + // 优先,匹配最优的 POST、PUT、DELETE | ||
| 298 | + RequestMethod result = obtainFirstLogRequestMethod(requestMethods); | ||
| 299 | + if (result != null) { | ||
| 300 | + return result; | ||
| 301 | + } | ||
| 302 | + // 然后,匹配次优的 GET | ||
| 303 | + result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) | ||
| 304 | + .findFirst().orElse(null); | ||
| 305 | + if (result != null) { | ||
| 306 | + return result; | ||
| 307 | + } | ||
| 308 | + // 兜底,获得第一个 | ||
| 309 | + return requestMethods[0]; | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { | ||
| 313 | + RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 | ||
| 314 | + ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); | ||
| 315 | + return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { | ||
| 319 | + if (ArrayUtil.isEmpty(requestMethods)) { | ||
| 320 | + return null; | ||
| 321 | + } | ||
| 322 | + return Arrays.stream(requestMethods).filter(requestMethod -> | ||
| 323 | + requestMethod == RequestMethod.POST | ||
| 324 | + || requestMethod == RequestMethod.PUT | ||
| 325 | + || requestMethod == RequestMethod.DELETE) | ||
| 326 | + .findFirst().orElse(null); | ||
| 327 | + } | ||
| 328 | + | ||
| 329 | +} |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.operatelogv2.core.enums; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 操作日志常量接口 | ||
| 5 | + * | ||
| 6 | + * @author HUIHUI | ||
| 7 | + */ | ||
| 8 | +public interface OperateLogV2Constants { | ||
| 9 | + | ||
| 10 | + // ========== 开关字段-如果没有值默认就是记录 ========== | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 是否记录日志 | ||
| 14 | + */ | ||
| 15 | + String ENABLE = "enable"; | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 是否记录方法参数 | ||
| 19 | + */ | ||
| 20 | + String IS_LOG_ARGS = "isLogArgs"; | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 是否记录方法结果的数据 | ||
| 24 | + */ | ||
| 25 | + String IS_LOG_RESULT_DATA = "isLogResultData"; | ||
| 26 | + | ||
| 27 | + // ========== 扩展 ========== | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 扩展信息 | ||
| 31 | + */ | ||
| 32 | + String EXTRA_KEY = "extra"; | ||
| 33 | + | ||
| 34 | +} |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.operatelogv2.core.service; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; | ||
| 4 | +import com.mzt.logapi.beans.LogRecord; | ||
| 5 | +import com.mzt.logapi.context.LogRecordContext; | ||
| 6 | +import com.mzt.logapi.service.ILogRecordService; | ||
| 7 | +import lombok.extern.slf4j.Slf4j; | ||
| 8 | + | ||
| 9 | +import java.util.Collections; | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 操作日志 ILogRecordService 实现类 | ||
| 14 | + * | ||
| 15 | + * 基于 {@link OperateLogV2Aspect} 实现,记录操作日志 | ||
| 16 | + * | ||
| 17 | + * @author HUIHUI | ||
| 18 | + */ | ||
| 19 | +@Slf4j | ||
| 20 | +public class ILogRecordServiceImpl implements ILogRecordService { | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public void record(LogRecord logRecord) { | ||
| 24 | + OperateLogV2Aspect.setContent(logRecord); // 操作日志 | ||
| 25 | + OperateLogV2Aspect.addExtra(LogRecordContext.getVariables()); // 扩展信息 | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public List<LogRecord> queryLog(String bizNo, String type) { | ||
| 30 | + return Collections.emptyList(); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public List<LogRecord> queryLogByBizNo(String bizNo, String type, String subType) { | ||
| 35 | + return Collections.emptyList(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | +} |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.operatelogv2.core.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +@Schema(description = "管理后台 - 操作日志分页 Request VO") | ||
| 8 | +@Data | ||
| 9 | +public class OperateLogV2PageReqVO extends PageParam { | ||
| 10 | + | ||
| 11 | + @Schema(description = "模块数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||
| 12 | + private Long bizId; | ||
| 13 | + | ||
| 14 | + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 15 | + private Long userId; | ||
| 16 | + | ||
| 17 | + @Schema(description = "模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 18 | + private String bizType; | ||
| 19 | + | ||
| 20 | +} |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
| 1 | -cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration | ||
| 2 | \ No newline at end of file | 1 | \ No newline at end of file |
| 2 | +cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration | ||
| 3 | +cn.iocoder.yudao.framework.operatelogv2.config.YudaoOperateLogV2Configuration | ||
| 3 | \ No newline at end of file | 4 | \ No newline at end of file |
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 { | @@ -22,6 +22,5 @@ public interface LogRecordConstants { | ||
| 22 | //======================= 客户转移操作日志 ======================= | 22 | //======================= 客户转移操作日志 ======================= |
| 23 | 23 | ||
| 24 | String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; | 24 | String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; |
| 25 | - String TRANSFER_CUSTOMER_LOG_FAIL = ""; // TODO @puhui999:这个可以删除哈,一般不搞失败的日志 | ||
| 26 | 25 | ||
| 27 | } | 26 | } |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.enums.permission; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Crm 数据权限角色枚举 | ||
| 8 | + * | ||
| 9 | + * @author HUIHUI | ||
| 10 | + */ | ||
| 11 | +@Getter | ||
| 12 | +@AllArgsConstructor | ||
| 13 | +public enum CrmPermissionRoleCodeEnum { | ||
| 14 | + | ||
| 15 | + CRM_ADMIN("crm_admin", "CRM 管理员"); | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 角色标识 | ||
| 19 | + */ | ||
| 20 | + private String code; | ||
| 21 | + /** | ||
| 22 | + * 角色名称 | ||
| 23 | + */ | ||
| 24 | + private String name; | ||
| 25 | + | ||
| 26 | +} | ||
| 27 | + |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http
| 1 | ### 请求 /transfer | 1 | ### 请求 /transfer |
| 2 | PUT {{baseUrl}}/crm/customer/transfer | 2 | PUT {{baseUrl}}/crm/customer/transfer |
| 3 | -Content-Type: application/json | 3 | +Content-Type: application/-id: {{adminTenentId}}json |
| 4 | Authorization: Bearer {{token}} | 4 | Authorization: Bearer {{token}} |
| 5 | -tenant-id: {{adminTenentId}} | 5 | +tenant |
| 6 | 6 | ||
| 7 | { | 7 | { |
| 8 | "id": 10, | 8 | "id": 10, |
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; | @@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 6 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | 7 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 7 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | 8 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 9 | +import cn.iocoder.yudao.framework.operatelogv2.core.vo.OperateLogV2PageReqVO; | ||
| 8 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | 10 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; |
| 9 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; | 11 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; |
| 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| @@ -12,6 +14,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | @@ -12,6 +14,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||
| 12 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | 14 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 13 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | 15 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 14 | import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | 16 | import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; |
| 17 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | ||
| 15 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | 18 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; |
| 16 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 19 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 17 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 20 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| @@ -64,7 +67,7 @@ public class CrmCustomerController { | @@ -64,7 +67,7 @@ public class CrmCustomerController { | ||
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | @PutMapping("/update") | 69 | @PutMapping("/update") |
| 67 | - //@Operation(summary = "更新客户") | 70 | + @Operation(summary = "更新客户") |
| 68 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") | 71 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 69 | public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { | 72 | public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { |
| 70 | customerService.updateCustomer(updateReqVO); | 73 | customerService.updateCustomer(updateReqVO); |
| @@ -128,30 +131,21 @@ public class CrmCustomerController { | @@ -128,30 +131,21 @@ public class CrmCustomerController { | ||
| 128 | } | 131 | } |
| 129 | 132 | ||
| 130 | @PutMapping("/transfer") | 133 | @PutMapping("/transfer") |
| 131 | - //@Operation(summary = "客户转移") | 134 | + @Operation(summary = "客户转移") |
| 132 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") | 135 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 133 | public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { | 136 | public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { |
| 134 | customerService.transferCustomer(reqVO, getLoginUserId()); | 137 | customerService.transferCustomer(reqVO, getLoginUserId()); |
| 135 | return success(true); | 138 | return success(true); |
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | - // TODO @puhui999:operate-log-list 或者 operate-log-page 如果分页 | ||
| 139 | - @GetMapping("/operate-log") | 141 | + @GetMapping("/operate-log-page") |
| 140 | @Operation(summary = "获得客户操作日志") | 142 | @Operation(summary = "获得客户操作日志") |
| 141 | @Parameter(name = "id", description = "编号", required = true, example = "1024") | 143 | @Parameter(name = "id", description = "编号", required = true, example = "1024") |
| 142 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") | 144 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") |
| 143 | - // TODO @puhui999:最好有读权限;方法名改成 getCustomerOperateLog | ||
| 144 | - public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) { | ||
| 145 | - // 1. 获取客户 | ||
| 146 | - // TODO @puhui999:这个校验可以去掉哈; | ||
| 147 | - CrmCustomerDO customer = customerService.getCustomer(id); | ||
| 148 | - if (customer == null) { | ||
| 149 | - return success(null); | ||
| 150 | - } | ||
| 151 | - | ||
| 152 | - // 2. 获取操作日志 | ||
| 153 | - // TODO @puhui999:操作日志,返回可能要分页哈; | ||
| 154 | - return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id)); | 145 | + public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(OperateLogV2PageReqVO reqVO) { |
| 146 | + reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 | ||
| 147 | + reqVO.setBizType(CRM_CUSTOMER); | ||
| 148 | + return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); | ||
| 155 | } | 149 | } |
| 156 | 150 | ||
| 157 | // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; | 151 | // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; |
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 | @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionR | ||
| 8 | import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; | 8 | import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; |
| 9 | import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; | 9 | import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; |
| 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; |
| 11 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | ||
| 12 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 11 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 12 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | ||
| 13 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 13 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 14 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; | 14 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 15 | import cn.iocoder.yudao.module.system.api.dept.PostApi; | 15 | import cn.iocoder.yudao.module.system.api.dept.PostApi; |
| @@ -21,12 +21,12 @@ import io.swagger.v3.oas.annotations.Operation; | @@ -21,12 +21,12 @@ import io.swagger.v3.oas.annotations.Operation; | ||
| 21 | import io.swagger.v3.oas.annotations.Parameter; | 21 | import io.swagger.v3.oas.annotations.Parameter; |
| 22 | import io.swagger.v3.oas.annotations.Parameters; | 22 | import io.swagger.v3.oas.annotations.Parameters; |
| 23 | import io.swagger.v3.oas.annotations.tags.Tag; | 23 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 24 | +import jakarta.annotation.Resource; | ||
| 25 | +import jakarta.validation.Valid; | ||
| 24 | import org.springframework.security.access.prepost.PreAuthorize; | 26 | import org.springframework.security.access.prepost.PreAuthorize; |
| 25 | import org.springframework.validation.annotation.Validated; | 27 | import org.springframework.validation.annotation.Validated; |
| 26 | import org.springframework.web.bind.annotation.*; | 28 | import org.springframework.web.bind.annotation.*; |
| 27 | 29 | ||
| 28 | -import jakarta.annotation.Resource; | ||
| 29 | -import jakarta.validation.Valid; | ||
| 30 | import java.util.*; | 30 | import java.util.*; |
| 31 | 31 | ||
| 32 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 32 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
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<CrmBusinessDO> { | @@ -38,11 +38,8 @@ public interface CrmBusinessMapper extends BaseMapperX<CrmBusinessDO> { | ||
| 38 | default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { | 38 | default PageResult<CrmBusinessDO> selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { |
| 39 | MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); | 39 | MPJLambdaWrapperX<CrmBusinessDO> query = new MPJLambdaWrapperX<>(); |
| 40 | // 拼接数据权限的查询条件 | 40 | // 拼接数据权限的查询条件 |
| 41 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), | 41 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), |
| 42 | CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | 42 | CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); |
| 43 | - if (!condition) { | ||
| 44 | - return PageResult.empty(); | ||
| 45 | - } | ||
| 46 | // 拼接自身的查询条件 | 43 | // 拼接自身的查询条件 |
| 47 | query.selectAll(CrmBusinessDO.class) | 44 | query.selectAll(CrmBusinessDO.class) |
| 48 | .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) | 45 | .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) |
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<CrmClueDO> { | @@ -30,11 +30,8 @@ public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { | ||
| 30 | default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { | 30 | default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); | 31 | MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); |
| 32 | // 拼接数据权限的查询条件 | 32 | // 拼接数据权限的查询条件 |
| 33 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), | 33 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), |
| 34 | CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | 34 | CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); |
| 35 | - if (!condition) { | ||
| 36 | - return PageResult.empty(); | ||
| 37 | - } | ||
| 38 | // 拼接自身的查询条件 | 35 | // 拼接自身的查询条件 |
| 39 | query.selectAll(CrmClueDO.class) | 36 | query.selectAll(CrmClueDO.class) |
| 40 | .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) | 37 | .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) |
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<CrmContactDO> { | @@ -43,11 +43,8 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> { | ||
| 43 | default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { | 43 | default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { |
| 44 | MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); | 44 | MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); |
| 45 | // 拼接数据权限的查询条件 | 45 | // 拼接数据权限的查询条件 |
| 46 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), | 46 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), |
| 47 | CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | 47 | CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); |
| 48 | - if (!condition) { | ||
| 49 | - return PageResult.empty(); | ||
| 50 | - } | ||
| 51 | // 拼接自身的查询条件 | 48 | // 拼接自身的查询条件 |
| 52 | query.selectAll(CrmContactDO.class) | 49 | query.selectAll(CrmContactDO.class) |
| 53 | .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) | 50 | .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) |
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<CrmContractDO> { | @@ -41,11 +41,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { | ||
| 41 | default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { | 41 | default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { |
| 42 | MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); | 42 | MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); |
| 43 | // 拼接数据权限的查询条件 | 43 | // 拼接数据权限的查询条件 |
| 44 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), | 44 | + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), |
| 45 | CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | 45 | CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); |
| 46 | - if (!condition) { | ||
| 47 | - return PageResult.empty(); | ||
| 48 | - } | ||
| 49 | // 拼接自身的查询条件 | 46 | // 拼接自身的查询条件 |
| 50 | mpjLambdaWrapperX.selectAll(CrmContractDO.class) | 47 | mpjLambdaWrapperX.selectAll(CrmContractDO.class) |
| 51 | .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) | 48 | .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) |
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<CrmCustomerDO> { | @@ -30,11 +30,8 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { | ||
| 30 | default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { | 30 | default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { |
| 31 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); | 31 | MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); |
| 32 | // 拼接数据权限的查询条件 | 32 | // 拼接数据权限的查询条件 |
| 33 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), | 33 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), |
| 34 | CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); | 34 | CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); |
| 35 | - if (!condition) { | ||
| 36 | - return PageResult.empty(); | ||
| 37 | - } | ||
| 38 | // 拼接自身的查询条件 | 35 | // 拼接自身的查询条件 |
| 39 | query.selectAll(CrmCustomerDO.class) | 36 | query.selectAll(CrmCustomerDO.class) |
| 40 | .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) | 37 | .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) |
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<CrmReceivableDO> { | @@ -39,11 +39,8 @@ public interface CrmReceivableMapper extends BaseMapperX<CrmReceivableDO> { | ||
| 39 | default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { | 39 | default PageResult<CrmReceivableDO> selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { |
| 40 | MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); | 40 | MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); |
| 41 | // 拼接数据权限的查询条件 | 41 | // 拼接数据权限的查询条件 |
| 42 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), | 42 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), |
| 43 | CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | 43 | CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); |
| 44 | - if (!condition) { | ||
| 45 | - return PageResult.empty(); | ||
| 46 | - } | ||
| 47 | // 拼接自身的查询条件 | 44 | // 拼接自身的查询条件 |
| 48 | query.selectAll(CrmReceivableDO.class) | 45 | query.selectAll(CrmReceivableDO.class) |
| 49 | .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) | 46 | .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) |
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<CrmReceivablePlanDO | @@ -38,11 +38,8 @@ public interface CrmReceivablePlanMapper extends BaseMapperX<CrmReceivablePlanDO | ||
| 38 | default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { | 38 | default PageResult<CrmReceivablePlanDO> selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { |
| 39 | MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); | 39 | MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); |
| 40 | // 拼接数据权限的查询条件 | 40 | // 拼接数据权限的查询条件 |
| 41 | - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), | 41 | + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), |
| 42 | CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); | 42 | CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); |
| 43 | - if (!condition) { | ||
| 44 | - return PageResult.empty(); | ||
| 45 | - } | ||
| 46 | // 拼接自身的查询条件 | 43 | // 拼接自身的查询条件 |
| 47 | query.selectAll(CrmReceivablePlanDO.class) | 44 | query.selectAll(CrmReceivablePlanDO.class) |
| 48 | .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) | 45 | .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java deleted
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java deleted
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java
0 → 100644
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java
| 1 | -package cn.iocoder.yudao.module.crm.framework.bizlog.function; | 1 | +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.StrUtil; | 3 | import cn.hutool.core.util.StrUtil; |
| 4 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | 4 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; |
| @@ -8,7 +8,6 @@ import org.springframework.stereotype.Component; | @@ -8,7 +8,6 @@ import org.springframework.stereotype.Component; | ||
| 8 | 8 | ||
| 9 | import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; | 9 | import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; |
| 10 | 10 | ||
| 11 | -// TODO @puhui999:包名使用 operatelog 更合适哈; | ||
| 12 | /** | 11 | /** |
| 13 | * 自定义函数-通过行业编号获取行业信息 | 12 | * 自定义函数-通过行业编号获取行业信息 |
| 14 | * | 13 | * |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java
| 1 | -package cn.iocoder.yudao.module.crm.framework.bizlog.function; | 1 | +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.StrUtil; | 3 | import cn.hutool.core.util.StrUtil; |
| 4 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | 4 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java
| 1 | -package cn.iocoder.yudao.module.crm.framework.bizlog.function; | 1 | +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.StrUtil; | 3 | import cn.hutool.core.util.StrUtil; |
| 4 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; | 4 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java
| 1 | -package cn.iocoder.yudao.module.crm.framework.core.annotations; | 1 | +package cn.iocoder.yudao.module.crm.framework.permission.core.annotations; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 3 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 4 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 4 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
| 1 | -package cn.iocoder.yudao.module.crm.framework.core.aop; | 1 | +package cn.iocoder.yudao.module.crm.framework.permission.core.aop; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.util.ObjUtil; | 4 | import cn.hutool.core.util.ObjUtil; |
| @@ -6,27 +6,27 @@ import cn.hutool.core.util.StrUtil; | @@ -6,27 +6,27 @@ import cn.hutool.core.util.StrUtil; | ||
| 6 | import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; | 6 | import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; |
| 7 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 7 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; |
| 9 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | ||
| 10 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 9 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 11 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 10 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 11 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | ||
| 12 | +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; | ||
| 12 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 13 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 14 | +import jakarta.annotation.Resource; | ||
| 13 | import lombok.extern.slf4j.Slf4j; | 15 | import lombok.extern.slf4j.Slf4j; |
| 14 | import org.aspectj.lang.JoinPoint; | 16 | import org.aspectj.lang.JoinPoint; |
| 15 | import org.aspectj.lang.annotation.Aspect; | 17 | import org.aspectj.lang.annotation.Aspect; |
| 16 | import org.aspectj.lang.annotation.Before; | 18 | import org.aspectj.lang.annotation.Before; |
| 17 | import org.springframework.stereotype.Component; | 19 | import org.springframework.stereotype.Component; |
| 18 | 20 | ||
| 19 | -import jakarta.annotation.Resource; | ||
| 20 | import java.util.ArrayList; | 21 | import java.util.ArrayList; |
| 21 | import java.util.List; | 22 | import java.util.List; |
| 22 | import java.util.Map; | 23 | import java.util.Map; |
| 23 | 24 | ||
| 24 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 25 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; | ||
| 25 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | 27 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 26 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED; | 28 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED; |
| 27 | -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS; | ||
| 28 | 29 | ||
| 29 | -// TODO 这个包,改成 permission,然后搞 config 和 core 包,这个类在 core 包里;目的是:framework 最好分类下 | ||
| 30 | /** | 30 | /** |
| 31 | * Crm 数据权限校验 AOP 切面 | 31 | * Crm 数据权限校验 AOP 切面 |
| 32 | * | 32 | * |
| @@ -42,10 +42,6 @@ public class CrmPermissionAspect { | @@ -42,10 +42,6 @@ public class CrmPermissionAspect { | ||
| 42 | 42 | ||
| 43 | @Before("@annotation(crmPermission)") | 43 | @Before("@annotation(crmPermission)") |
| 44 | public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { | 44 | public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { |
| 45 | - // TODO 芋艿:临时,方便大家调试 | ||
| 46 | - //if (true) { | ||
| 47 | - // return; | ||
| 48 | - //} | ||
| 49 | // 获取相关属性值 | 45 | // 获取相关属性值 |
| 50 | Map<String, Object> expressionValues = parseExpressions(joinPoint, crmPermission); | 46 | Map<String, Object> expressionValues = parseExpressions(joinPoint, crmPermission); |
| 51 | Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? | 47 | Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? |
| @@ -53,16 +49,28 @@ public class CrmPermissionAspect { | @@ -53,16 +49,28 @@ public class CrmPermissionAspect { | ||
| 53 | Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号 | 49 | Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号 |
| 54 | Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 | 50 | Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 |
| 55 | 51 | ||
| 56 | - // TODO 如果是超级管理员则直接通过 | ||
| 57 | - //if (superAdmin){ | ||
| 58 | - // return; | ||
| 59 | - //} | ||
| 60 | - | ||
| 61 | - // 1. 获取数据权限 | 52 | + // 1.1 如果是超级管理员则直接通过 |
| 53 | + if (CrmPermissionUtils.validateAdminUser()) { | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + // 1.2 获取数据权限 | ||
| 62 | List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); | 57 | List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); |
| 63 | - if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在 | ||
| 64 | - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType)); | 58 | + if (CollUtil.isEmpty(bizPermissions)) { // 没有数据权限的情况 |
| 59 | + // 公海数据如果没有团队成员大家也因该有读权限才对 | ||
| 60 | + if (CrmPermissionLevelEnum.isRead(permissionLevel)) { | ||
| 61 | + return; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + // 没有数据权限的情况下超出了读权限直接报错,避免后面校验空指针 | ||
| 65 | + throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType)); | ||
| 66 | + } else { // 有数据权限但是没有负责人的情况 | ||
| 67 | + if (!anyMatch(bizPermissions, item -> CrmPermissionLevelEnum.isOwner(item.getLevel()))) { | ||
| 68 | + if (CrmPermissionLevelEnum.isRead(permissionLevel)) { | ||
| 69 | + return; | ||
| 70 | + } | ||
| 71 | + } | ||
| 65 | } | 72 | } |
| 73 | + | ||
| 66 | // 2.1 情况一:如果自己是负责人,则默认有所有权限 | 74 | // 2.1 情况一:如果自己是负责人,则默认有所有权限 |
| 67 | CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId())); | 75 | CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId())); |
| 68 | if (userPermission != null) { | 76 | if (userPermission != null) { |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java
0 → 100644
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.framework.permission.core.util; | ||
| 2 | + | ||
| 3 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||
| 5 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; | ||
| 6 | +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 数据权限工具类 | ||
| 10 | + * | ||
| 11 | + * @author HUIHUI | ||
| 12 | + */ | ||
| 13 | +public class CrmPermissionUtils { | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 校验用户是否是 CRM 管理员 | ||
| 17 | + * | ||
| 18 | + * @return 是/否 | ||
| 19 | + */ | ||
| 20 | + public static boolean validateAdminUser() { | ||
| 21 | + return SingletonManager.getPermissionApi().hasAnyRoles(getUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 获得用户编号 | ||
| 26 | + * | ||
| 27 | + * @return 用户编号 | ||
| 28 | + */ | ||
| 29 | + private static Long getUserId() { | ||
| 30 | + return WebFrameworkUtils.getLoginUserId(); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 静态内部类实现单例获取 | ||
| 35 | + * | ||
| 36 | + * @author HUIHUI | ||
| 37 | + */ | ||
| 38 | + private static class SingletonManager { | ||
| 39 | + | ||
| 40 | + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); | ||
| 41 | + | ||
| 42 | + public static PermissionApi getPermissionApi() { | ||
| 43 | + return PERMISSION_API; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | +} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java
0 → 100644
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; | @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; | ||
| 12 | import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; | 12 | import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; |
| 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 15 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 15 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 16 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 16 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 17 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 17 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 18 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 18 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
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; | @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; | ||
| 12 | import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; | 12 | import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; |
| 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 15 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 15 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 16 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 16 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 17 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 17 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 18 | import jakarta.annotation.Resource; | 18 | import jakarta.annotation.Resource; |
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; | @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; | ||
| 9 | import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; | 9 | import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; |
| 10 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 10 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 11 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 11 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 12 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 12 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 13 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 13 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 14 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 14 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 15 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 15 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
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 | @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContact | ||
| 14 | import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; | 14 | import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; |
| 15 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 15 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 16 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 16 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 17 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 17 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 18 | import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; | 18 | import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; |
| 19 | import jakarta.annotation.Resource; | 19 | import jakarta.annotation.Resource; |
| 20 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
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; | @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; | ||
| 12 | import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; | 12 | import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; |
| 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 15 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 15 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 16 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 16 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 17 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 17 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 18 | import jakarta.annotation.Resource; | 18 | import jakarta.annotation.Resource; |
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; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.customer; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | +import cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants; | ||
| 6 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; | 7 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; |
| 7 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | 8 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; |
| 8 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | 9 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; |
| @@ -12,7 +13,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | @@ -12,7 +13,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; | ||
| 12 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; | 13 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; |
| 13 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 14 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 14 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 15 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 15 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 16 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 16 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 17 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 17 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 18 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 18 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 19 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -52,6 +53,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -52,6 +53,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 52 | 53 | ||
| 53 | @Override | 54 | @Override |
| 54 | @Transactional(rollbackFor = Exception.class) | 55 | @Transactional(rollbackFor = Exception.class) |
| 56 | + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#customerId}}", success = "创建了客户") | ||
| 55 | public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { | 57 | public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { |
| 56 | // 插入 | 58 | // 插入 |
| 57 | CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); | 59 | CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); |
| @@ -60,26 +62,34 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -60,26 +62,34 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 60 | // 创建数据权限 | 62 | // 创建数据权限 |
| 61 | crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) | 63 | crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) |
| 62 | .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 | 64 | .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 |
| 65 | + | ||
| 66 | + // 添加日志上下文所需 | ||
| 67 | + LogRecordContext.putVariable("customerId", customer.getId()); | ||
| 63 | return customer.getId(); | 68 | return customer.getId(); |
| 64 | } | 69 | } |
| 65 | 70 | ||
| 66 | @Override | 71 | @Override |
| 67 | @Transactional(rollbackFor = Exception.class) | 72 | @Transactional(rollbackFor = Exception.class) |
| 68 | - @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") | 73 | + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}") |
| 69 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | 74 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 70 | public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { | 75 | public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { |
| 71 | // 校验存在 | 76 | // 校验存在 |
| 72 | CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); | 77 | CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); |
| 73 | 78 | ||
| 74 | - // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null | ||
| 75 | - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); | ||
| 76 | // 更新 | 79 | // 更新 |
| 77 | CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); | 80 | CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); |
| 78 | customerMapper.updateById(updateObj); | 81 | customerMapper.updateById(updateObj); |
| 82 | + | ||
| 83 | + // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null | ||
| 84 | + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); | ||
| 85 | + HashMap<String, Object> extra = new HashMap<>(); | ||
| 86 | + extra.put("tips", "随便记录一点啦"); | ||
| 87 | + LogRecordContext.putVariable(OperateLogV2Constants.EXTRA_KEY, extra); | ||
| 79 | } | 88 | } |
| 80 | 89 | ||
| 81 | @Override | 90 | @Override |
| 82 | @Transactional(rollbackFor = Exception.class) | 91 | @Transactional(rollbackFor = Exception.class) |
| 92 | + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "删除了客户") | ||
| 83 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | 93 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 84 | public void deleteCustomer(Long id) { | 94 | public void deleteCustomer(Long id) { |
| 85 | // 校验存在 | 95 | // 校验存在 |
| @@ -125,27 +135,17 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -125,27 +135,17 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 125 | */ | 135 | */ |
| 126 | @Override | 136 | @Override |
| 127 | public void validateCustomer(Long customerId) { | 137 | public void validateCustomer(Long customerId) { |
| 128 | - // 校验客户是否存在 | ||
| 129 | - if (customerId == null) { | ||
| 130 | - throw exception(CUSTOMER_NOT_EXISTS); | ||
| 131 | - } | ||
| 132 | - CrmCustomerDO customer = customerMapper.selectById(customerId); | ||
| 133 | - if (Objects.isNull(customer)) { | ||
| 134 | - throw exception(CUSTOMER_NOT_EXISTS); | ||
| 135 | - } | 138 | + validateCustomerExists(customerId); |
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | @Override | 141 | @Override |
| 139 | @Transactional(rollbackFor = Exception.class) | 142 | @Transactional(rollbackFor = Exception.class) |
| 140 | - // TODO @puhui999:@LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) | ||
| 141 | - @LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}") | 143 | + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) |
| 142 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) | 144 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) |
| 143 | public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { | 145 | public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { |
| 144 | // 1. 校验客户是否存在 | 146 | // 1. 校验客户是否存在 |
| 145 | - validateCustomer(reqVO.getId()); | ||
| 146 | - // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 | ||
| 147 | - // TODO @puhui999:customer 不用查询,从 1. 拿到哈;然后 put这个动作,可以放到 3.;这样逻辑结构就是,校验、逻辑、日志,更加清晰 | ||
| 148 | - LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); | 147 | + CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId()); |
| 148 | + | ||
| 149 | // 2.1 数据权限转移 | 149 | // 2.1 数据权限转移 |
| 150 | crmPermissionService.transferPermission( | 150 | crmPermissionService.transferPermission( |
| 151 | CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); | 151 | CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); |
| @@ -153,9 +153,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -153,9 +153,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 153 | customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | 153 | customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |
| 154 | 154 | ||
| 155 | // 3. TODO 记录转移日志 | 155 | // 3. TODO 记录转移日志 |
| 156 | + LogRecordContext.putVariable("crmCustomer", customerDO); | ||
| 156 | } | 157 | } |
| 157 | 158 | ||
| 158 | @Override | 159 | @Override |
| 160 | + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") | ||
| 159 | public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) { | 161 | public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) { |
| 160 | // 校验存在 | 162 | // 校验存在 |
| 161 | validateCustomerExists(updateReqVO.getId()); | 163 | validateCustomerExists(updateReqVO.getId()); |
| @@ -169,6 +171,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | @@ -169,6 +171,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||
| 169 | 171 | ||
| 170 | @Override | 172 | @Override |
| 171 | @Transactional(rollbackFor = Exception.class) | 173 | @Transactional(rollbackFor = Exception.class) |
| 174 | + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "将客户放入了公海") | ||
| 172 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | 175 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 173 | public void putCustomerPool(Long id) { | 176 | public void putCustomerPool(Long id) { |
| 174 | // 1. 校验存在 | 177 | // 1. 校验存在 |
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; | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | ||
| 8 | import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; | 8 | import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; |
| 9 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 9 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 10 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 10 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 11 | +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; | ||
| 11 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; | 12 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 12 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; | 13 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; |
| 13 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 14 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| @@ -89,8 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | @@ -89,8 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | ||
| 89 | CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( | 90 | CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( |
| 90 | transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); | 91 | transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); |
| 91 | String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); | 92 | String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); |
| 92 | - // TODO 校验是否为超级管理员 || 1 | ||
| 93 | - if (oldPermission == null || !isOwner(oldPermission.getLevel())) { | 93 | + if (oldPermission == null || !isOwner(oldPermission.getLevel()) || !CrmPermissionUtils.validateAdminUser()) { |
| 94 | throw exception(CRM_PERMISSION_DENIED, bizTypeName); | 94 | throw exception(CRM_PERMISSION_DENIED, bizTypeName); |
| 95 | } | 95 | } |
| 96 | // 1.1 校验转移对象是否已经是该负责人 | 96 | // 1.1 校验转移对象是否已经是该负责人 |
| @@ -138,7 +138,6 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | @@ -138,7 +138,6 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | ||
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | @Override | 140 | @Override |
| 141 | - @Transactional(rollbackFor = Exception.class) // TODO @puhui999:这里不用加的,就一个操作哈; | ||
| 142 | public void deletePermission(Integer bizType, Long bizId) { | 141 | public void deletePermission(Integer bizType, Long bizId) { |
| 143 | int deletedCount = crmPermissionMapper.deletePermission(bizType, bizId); | 142 | int deletedCount = crmPermissionMapper.deletePermission(bizType, bizId); |
| 144 | if (deletedCount == 0) { | 143 | if (deletedCount == 0) { |
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 | @@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO | ||
| 15 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; | 15 | import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; |
| 16 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 16 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 17 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 17 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 18 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 18 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 19 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 19 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 20 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 20 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 21 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 21 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
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; | @@ -18,7 +18,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; | ||
| 18 | import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; | 18 | import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; |
| 19 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 19 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 20 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 20 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 21 | -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; | 21 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 22 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | 22 | import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; |
| 23 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | 23 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 24 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | 24 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java
| @@ -7,9 +7,11 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | @@ -7,9 +7,11 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; | ||
| 7 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | 7 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 8 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; | 8 | import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; |
| 9 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | 9 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 10 | +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; | ||
| 10 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | 11 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 11 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | 12 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 12 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; | 13 | import com.baomidou.mybatisplus.core.toolkit.support.SFunction; |
| 14 | +import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; | ||
| 13 | import com.github.yulichang.wrapper.MPJLambdaWrapper; | 15 | import com.github.yulichang.wrapper.MPJLambdaWrapper; |
| 14 | 16 | ||
| 15 | import java.util.Collection; | 17 | import java.util.Collection; |
| @@ -33,46 +35,41 @@ public class CrmQueryWrapperUtils { | @@ -33,46 +35,41 @@ public class CrmQueryWrapperUtils { | ||
| 33 | * @param userId 用户编号 | 35 | * @param userId 用户编号 |
| 34 | * @param sceneType 场景类型 | 36 | * @param sceneType 场景类型 |
| 35 | * @param pool 公海 | 37 | * @param pool 公海 |
| 36 | - * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) | ||
| 37 | */ | 38 | */ |
| 38 | - // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少;是不是把 bizId 传入就好啦? | ||
| 39 | - public static <T extends MPJLambdaWrapper<?>, S> boolean appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId, | ||
| 40 | - Long userId, Integer sceneType, Boolean pool) { | 39 | + public static <T extends MPJLambdaWrapper<?>, S> void appendPermissionCondition(T query, Integer bizType, SFunction<S, ?> bizId, |
| 40 | + Long userId, Integer sceneType, Boolean pool) { | ||
| 41 | + final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; | ||
| 41 | // 1. 构建数据权限连表条件 | 42 | // 1. 构建数据权限连表条件 |
| 42 | - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 | 43 | + if (ObjUtil.notEqual(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 |
| 43 | query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) | 44 | query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) |
| 44 | - .eq(CrmPermissionDO::getBizId, bizId) | 45 | + .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 |
| 45 | .eq(CrmPermissionDO::getUserId, userId)); | 46 | .eq(CrmPermissionDO::getUserId, userId)); |
| 46 | } | 47 | } |
| 47 | // 2.1 场景一:我负责的数据 | 48 | // 2.1 场景一:我负责的数据 |
| 48 | if (CrmSceneTypeEnum.isOwner(sceneType)) { | 49 | if (CrmSceneTypeEnum.isOwner(sceneType)) { |
| 49 | - query.eq("owner_user_id", userId); | 50 | + query.eq(ownerUserIdField, userId); |
| 50 | } | 51 | } |
| 51 | // 2.2 场景二:我参与的数据 | 52 | // 2.2 场景二:我参与的数据 |
| 52 | if (CrmSceneTypeEnum.isInvolved(sceneType)) { | 53 | if (CrmSceneTypeEnum.isInvolved(sceneType)) { |
| 53 | - query.ne("owner_user_id", userId) | ||
| 54 | - // TODO @puhui999:IN 是不是更合适哈; | ||
| 55 | - .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel()) | ||
| 56 | - .or() | ||
| 57 | - .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel())); | 54 | + query.ne(ownerUserIdField, userId) |
| 55 | + .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel()); | ||
| 58 | } | 56 | } |
| 59 | // 2.3 场景三:下属负责的数据 | 57 | // 2.3 场景三:下属负责的数据 |
| 60 | if (CrmSceneTypeEnum.isSubordinate(sceneType)) { | 58 | if (CrmSceneTypeEnum.isSubordinate(sceneType)) { |
| 61 | - // TODO @puhui999:要不如果没有下属,拼一个 owner_user_id in null,不返回结果就好啦; | ||
| 62 | - List<AdminUserRespDTO> subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); | 59 | + List<AdminUserRespDTO> subordinateUsers = SingletonManager.getAdminUserApi().getUserListBySubordinate(userId); |
| 63 | if (CollUtil.isEmpty(subordinateUsers)) { | 60 | if (CollUtil.isEmpty(subordinateUsers)) { |
| 64 | - return false; | 61 | + query.eq(ownerUserIdField, -1); // 不返回任何结果 |
| 62 | + } else { | ||
| 63 | + query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId)); | ||
| 65 | } | 64 | } |
| 66 | - query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); | ||
| 67 | } | 65 | } |
| 68 | 66 | ||
| 69 | // 3. 拼接公海的查询条件 | 67 | // 3. 拼接公海的查询条件 |
| 70 | if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 | 68 | if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 |
| 71 | - query.isNull("owner_user_id"); | 69 | + query.isNull(ownerUserIdField); |
| 72 | } else { // 情况二:不是公海 | 70 | } else { // 情况二:不是公海 |
| 73 | - query.isNotNull("owner_user_id"); | 71 | + query.isNotNull(ownerUserIdField); |
| 74 | } | 72 | } |
| 75 | - return true; | ||
| 76 | } | 73 | } |
| 77 | 74 | ||
| 78 | /** | 75 | /** |
| @@ -84,7 +81,7 @@ public class CrmQueryWrapperUtils { | @@ -84,7 +81,7 @@ public class CrmQueryWrapperUtils { | ||
| 84 | * @param userId 用户编号 | 81 | * @param userId 用户编号 |
| 85 | */ | 82 | */ |
| 86 | public static <T extends MPJLambdaWrapper<?>> void appendPermissionCondition(T query, Integer bizType, Collection<Long> bizIds, Long userId) { | 83 | public static <T extends MPJLambdaWrapper<?>> void appendPermissionCondition(T query, Integer bizType, Collection<Long> bizIds, Long userId) { |
| 87 | - if (ObjUtil.equal(validateAdminUser(userId), Boolean.TRUE)) {// 管理员不需要数据权限 | 84 | + if (ObjUtil.equal(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE)) {// 管理员不需要数据权限 |
| 88 | return; | 85 | return; |
| 89 | } | 86 | } |
| 90 | 87 | ||
| @@ -93,38 +90,23 @@ public class CrmQueryWrapperUtils { | @@ -93,38 +90,23 @@ public class CrmQueryWrapperUtils { | ||
| 93 | .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); | 90 | .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); |
| 94 | } | 91 | } |
| 95 | 92 | ||
| 96 | - private static AdminUserApi getAdminUserApi() { | ||
| 97 | - return AdminUserApiHolder.ADMIN_USER_API; | ||
| 98 | - } | ||
| 99 | - | ||
| 100 | /** | 93 | /** |
| 101 | - * 校验用户是否是管理员 | ||
| 102 | - * | ||
| 103 | - * @param userId 用户编号 | ||
| 104 | - * @return 是/否 | ||
| 105 | - */ | ||
| 106 | - private static boolean validateAdminUser(Long userId) { | ||
| 107 | - // TODO 查询权限配置表用户的角色信息 | ||
| 108 | - // TODO @puhui999:查询用户的角色;CRM_ADMIN("crm_admin", "CRM 管理员"), | ||
| 109 | - //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); | ||
| 110 | - //if (permissionConfig == null) { | ||
| 111 | - // return false; | ||
| 112 | - //} | ||
| 113 | - //// 校验是否为管理员 | ||
| 114 | - //if (permissionConfig.getIsAdmin()){ | ||
| 115 | - // return true; | ||
| 116 | - //} | ||
| 117 | - return false; | ||
| 118 | - } | ||
| 119 | - | ||
| 120 | - /** | ||
| 121 | - * 静态内部类实现 AdminUserApi 单例获取 | 94 | + * 静态内部类实现单例获取 |
| 122 | * | 95 | * |
| 123 | * @author HUIHUI | 96 | * @author HUIHUI |
| 124 | */ | 97 | */ |
| 125 | - private static class AdminUserApiHolder { | 98 | + private static class SingletonManager { |
| 126 | 99 | ||
| 127 | private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); | 100 | private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); |
| 101 | + private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); | ||
| 102 | + | ||
| 103 | + public static AdminUserApi getAdminUserApi() { | ||
| 104 | + return ADMIN_USER_API; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { | ||
| 108 | + return MYBATIS_PLUS_JOIN_PROPERTIES; | ||
| 109 | + } | ||
| 128 | 110 | ||
| 129 | } | 111 | } |
| 130 | 112 |
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; | @@ -7,26 +7,33 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 7 | import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO; |
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; |
| 10 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; | ||
| 11 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; | ||
| 12 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; | ||
| 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; | 13 | import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; |
| 14 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; | ||
| 11 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 15 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 12 | import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; | 16 | import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; |
| 13 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; | 17 | import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; |
| 18 | +import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; | ||
| 19 | +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; | ||
| 14 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; | 20 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; |
| 15 | import io.swagger.v3.oas.annotations.Operation; | 21 | import io.swagger.v3.oas.annotations.Operation; |
| 16 | import io.swagger.v3.oas.annotations.Parameter; | 22 | import io.swagger.v3.oas.annotations.Parameter; |
| 17 | import io.swagger.v3.oas.annotations.tags.Tag; | 23 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 24 | +import jakarta.annotation.Resource; | ||
| 18 | import org.springframework.validation.annotation.Validated; | 25 | import org.springframework.validation.annotation.Validated; |
| 19 | import org.springframework.web.bind.annotation.GetMapping; | 26 | import org.springframework.web.bind.annotation.GetMapping; |
| 20 | import org.springframework.web.bind.annotation.RequestMapping; | 27 | import org.springframework.web.bind.annotation.RequestMapping; |
| 21 | import org.springframework.web.bind.annotation.RequestParam; | 28 | import org.springframework.web.bind.annotation.RequestParam; |
| 22 | import org.springframework.web.bind.annotation.RestController; | 29 | import org.springframework.web.bind.annotation.RestController; |
| 23 | 30 | ||
| 24 | -import jakarta.annotation.Resource; | ||
| 25 | import java.time.LocalDateTime; | 31 | import java.time.LocalDateTime; |
| 26 | import java.util.*; | 32 | import java.util.*; |
| 33 | +import java.util.stream.Collectors; | ||
| 27 | 34 | ||
| 28 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 35 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 29 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; | 36 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 30 | 37 | ||
| 31 | @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 | 38 | @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 |
| 32 | @RestController | 39 | @RestController |
| @@ -40,6 +47,10 @@ public class AppActivityController { | @@ -40,6 +47,10 @@ public class AppActivityController { | ||
| 40 | private SeckillActivityService seckillActivityService; | 47 | private SeckillActivityService seckillActivityService; |
| 41 | @Resource | 48 | @Resource |
| 42 | private BargainActivityService bargainActivityService; | 49 | private BargainActivityService bargainActivityService; |
| 50 | + @Resource | ||
| 51 | + private DiscountActivityService discountActivityService; | ||
| 52 | + @Resource | ||
| 53 | + private RewardActivityService rewardActivityService; | ||
| 43 | 54 | ||
| 44 | @GetMapping("/list-by-spu-id") | 55 | @GetMapping("/list-by-spu-id") |
| 45 | @Operation(summary = "获得单个商品,近期参与的每个活动") | 56 | @Operation(summary = "获得单个商品,近期参与的每个活动") |
| @@ -64,45 +75,105 @@ public class AppActivityController { | @@ -64,45 +75,105 @@ public class AppActivityController { | ||
| 64 | if (CollUtil.isEmpty(spuIds)) { | 75 | if (CollUtil.isEmpty(spuIds)) { |
| 65 | return new ArrayList<>(); | 76 | return new ArrayList<>(); |
| 66 | } | 77 | } |
| 78 | + | ||
| 67 | LocalDateTime now = LocalDateTime.now(); | 79 | LocalDateTime now = LocalDateTime.now(); |
| 80 | + // 获取开启的且开始的且没有结束的活动 | ||
| 68 | List<AppActivityRespVO> activityList = new ArrayList<>(); | 81 | List<AppActivityRespVO> activityList = new ArrayList<>(); |
| 82 | + // 1. 拼团活动 | ||
| 83 | + getCombinationActivities(spuIds, now, activityList); | ||
| 84 | + // 2. 秒杀活动 | ||
| 85 | + getSeckillActivities(spuIds, now, activityList); | ||
| 86 | + // 3. 砍价活动 | ||
| 87 | + getBargainActivities(spuIds, now, activityList); | ||
| 88 | + // 4. 限时折扣活动 | ||
| 89 | + getDiscountActivities(spuIds, now, activityList); | ||
| 90 | + // 5. 满减送活动 | ||
| 91 | + getRewardActivities(spuIds, now, activityList); | ||
| 92 | + return activityList; | ||
| 93 | + } | ||
| 69 | 94 | ||
| 70 | - // 1. 拼团活动 - 获取开启的且开始的且没有结束的活动 | 95 | + private void getCombinationActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { |
| 71 | List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( | 96 | List<CombinationActivityDO> combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( |
| 72 | spuIds, CommonStatusEnum.ENABLE.getStatus(), now); | 97 | spuIds, CommonStatusEnum.ENABLE.getStatus(), now); |
| 73 | - if (CollUtil.isNotEmpty(combinationActivities)) { | ||
| 74 | - combinationActivities.forEach(item -> { | ||
| 75 | - activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 76 | - .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) | ||
| 77 | - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 78 | - }); | 98 | + if (CollUtil.isEmpty(combinationActivities)) { |
| 99 | + return; | ||
| 79 | } | 100 | } |
| 80 | 101 | ||
| 81 | - // 2. 秒杀活动 - 获取开启的且开始的且没有结束的活动 | 102 | + combinationActivities.forEach(item -> { |
| 103 | + activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 104 | + .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) | ||
| 105 | + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 106 | + }); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + private void getSeckillActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { | ||
| 82 | List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( | 110 | List<SeckillActivityDO> seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( |
| 83 | spuIds, CommonStatusEnum.ENABLE.getStatus(), now); | 111 | spuIds, CommonStatusEnum.ENABLE.getStatus(), now); |
| 84 | - if (CollUtil.isNotEmpty(seckillActivities)) { | ||
| 85 | - seckillActivities.forEach(item -> { | ||
| 86 | - activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 87 | - .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) | ||
| 88 | - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 89 | - }); | 112 | + if (CollUtil.isEmpty(seckillActivities)) { |
| 113 | + return; | ||
| 90 | } | 114 | } |
| 91 | 115 | ||
| 92 | - // 3. 砍价活动 - 获取开启的且开始的且没有结束的活动 | 116 | + seckillActivities.forEach(item -> { |
| 117 | + activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 118 | + .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) | ||
| 119 | + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 120 | + }); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + private void getBargainActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { | ||
| 93 | List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( | 124 | List<BargainActivityDO> bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( |
| 94 | spuIds, CommonStatusEnum.ENABLE.getStatus(), now); | 125 | spuIds, CommonStatusEnum.ENABLE.getStatus(), now); |
| 95 | if (CollUtil.isNotEmpty(bargainActivities)) { | 126 | if (CollUtil.isNotEmpty(bargainActivities)) { |
| 96 | - bargainActivities.forEach(item -> { | ||
| 97 | - activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 98 | - .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) | ||
| 99 | - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 100 | - }); | 127 | + return; |
| 101 | } | 128 | } |
| 102 | 129 | ||
| 103 | - // TODO 芋艿:满减送活动 | ||
| 104 | - // TODO 芋艿:限时折扣活动 | ||
| 105 | - return activityList; | 130 | + bargainActivities.forEach(item -> { |
| 131 | + activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 132 | + .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) | ||
| 133 | + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 134 | + }); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + private void getDiscountActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { | ||
| 138 | + List<DiscountActivityDO> discountActivities = discountActivityService.getDiscountActivityBySpuIdsAndStatusAndDateTimeLt( | ||
| 139 | + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); | ||
| 140 | + if (CollUtil.isEmpty(discountActivities)) { | ||
| 141 | + return; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + List<DiscountProductDO> products = discountActivityService.getDiscountProductsByActivityId( | ||
| 145 | + convertSet(discountActivities, DiscountActivityDO::getId)); | ||
| 146 | + Map<Long, Long> productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); | ||
| 147 | + discountActivities.forEach(item -> { | ||
| 148 | + activityList.add(new AppActivityRespVO().setId(item.getId()) | ||
| 149 | + .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) | ||
| 150 | + .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | ||
| 151 | + }); | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + private void getRewardActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { | ||
| 155 | + List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt( | ||
| 156 | + spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now); | ||
| 157 | + if (CollUtil.isEmpty(rewardActivityList)) { | ||
| 158 | + return; | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + Map<Long, Optional<RewardActivityDO>> spuIdAndActivityMap = spuIds.stream() | ||
| 162 | + .collect(Collectors.toMap( | ||
| 163 | + spuId -> spuId, | ||
| 164 | + spuId -> rewardActivityList.stream() | ||
| 165 | + .filter(activity -> activity.getProductSpuIds().contains(spuId)) | ||
| 166 | + .max(Comparator.comparing(RewardActivityDO::getCreateTime)))); | ||
| 167 | + for (Long supId : spuIdAndActivityMap.keySet()) { | ||
| 168 | + if (spuIdAndActivityMap.get(supId).isEmpty()) { | ||
| 169 | + continue; | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get(); | ||
| 173 | + activityList.add(new AppActivityRespVO().setId(rewardActivityDO.getId()) | ||
| 174 | + .setType(PromotionTypeEnum.REWARD_ACTIVITY.getType()).setName(rewardActivityDO.getName()) | ||
| 175 | + .setSpuId(supId).setStartTime(rewardActivityDO.getStartTime()).setEndTime(rewardActivityDO.getEndTime())); | ||
| 176 | + } | ||
| 106 | } | 177 | } |
| 107 | 178 | ||
| 108 | } | 179 | } |
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 | @@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc | ||
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | ||
| 10 | +import java.time.LocalDateTime; | ||
| 10 | import java.util.Collection; | 11 | import java.util.Collection; |
| 11 | import java.util.List; | 12 | import java.util.List; |
| 12 | -import java.util.Set; | ||
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * 限时折扣活动 Mapper | 15 | * 限时折扣活动 Mapper |
| @@ -27,4 +27,20 @@ public interface DiscountActivityMapper extends BaseMapperX<DiscountActivityDO> | @@ -27,4 +27,20 @@ public interface DiscountActivityMapper extends BaseMapperX<DiscountActivityDO> | ||
| 27 | .orderByDesc(DiscountActivityDO::getId)); | 27 | .orderByDesc(DiscountActivityDO::getId)); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | + /** | ||
| 31 | + * 获取指定活动编号的活动列表且 | ||
| 32 | + * 开始时间和结束时间小于给定时间 dateTime 的活动列表 | ||
| 33 | + * | ||
| 34 | + * @param ids 活动编号 | ||
| 35 | + * @param dateTime 指定日期 | ||
| 36 | + * @return 活动列表 | ||
| 37 | + */ | ||
| 38 | + default List<DiscountActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) { | ||
| 39 | + return selectList(new LambdaQueryWrapperX<DiscountActivityDO>() | ||
| 40 | + .in(DiscountActivityDO::getId, ids) | ||
| 41 | + .lt(DiscountActivityDO::getStartTime, dateTime) | ||
| 42 | + .gt(DiscountActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 | ||
| 43 | + .orderByDesc(DiscountActivityDO::getCreateTime)); | ||
| 44 | + } | ||
| 45 | + | ||
| 30 | } | 46 | } |
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; | @@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.discount; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; | 4 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 5 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 5 | import org.apache.ibatis.annotations.Mapper; | 6 | import org.apache.ibatis.annotations.Mapper; |
| 6 | import org.apache.ibatis.annotations.Param; | 7 | import org.apache.ibatis.annotations.Param; |
| 7 | 8 | ||
| 8 | import java.util.Collection; | 9 | import java.util.Collection; |
| 9 | import java.util.List; | 10 | import java.util.List; |
| 11 | +import java.util.Map; | ||
| 10 | 12 | ||
| 11 | /** | 13 | /** |
| 12 | * 限时折扣商城 Mapper | 14 | * 限时折扣商城 Mapper |
| @@ -30,4 +32,20 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { | @@ -30,4 +32,20 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { | ||
| 30 | 32 | ||
| 31 | // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 | 33 | // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 |
| 32 | List<DiscountProductDO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds); | 34 | List<DiscountProductDO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds); |
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 | ||
| 38 | + * | ||
| 39 | + * @param spuIds spu 编号 | ||
| 40 | + * @param status 状态 | ||
| 41 | + * @return 包含 spuId 和 activityId 的 map 对象列表 | ||
| 42 | + */ | ||
| 43 | + default List<Map<String, Object>> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | ||
| 44 | + return selectMaps(new QueryWrapper<DiscountProductDO>() | ||
| 45 | + .select("spu_id AS spuId, MAX(DISTINCT(activity_id)) AS activityId") | ||
| 46 | + .in("spu_id", spuIds) | ||
| 47 | + .eq("activity_status", status) | ||
| 48 | + .groupBy("spu_id")); | ||
| 49 | + } | ||
| 50 | + | ||
| 33 | } | 51 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.reward; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.reward; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; |
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 8 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 11 | ||
| 12 | +import java.time.LocalDateTime; | ||
| 10 | import java.util.Collection; | 13 | import java.util.Collection; |
| 11 | import java.util.List; | 14 | import java.util.List; |
| 15 | +import java.util.function.Function; | ||
| 16 | +import java.util.stream.Collectors; | ||
| 12 | 17 | ||
| 13 | /** | 18 | /** |
| 14 | * 满减送活动 Mapper | 19 | * 满减送活动 Mapper |
| @@ -35,4 +40,30 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> { | @@ -35,4 +40,30 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> { | ||
| 35 | .eq(RewardActivityDO::getStatus, status)); | 40 | .eq(RewardActivityDO::getStatus, status)); |
| 36 | } | 41 | } |
| 37 | 42 | ||
| 43 | + default List<RewardActivityDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | ||
| 44 | + Function<Collection<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream() | ||
| 45 | + .map(id -> StrUtil.format("FIND_IN_SET({}, product_spu_ids) ", id)) | ||
| 46 | + .collect(Collectors.joining(" OR ")); | ||
| 47 | + return selectList(new QueryWrapper<RewardActivityDO>() | ||
| 48 | + .eq("status", status) | ||
| 49 | + .apply(productScopeValuesFindInSetFunc.apply(spuIds))); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * 获取指定活动编号的活动列表且 | ||
| 54 | + * 开始时间和结束时间小于给定时间 dateTime 的活动列表 | ||
| 55 | + * | ||
| 56 | + * @param ids 活动编号 | ||
| 57 | + * @param dateTime 指定日期 | ||
| 58 | + * @return 活动列表 | ||
| 59 | + */ | ||
| 60 | + default List<RewardActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) { | ||
| 61 | + return selectList(new LambdaQueryWrapperX<RewardActivityDO>() | ||
| 62 | + .in(RewardActivityDO::getId, ids) | ||
| 63 | + .lt(RewardActivityDO::getStartTime, dateTime) | ||
| 64 | + .gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 | ||
| 65 | + .orderByDesc(RewardActivityDO::getCreateTime) | ||
| 66 | + ); | ||
| 67 | + } | ||
| 68 | + | ||
| 38 | } | 69 | } |
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 | @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc | ||
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; |
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 9 | - | ||
| 10 | import jakarta.validation.Valid; | 9 | import jakarta.validation.Valid; |
| 10 | + | ||
| 11 | +import java.time.LocalDateTime; | ||
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 13 | 14 | ||
| @@ -89,4 +90,14 @@ public interface DiscountActivityService { | @@ -89,4 +90,14 @@ public interface DiscountActivityService { | ||
| 89 | */ | 90 | */ |
| 90 | List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds); | 91 | List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds); |
| 91 | 92 | ||
| 93 | + /** | ||
| 94 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | ||
| 95 | + * | ||
| 96 | + * @param spuIds spu 编号 | ||
| 97 | + * @param status 状态 | ||
| 98 | + * @param dateTime 当前日期时间 | ||
| 99 | + * @return 折扣活动列表 | ||
| 100 | + */ | ||
| 101 | + List<DiscountActivityDO> getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime); | ||
| 102 | + | ||
| 92 | } | 103 | } |
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; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.discount; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.collection.CollectionUtil; | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | +import cn.hutool.core.map.MapUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; | 8 | 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 | @@ -15,16 +16,20 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapp | ||
| 15 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; | 16 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; |
| 16 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; | 17 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; |
| 17 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; | 18 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; |
| 19 | +import jakarta.annotation.Resource; | ||
| 18 | import org.springframework.stereotype.Service; | 20 | import org.springframework.stereotype.Service; |
| 19 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 20 | 22 | ||
| 21 | -import jakarta.annotation.Resource; | 23 | +import java.time.LocalDateTime; |
| 22 | import java.util.Collection; | 24 | import java.util.Collection; |
| 25 | +import java.util.Collections; | ||
| 23 | import java.util.List; | 26 | import java.util.List; |
| 27 | +import java.util.Map; | ||
| 24 | import java.util.stream.Collectors; | 28 | import java.util.stream.Collectors; |
| 25 | 29 | ||
| 26 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 30 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 31 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 32 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 28 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 33 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 29 | 34 | ||
| 30 | /** | 35 | /** |
| @@ -109,7 +114,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | @@ -109,7 +114,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | ||
| 109 | /** | 114 | /** |
| 110 | * 校验商品是否冲突 | 115 | * 校验商品是否冲突 |
| 111 | * | 116 | * |
| 112 | - * @param id 编号 | 117 | + * @param id 编号 |
| 113 | * @param products 商品列表 | 118 | * @param products 商品列表 |
| 114 | */ | 119 | */ |
| 115 | private void validateDiscountActivityProductConflicts(Long id, List<DiscountActivityBaseVO.Product> products) { | 120 | private void validateDiscountActivityProductConflicts(Long id, List<DiscountActivityBaseVO.Product> products) { |
| @@ -184,4 +189,17 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | @@ -184,4 +189,17 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | ||
| 184 | return discountProductMapper.selectList("activity_id", activityIds); | 189 | return discountProductMapper.selectList("activity_id", activityIds); |
| 185 | } | 190 | } |
| 186 | 191 | ||
| 192 | + @Override | ||
| 193 | + public List<DiscountActivityDO> getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) { | ||
| 194 | + // 1. 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 | ||
| 195 | + List<Map<String, Object>> spuIdAndActivityIdMaps = discountProductMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); | ||
| 196 | + if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { | ||
| 197 | + return Collections.emptyList(); | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + // 2. 查询活动详情 | ||
| 201 | + return discountActivityMapper.selectListByIdsAndDateTimeLt( | ||
| 202 | + convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); | ||
| 203 | + } | ||
| 204 | + | ||
| 187 | } | 205 | } |
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 | @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi | ||
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; |
| 7 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; |
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; |
| 9 | - | ||
| 10 | import jakarta.validation.Valid; | 9 | import jakarta.validation.Valid; |
| 10 | + | ||
| 11 | +import java.time.LocalDateTime; | ||
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 13 | 14 | ||
| @@ -71,4 +72,14 @@ public interface RewardActivityService { | @@ -71,4 +72,14 @@ public interface RewardActivityService { | ||
| 71 | */ | 72 | */ |
| 72 | List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds); | 73 | List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds); |
| 73 | 74 | ||
| 75 | + /** | ||
| 76 | + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 | ||
| 77 | + * | ||
| 78 | + * @param spuIds spu 编号 | ||
| 79 | + * @param status 状态 | ||
| 80 | + * @param dateTime 当前日期时间 | ||
| 81 | + * @return 满减送活动列表 | ||
| 82 | + */ | ||
| 83 | + List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime); | ||
| 84 | + | ||
| 74 | } | 85 | } |
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; | @@ -11,14 +11,17 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; | ||
| 11 | import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; | 11 | import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; |
| 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; | 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; |
| 13 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; | 13 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; |
| 14 | +import jakarta.annotation.Resource; | ||
| 14 | import org.springframework.stereotype.Service; | 15 | import org.springframework.stereotype.Service; |
| 15 | import org.springframework.validation.annotation.Validated; | 16 | import org.springframework.validation.annotation.Validated; |
| 16 | 17 | ||
| 17 | -import jakarta.annotation.Resource; | 18 | +import java.time.LocalDateTime; |
| 18 | import java.util.Collection; | 19 | import java.util.Collection; |
| 20 | +import java.util.Collections; | ||
| 19 | import java.util.List; | 21 | import java.util.List; |
| 20 | 22 | ||
| 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | ||
| 22 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 25 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 23 | import static java.util.Arrays.asList; | 26 | import static java.util.Arrays.asList; |
| 24 | 27 | ||
| @@ -100,10 +103,11 @@ public class RewardActivityServiceImpl implements RewardActivityService { | @@ -100,10 +103,11 @@ public class RewardActivityServiceImpl implements RewardActivityService { | ||
| 100 | } | 103 | } |
| 101 | 104 | ||
| 102 | // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; | 105 | // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; |
| 106 | + | ||
| 103 | /** | 107 | /** |
| 104 | * 校验商品参加的活动是否冲突 | 108 | * 校验商品参加的活动是否冲突 |
| 105 | * | 109 | * |
| 106 | - * @param id 活动编号 | 110 | + * @param id 活动编号 |
| 107 | * @param spuIds 商品 SPU 编号数组 | 111 | * @param spuIds 商品 SPU 编号数组 |
| 108 | */ | 112 | */ |
| 109 | private void validateRewardActivitySpuConflicts(Long id, Collection<Long> spuIds) { | 113 | private void validateRewardActivitySpuConflicts(Long id, Collection<Long> spuIds) { |
| @@ -125,7 +129,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { | @@ -125,7 +129,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { | ||
| 125 | /** | 129 | /** |
| 126 | * 获得商品参加的满减送活动的数组 | 130 | * 获得商品参加的满减送活动的数组 |
| 127 | * | 131 | * |
| 128 | - * @param spuIds 商品 SPU 编号数组 | 132 | + * @param spuIds 商品 SPU 编号数组 |
| 129 | * @param statuses 活动状态数组 | 133 | * @param statuses 活动状态数组 |
| 130 | * @return 商品参加的满减送活动的数组 | 134 | * @return 商品参加的满减送活动的数组 |
| 131 | */ | 135 | */ |
| @@ -163,4 +167,16 @@ public class RewardActivityServiceImpl implements RewardActivityService { | @@ -163,4 +167,16 @@ public class RewardActivityServiceImpl implements RewardActivityService { | ||
| 163 | return null; | 167 | return null; |
| 164 | } | 168 | } |
| 165 | 169 | ||
| 170 | + @Override | ||
| 171 | + public List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) { | ||
| 172 | + // 1. 查询出指定 spuId 的 spu 参加的活动 | ||
| 173 | + List<RewardActivityDO> rewardActivityList = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, status); | ||
| 174 | + if (CollUtil.isEmpty(rewardActivityList)) { | ||
| 175 | + return Collections.emptyList(); | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + // 2. 查询活动详情 | ||
| 179 | + return rewardActivityMapper.selectListByIdsAndDateTimeLt(convertSet(rewardActivityList, RewardActivityDO::getId), dateTime); | ||
| 180 | + } | ||
| 181 | + | ||
| 166 | } | 182 | } |
yudao-module-system/yudao-module-system-api/pom.xml
| @@ -22,32 +22,12 @@ | @@ -22,32 +22,12 @@ | ||
| 22 | <artifactId>yudao-common</artifactId> | 22 | <artifactId>yudao-common</artifactId> |
| 23 | </dependency> | 23 | </dependency> |
| 24 | 24 | ||
| 25 | - <!-- TODO @puhui999 & 芋艿:操作日志,要不要这么引入? --> | ||
| 26 | - <!-- Springboot-注解-通用操作日志组件 --> | ||
| 27 | - <!-- 此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 --> | ||
| 28 | - <dependency> | ||
| 29 | - <groupId>io.github.mouzt</groupId> | ||
| 30 | - <artifactId>bizlog-sdk</artifactId> | ||
| 31 | - </dependency> | ||
| 32 | - | ||
| 33 | - <!-- TODO @puhui999 & 芋艿:要不要移除掉 --> | ||
| 34 | - <!--工具类相关--> | ||
| 35 | - <dependency> | ||
| 36 | - <groupId>com.fasterxml.jackson.core</groupId> | ||
| 37 | - <artifactId>jackson-databind</artifactId> | ||
| 38 | - </dependency> | ||
| 39 | - <dependency> | ||
| 40 | - <groupId>com.fasterxml.jackson.core</groupId> | ||
| 41 | - <artifactId>jackson-core</artifactId> | ||
| 42 | - </dependency> | ||
| 43 | - | ||
| 44 | <!-- 参数校验 --> | 25 | <!-- 参数校验 --> |
| 45 | <dependency> | 26 | <dependency> |
| 46 | <groupId>org.springframework.boot</groupId> | 27 | <groupId>org.springframework.boot</groupId> |
| 47 | <artifactId>spring-boot-starter-validation</artifactId> | 28 | <artifactId>spring-boot-starter-validation</artifactId> |
| 48 | <optional>true</optional> | 29 | <optional>true</optional> |
| 49 | </dependency> | 30 | </dependency> |
| 50 | - | ||
| 51 | </dependencies> | 31 | </dependencies> |
| 52 | 32 | ||
| 53 | </project> | 33 | </project> |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java
| 1 | package cn.iocoder.yudao.module.system.api.logger; | 1 | package cn.iocoder.yudao.module.system.api.logger; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 5 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; | ||
| 6 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | ||
| 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | 7 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; |
| 5 | import jakarta.validation.Valid; | 8 | import jakarta.validation.Valid; |
| 6 | 9 | ||
| 7 | -import java.util.List; | ||
| 8 | - | ||
| 9 | /** | 10 | /** |
| 10 | * 操作日志 API 接口 | 11 | * 操作日志 API 接口 |
| 11 | * | 12 | * |
| @@ -21,12 +22,18 @@ public interface OperateLogApi { | @@ -21,12 +22,18 @@ public interface OperateLogApi { | ||
| 21 | void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); | 22 | void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); |
| 22 | 23 | ||
| 23 | /** | 24 | /** |
| 24 | - * 获取指定模块的指定数据的操作日志 | 25 | + * 创建操作日志 |
| 26 | + * | ||
| 27 | + * @param createReqDTO 请求 | ||
| 28 | + */ | ||
| 29 | + void createOperateLogV2(@Valid OperateLogV2CreateReqDTO createReqDTO); | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 获取指定模块的指定数据的操作日志分页 | ||
| 25 | * | 33 | * |
| 26 | - * @param module 操作模块 | ||
| 27 | - * @param bizId 操作模块编号 | ||
| 28 | - * @return 操作日志 | 34 | + * @param pageReqVO 请求 |
| 35 | + * @return 操作日志分页 | ||
| 29 | */ | 36 | */ |
| 30 | - List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId); | 37 | + PageResult<OperateLogV2RespDTO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO); |
| 31 | 38 | ||
| 32 | } | 39 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java renamed to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java
| 1 | -package cn.iocoder.yudao.module.system.service.logger.bo; | 1 | +package cn.iocoder.yudao.module.system.api.logger.dto; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | import jakarta.validation.constraints.NotEmpty; | 4 | import jakarta.validation.constraints.NotEmpty; |
| 5 | +import jakarta.validation.constraints.NotNull; | ||
| 5 | import lombok.Data; | 6 | import lombok.Data; |
| 6 | 7 | ||
| 8 | +import java.time.LocalDateTime; | ||
| 9 | +import java.util.Map; | ||
| 10 | + | ||
| 7 | /** | 11 | /** |
| 8 | * 系统操作日志 Create Req BO | 12 | * 系统操作日志 Create Req BO |
| 9 | * | 13 | * |
| 10 | * @author HUIHUI | 14 | * @author HUIHUI |
| 11 | */ | 15 | */ |
| 12 | @Data | 16 | @Data |
| 13 | -public class OperateLogV2CreateReqBO { | 17 | +public class OperateLogV2CreateReqDTO { |
| 14 | 18 | ||
| 15 | /** | 19 | /** |
| 16 | * 链路追踪编号 | 20 | * 链路追踪编号 |
| @@ -23,29 +27,29 @@ public class OperateLogV2CreateReqBO { | @@ -23,29 +27,29 @@ public class OperateLogV2CreateReqBO { | ||
| 23 | * | 27 | * |
| 24 | * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 | 28 | * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 |
| 25 | */ | 29 | */ |
| 26 | - @NotEmpty(message = "用户编号不能为空") | 30 | + @NotNull(message = "用户编号不能为空") |
| 27 | private Long userId; | 31 | private Long userId; |
| 28 | /** | 32 | /** |
| 29 | * 用户类型 | 33 | * 用户类型 |
| 30 | * | 34 | * |
| 31 | * 关联 {@link UserTypeEnum} | 35 | * 关联 {@link UserTypeEnum} |
| 32 | */ | 36 | */ |
| 33 | - @NotEmpty(message = "用户类型不能为空") | 37 | + @NotNull(message = "用户类型不能为空") |
| 34 | private Integer userType; | 38 | private Integer userType; |
| 35 | /** | 39 | /** |
| 36 | - * 操作模块 | 40 | + * 操作模块类型 |
| 37 | */ | 41 | */ |
| 38 | - @NotEmpty(message = "操作模块不能为空") | ||
| 39 | - private String module; | 42 | + @NotEmpty(message = "操作模块类型不能为空") |
| 43 | + private String type; | ||
| 40 | /** | 44 | /** |
| 41 | * 操作名 | 45 | * 操作名 |
| 42 | */ | 46 | */ |
| 43 | @NotEmpty(message = "操作名不能为空") | 47 | @NotEmpty(message = "操作名不能为空") |
| 44 | - private String name; | 48 | + private String subType; |
| 45 | /** | 49 | /** |
| 46 | * 操作模块业务编号 | 50 | * 操作模块业务编号 |
| 47 | */ | 51 | */ |
| 48 | - @NotEmpty(message = "操作模块业务编号不能为空") | 52 | + @NotNull(message = "操作模块业务编号不能为空") |
| 49 | private Long bizId; | 53 | private Long bizId; |
| 50 | /** | 54 | /** |
| 51 | * 操作内容,记录整个操作的明细 | 55 | * 操作内容,记录整个操作的明细 |
| @@ -57,7 +61,7 @@ public class OperateLogV2CreateReqBO { | @@ -57,7 +61,7 @@ public class OperateLogV2CreateReqBO { | ||
| 57 | * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) | 61 | * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) |
| 58 | * 例如说,记录订单编号,{ orderId: "1"} | 62 | * 例如说,记录订单编号,{ orderId: "1"} |
| 59 | */ | 63 | */ |
| 60 | - private String extra; | 64 | + private Map<String, Object> extra; |
| 61 | 65 | ||
| 62 | /** | 66 | /** |
| 63 | * 请求方法名 | 67 | * 请求方法名 |
| @@ -80,4 +84,38 @@ public class OperateLogV2CreateReqBO { | @@ -80,4 +84,38 @@ public class OperateLogV2CreateReqBO { | ||
| 80 | @NotEmpty(message = "浏览器 UA 不能为空") | 84 | @NotEmpty(message = "浏览器 UA 不能为空") |
| 81 | private String userAgent; | 85 | private String userAgent; |
| 82 | 86 | ||
| 87 | + /** | ||
| 88 | + * Java 方法名 | ||
| 89 | + */ | ||
| 90 | + private String javaMethod; | ||
| 91 | + /** | ||
| 92 | + * Java 方法的参数 | ||
| 93 | + */ | ||
| 94 | + private String javaMethodArgs; | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * 开始时间 | ||
| 98 | + */ | ||
| 99 | + private LocalDateTime startTime; | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 执行时长,单位:毫秒 | ||
| 103 | + */ | ||
| 104 | + private Integer duration; | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 结果码 | ||
| 108 | + */ | ||
| 109 | + private Integer resultCode; | ||
| 110 | + | ||
| 111 | + /** | ||
| 112 | + * 结果提示 | ||
| 113 | + */ | ||
| 114 | + private String resultMsg; | ||
| 115 | + | ||
| 116 | + /** | ||
| 117 | + * 结果数据 | ||
| 118 | + */ | ||
| 119 | + private String resultData; | ||
| 120 | + | ||
| 83 | } | 121 | } |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.logger.dto; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 操作日志分页 Request DTO | ||
| 8 | + * | ||
| 9 | + * @author HUIHUI | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class OperateLogV2PageReqDTO extends PageParam { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 模块类型 | ||
| 16 | + */ | ||
| 17 | + private String bizType; | ||
| 18 | + /** | ||
| 19 | + * 模块数据编号 | ||
| 20 | + */ | ||
| 21 | + private Long bizId; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 用户编号 | ||
| 25 | + */ | ||
| 26 | + private Long userId; | ||
| 27 | + | ||
| 28 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java
| 1 | package cn.iocoder.yudao.module.system.api.logger.dto; | 1 | package cn.iocoder.yudao.module.system.api.logger.dto; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 4 | -import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 5 | import lombok.Data; | 3 | import lombok.Data; |
| 6 | 4 | ||
| 7 | import java.time.LocalDateTime; | 5 | import java.time.LocalDateTime; |
| 8 | - | ||
| 9 | -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 10 | -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; | 6 | +import java.util.Map; |
| 11 | 7 | ||
| 12 | /** | 8 | /** |
| 13 | * 系统操作日志 Resp DTO | 9 | * 系统操作日志 Resp DTO |
| @@ -26,17 +22,21 @@ public class OperateLogV2RespDTO { | @@ -26,17 +22,21 @@ public class OperateLogV2RespDTO { | ||
| 26 | */ | 22 | */ |
| 27 | private Long userId; | 23 | private Long userId; |
| 28 | /** | 24 | /** |
| 25 | + * 用户名称 | ||
| 26 | + */ | ||
| 27 | + private String userName; | ||
| 28 | + /** | ||
| 29 | * 用户类型 | 29 | * 用户类型 |
| 30 | */ | 30 | */ |
| 31 | private Integer userType; | 31 | private Integer userType; |
| 32 | /** | 32 | /** |
| 33 | - * 操作模块 | 33 | + * 操作模块类型 |
| 34 | */ | 34 | */ |
| 35 | - private String module; | 35 | + private String type; |
| 36 | /** | 36 | /** |
| 37 | * 操作名 | 37 | * 操作名 |
| 38 | */ | 38 | */ |
| 39 | - private String name; | 39 | + private String subType; |
| 40 | /** | 40 | /** |
| 41 | * 操作模块业务编号 | 41 | * 操作模块业务编号 |
| 42 | */ | 42 | */ |
| @@ -48,7 +48,7 @@ public class OperateLogV2RespDTO { | @@ -48,7 +48,7 @@ public class OperateLogV2RespDTO { | ||
| 48 | /** | 48 | /** |
| 49 | * 拓展字段 | 49 | * 拓展字段 |
| 50 | */ | 50 | */ |
| 51 | - private String extra; | 51 | + private Map<String, Object> extra; |
| 52 | 52 | ||
| 53 | /** | 53 | /** |
| 54 | * 请求方法名 | 54 | * 请求方法名 |
| @@ -68,20 +68,42 @@ public class OperateLogV2RespDTO { | @@ -68,20 +68,42 @@ public class OperateLogV2RespDTO { | ||
| 68 | private String userAgent; | 68 | private String userAgent; |
| 69 | 69 | ||
| 70 | /** | 70 | /** |
| 71 | - * 创建时间 | 71 | + * Java 方法名 |
| 72 | */ | 72 | */ |
| 73 | - // TODO puhui999: 木得效果怎么肥事 | ||
| 74 | - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) | ||
| 75 | - private LocalDateTime createTime; | 73 | + private String javaMethod; |
| 74 | + /** | ||
| 75 | + * Java 方法的参数 | ||
| 76 | + */ | ||
| 77 | + private String javaMethodArgs; | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 开始时间 | ||
| 81 | + */ | ||
| 82 | + private LocalDateTime startTime; | ||
| 83 | + | ||
| 84 | + /** | ||
| 85 | + * 执行时长,单位:毫秒 | ||
| 86 | + */ | ||
| 87 | + private Integer duration; | ||
| 88 | + | ||
| 89 | + /** | ||
| 90 | + * 结果码 | ||
| 91 | + */ | ||
| 92 | + private Integer resultCode; | ||
| 76 | 93 | ||
| 77 | - // TODO @puhui999:下面 2 个字段不用返回;用 userId 哈;返回一个 userName | ||
| 78 | /** | 94 | /** |
| 79 | - * 创建者 | 95 | + * 结果提示 |
| 80 | */ | 96 | */ |
| 81 | - private String creator; | 97 | + private String resultMsg; |
| 98 | + | ||
| 82 | /** | 99 | /** |
| 83 | - * 创建者名称 | 100 | + * 结果数据 |
| 84 | */ | 101 | */ |
| 85 | - private String creatorName; | 102 | + private String resultData; |
| 103 | + | ||
| 104 | + /** | ||
| 105 | + * 创建时间 | ||
| 106 | + */ | ||
| 107 | + private LocalDateTime createTime; | ||
| 86 | 108 | ||
| 87 | } | 109 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
| 1 | package cn.iocoder.yudao.module.system.api.logger; | 1 | package cn.iocoder.yudao.module.system.api.logger; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 6 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 7 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; | ||
| 8 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | ||
| 6 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | 9 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; |
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | 11 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 9 | import cn.iocoder.yudao.module.system.service.logger.OperateLogService; | 12 | import cn.iocoder.yudao.module.system.service.logger.OperateLogService; |
| 10 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; | 13 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 11 | import jakarta.annotation.Resource; | 14 | import jakarta.annotation.Resource; |
| 15 | +import org.springframework.scheduling.annotation.Async; | ||
| 12 | import org.springframework.stereotype.Service; | 16 | import org.springframework.stereotype.Service; |
| 13 | import org.springframework.validation.annotation.Validated; | 17 | import org.springframework.validation.annotation.Validated; |
| 14 | 18 | ||
| 15 | -import java.util.Collections; | ||
| 16 | import java.util.List; | 19 | import java.util.List; |
| 17 | import java.util.Map; | 20 | import java.util.Map; |
| 18 | 21 | ||
| @@ -39,21 +42,31 @@ public class OperateLogApiImpl implements OperateLogApi { | @@ -39,21 +42,31 @@ public class OperateLogApiImpl implements OperateLogApi { | ||
| 39 | } | 42 | } |
| 40 | 43 | ||
| 41 | @Override | 44 | @Override |
| 42 | - public List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId) { | ||
| 43 | - List<OperateLogV2DO> logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId); | ||
| 44 | - if (CollUtil.isEmpty(logList)) { | ||
| 45 | - return Collections.emptyList(); | 45 | + @Async |
| 46 | + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO) { | ||
| 47 | + operateLogService.createOperateLogV2(createReqDTO); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + @Override | ||
| 51 | + public PageResult<OperateLogV2RespDTO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { | ||
| 52 | + PageResult<OperateLogV2DO> operateLogPage = operateLogService.getOperateLogPage(pageReqVO); | ||
| 53 | + if (CollUtil.isEmpty(operateLogPage.getList())) { | ||
| 54 | + return PageResult.empty(); | ||
| 46 | } | 55 | } |
| 47 | 56 | ||
| 48 | // 获取用户 | 57 | // 获取用户 |
| 49 | - List<AdminUserDO> userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator()))); | 58 | + List<AdminUserDO> userList = adminUserService.getUserList(convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId)); |
| 59 | + return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + private static List<OperateLogV2RespDTO> setUserInfo(List<OperateLogV2DO> logList, List<AdminUserDO> userList) { | ||
| 50 | Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId); | 63 | Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId); |
| 51 | return convertList(logList, item -> { | 64 | return convertList(logList, item -> { |
| 52 | - OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class); | ||
| 53 | - findAndThen(userMap, Long.parseLong(item.getCreator()), user -> { | ||
| 54 | - bean.setCreatorName(user.getNickname()); | 65 | + OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); |
| 66 | + findAndThen(userMap, item.getUserId(), user -> { | ||
| 67 | + respDTO.setUserName(user.getNickname()); | ||
| 55 | }); | 68 | }); |
| 56 | - return bean; | 69 | + return respDTO; |
| 57 | }); | 70 | }); |
| 58 | } | 71 | } |
| 59 | 72 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java
| 1 | package cn.iocoder.yudao.module.system.dal.dataobject.logger; | 1 | package cn.iocoder.yudao.module.system.dal.dataobject.logger; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 5 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | import com.baomidou.mybatisplus.annotation.KeySequence; | 6 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 7 | +import com.baomidou.mybatisplus.annotation.TableField; | ||
| 6 | import com.baomidou.mybatisplus.annotation.TableId; | 8 | import com.baomidou.mybatisplus.annotation.TableId; |
| 7 | import com.baomidou.mybatisplus.annotation.TableName; | 9 | import com.baomidou.mybatisplus.annotation.TableName; |
| 10 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | ||
| 8 | import lombok.Data; | 11 | import lombok.Data; |
| 9 | import lombok.EqualsAndHashCode; | 12 | import lombok.EqualsAndHashCode; |
| 10 | 13 | ||
| 14 | +import java.time.LocalDateTime; | ||
| 15 | +import java.util.Map; | ||
| 16 | + | ||
| 11 | /** | 17 | /** |
| 12 | * 操作日志表 V2 | 18 | * 操作日志表 V2 |
| 13 | * | 19 | * |
| @@ -20,6 +26,16 @@ import lombok.EqualsAndHashCode; | @@ -20,6 +26,16 @@ import lombok.EqualsAndHashCode; | ||
| 20 | public class OperateLogV2DO extends BaseDO { | 26 | public class OperateLogV2DO extends BaseDO { |
| 21 | 27 | ||
| 22 | /** | 28 | /** |
| 29 | + * {@link #javaMethodArgs} 的最大长度 | ||
| 30 | + */ | ||
| 31 | + public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 8000; | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * {@link #resultData} 的最大长度 | ||
| 35 | + */ | ||
| 36 | + public static final Integer RESULT_MAX_LENGTH = 4000; | ||
| 37 | + | ||
| 38 | + /** | ||
| 23 | * 日志主键 | 39 | * 日志主键 |
| 24 | */ | 40 | */ |
| 25 | @TableId | 41 | @TableId |
| @@ -42,15 +58,14 @@ public class OperateLogV2DO extends BaseDO { | @@ -42,15 +58,14 @@ public class OperateLogV2DO extends BaseDO { | ||
| 42 | * 关联 {@link UserTypeEnum} | 58 | * 关联 {@link UserTypeEnum} |
| 43 | */ | 59 | */ |
| 44 | private Integer userType; | 60 | private Integer userType; |
| 45 | - // TODO @puhui999:module 改成 type,name 改成 subType; | ||
| 46 | /** | 61 | /** |
| 47 | - * 操作模块 | 62 | + * 操作模块类型 |
| 48 | */ | 63 | */ |
| 49 | - private String module; | 64 | + private String type; |
| 50 | /** | 65 | /** |
| 51 | * 操作名 | 66 | * 操作名 |
| 52 | */ | 67 | */ |
| 53 | - private String name; | 68 | + private String subType; |
| 54 | /** | 69 | /** |
| 55 | * 操作模块业务编号 | 70 | * 操作模块业务编号 |
| 56 | */ | 71 | */ |
| @@ -66,8 +81,8 @@ public class OperateLogV2DO extends BaseDO { | @@ -66,8 +81,8 @@ public class OperateLogV2DO extends BaseDO { | ||
| 66 | * | 81 | * |
| 67 | * 例如说,记录订单编号,{ orderId: "1"} | 82 | * 例如说,记录订单编号,{ orderId: "1"} |
| 68 | */ | 83 | */ |
| 69 | - // TODO @puhui999:看看能不能类似 exts 搞 json 格式; | ||
| 70 | - private String extra; | 84 | + @TableField(typeHandler = JacksonTypeHandler.class) |
| 85 | + private Map<String, Object> extra; | ||
| 71 | /** | 86 | /** |
| 72 | * 请求方法名 | 87 | * 请求方法名 |
| 73 | */ | 88 | */ |
| @@ -85,9 +100,43 @@ public class OperateLogV2DO extends BaseDO { | @@ -85,9 +100,43 @@ public class OperateLogV2DO extends BaseDO { | ||
| 85 | */ | 100 | */ |
| 86 | private String userAgent; | 101 | private String userAgent; |
| 87 | 102 | ||
| 88 | - // TODO @芋艿:requestUrl、requestMethod | ||
| 89 | - // TODO @芋艿:javaMethod、javaMethodArgs | ||
| 90 | - // TODO @芋艿:startTime、duration | ||
| 91 | - // TODO @芋艿:resultMsg、resultData | 103 | + /** |
| 104 | + * Java 方法名 | ||
| 105 | + */ | ||
| 106 | + private String javaMethod; | ||
| 107 | + /** | ||
| 108 | + * Java 方法的参数 | ||
| 109 | + * | ||
| 110 | + * 实际格式为 Map<String, Object> | ||
| 111 | + * 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败 | ||
| 112 | + * 其中,key 为参数名,value 为参数值 | ||
| 113 | + */ | ||
| 114 | + private String javaMethodArgs; | ||
| 115 | + /** | ||
| 116 | + * 开始时间 | ||
| 117 | + */ | ||
| 118 | + private LocalDateTime startTime; | ||
| 119 | + /** | ||
| 120 | + * 执行时长,单位:毫秒 | ||
| 121 | + */ | ||
| 122 | + private Integer duration; | ||
| 123 | + /** | ||
| 124 | + * 结果码 | ||
| 125 | + * | ||
| 126 | + * 目前使用的 {@link CommonResult#getCode()} 属性 | ||
| 127 | + */ | ||
| 128 | + private Integer resultCode; | ||
| 129 | + /** | ||
| 130 | + * 结果提示 | ||
| 131 | + * | ||
| 132 | + * 目前使用的 {@link CommonResult#getMsg()} 属性 | ||
| 133 | + */ | ||
| 134 | + private String resultMsg; | ||
| 135 | + /** | ||
| 136 | + * 结果数据 | ||
| 137 | + * | ||
| 138 | + * 如果是对象,则使用 JSON 格式化 | ||
| 139 | + */ | ||
| 140 | + private String resultData; | ||
| 92 | 141 | ||
| 93 | } | 142 | } |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java
| @@ -3,28 +3,18 @@ package cn.iocoder.yudao.module.system.dal.mysql.logger; | @@ -3,28 +3,18 @@ package cn.iocoder.yudao.module.system.dal.mysql.logger; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 6 | -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; | 6 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | ||
| 10 | -import java.util.Collection; | ||
| 11 | -import java.util.List; | ||
| 12 | - | ||
| 13 | @Mapper | 10 | @Mapper |
| 14 | public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> { | 11 | public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> { |
| 15 | 12 | ||
| 16 | - default PageResult<OperateLogV2DO> selectPage(OperateLogPageReqVO reqVO, Collection<Long> userIds) { | ||
| 17 | - LambdaQueryWrapperX<OperateLogV2DO> query = new LambdaQueryWrapperX<OperateLogV2DO>() | ||
| 18 | - .likeIfPresent(OperateLogV2DO::getModule, reqVO.getModule()) | ||
| 19 | - .inIfPresent(OperateLogV2DO::getUserId, userIds); | ||
| 20 | - query.orderByDesc(OperateLogV2DO::getId); // 降序 | ||
| 21 | - return selectPage(reqVO, query); | ||
| 22 | - } | ||
| 23 | - | ||
| 24 | - default List<OperateLogV2DO> selectListByModuleAndBizId(String module, Long bizId) { | ||
| 25 | - return selectList(new LambdaQueryWrapperX<OperateLogV2DO>() | ||
| 26 | - .eq(OperateLogV2DO::getModule, module) | ||
| 27 | - .eq(OperateLogV2DO::getBizId, bizId) | 13 | + default PageResult<OperateLogV2DO> selectPage(OperateLogV2PageReqDTO pageReqVO) { |
| 14 | + return selectPage(pageReqVO, new LambdaQueryWrapperX<OperateLogV2DO>() | ||
| 15 | + .eqIfPresent(OperateLogV2DO::getType, pageReqVO.getBizType()) | ||
| 16 | + .eqIfPresent(OperateLogV2DO::getBizId, pageReqVO.getBizId()) | ||
| 17 | + .eqIfPresent(OperateLogV2DO::getUserId, pageReqVO.getUserId()) | ||
| 28 | .orderByDesc(OperateLogV2DO::getCreateTime)); | 18 | .orderByDesc(OperateLogV2DO::getCreateTime)); |
| 29 | } | 19 | } |
| 30 | 20 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java deleted
| 1 | -package cn.iocoder.yudao.module.system.framework.bizlog.config; | ||
| 2 | - | ||
| 3 | -import com.mzt.logapi.starter.annotation.EnableLogRecord; | ||
| 4 | -import org.springframework.context.annotation.Configuration; | ||
| 5 | - | ||
| 6 | -// TODO @puhui999:挪到 yudao-spring-boot-starter-biz-operatelog 下,搞个 cn.iocoder.yudao.framework.operatelogv2;跑通后,我们直接就删除老的实现了; | ||
| 7 | -/** | ||
| 8 | - * mzt-biz-log 配置类 | ||
| 9 | - * | ||
| 10 | - * @author HUIHUI | ||
| 11 | - */ | ||
| 12 | -@Configuration(proxyBeanMethods = false) | ||
| 13 | -@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 | ||
| 14 | -public class YudaoOperateLogV2Configuration { | ||
| 15 | - | ||
| 16 | -} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java deleted
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java deleted
| 1 | -package cn.iocoder.yudao.module.system.framework.bizlog.service; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | ||
| 4 | -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | ||
| 5 | -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||
| 6 | -import cn.iocoder.yudao.module.system.service.logger.OperateLogService; | ||
| 7 | -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; | ||
| 8 | -import com.mzt.logapi.beans.LogRecord; | ||
| 9 | -import com.mzt.logapi.service.ILogRecordService; | ||
| 10 | -import jakarta.annotation.Resource; | ||
| 11 | -import jakarta.servlet.http.HttpServletRequest; | ||
| 12 | -import lombok.extern.slf4j.Slf4j; | ||
| 13 | -import org.springframework.stereotype.Service; | ||
| 14 | - | ||
| 15 | -import java.util.Collections; | ||
| 16 | -import java.util.List; | ||
| 17 | - | ||
| 18 | -// TODO @puhui999:这个应该搞到 operatelog 组件里哈; | ||
| 19 | -/** | ||
| 20 | - * 操作日志 ILogRecordService 实现类 | ||
| 21 | - * | ||
| 22 | - * 基于 {@link OperateLogService} 实现,记录操作日志 | ||
| 23 | - * | ||
| 24 | - * @author HUIHUI | ||
| 25 | - */ | ||
| 26 | -@Slf4j | ||
| 27 | -@Service | ||
| 28 | -public class ILogRecordServiceImpl implements ILogRecordService { | ||
| 29 | - | ||
| 30 | - @Resource | ||
| 31 | - private OperateLogService operateLogService; | ||
| 32 | - | ||
| 33 | - @Override | ||
| 34 | - public void record(LogRecord logRecord) { | ||
| 35 | - OperateLogV2CreateReqBO reqBO = new OperateLogV2CreateReqBO(); | ||
| 36 | - // 补全通用字段 | ||
| 37 | - reqBO.setTraceId(TracerUtils.getTraceId()); | ||
| 38 | - // 补充用户信息 | ||
| 39 | - fillUserFields(reqBO); | ||
| 40 | - // 补全模块信息 | ||
| 41 | - fillModuleFields(reqBO, logRecord); | ||
| 42 | - // 补全请求信息 | ||
| 43 | - fillRequestFields(reqBO); | ||
| 44 | - // 异步记录日志 | ||
| 45 | - operateLogService.createOperateLogV2(reqBO); | ||
| 46 | - log.info("操作日志 ===> {}", reqBO); | ||
| 47 | - } | ||
| 48 | - | ||
| 49 | - private static void fillUserFields(OperateLogV2CreateReqBO reqBO) { | ||
| 50 | - reqBO.setUserId(WebFrameworkUtils.getLoginUserId()); | ||
| 51 | - reqBO.setUserType(WebFrameworkUtils.getLoginUserType()); | ||
| 52 | - } | ||
| 53 | - | ||
| 54 | - public static void fillModuleFields(OperateLogV2CreateReqBO reqBO, LogRecord logRecord) { | ||
| 55 | - reqBO.setModule(logRecord.getType()); // 大模块类型如 crm-客户 | ||
| 56 | - reqBO.setName(logRecord.getSubType());// 操作名称如 转移客户 | ||
| 57 | - reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 | ||
| 58 | - reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 | ||
| 59 | - reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - private static void fillRequestFields(OperateLogV2CreateReqBO reqBO) { | ||
| 63 | - // 获得 Request 对象 | ||
| 64 | - HttpServletRequest request = ServletUtils.getRequest(); | ||
| 65 | - if (request == null) { | ||
| 66 | - return; | ||
| 67 | - } | ||
| 68 | - // 补全请求信息 | ||
| 69 | - reqBO.setRequestMethod(request.getMethod()); | ||
| 70 | - reqBO.setRequestUrl(request.getRequestURI()); | ||
| 71 | - reqBO.setUserIp(ServletUtils.getClientIP(request)); | ||
| 72 | - reqBO.setUserAgent(ServletUtils.getUserAgent(request)); | ||
| 73 | - } | ||
| 74 | - | ||
| 75 | - @Override | ||
| 76 | - public List<LogRecord> queryLog(String bizNo, String type) { | ||
| 77 | - return Collections.emptyList(); | ||
| 78 | - } | ||
| 79 | - | ||
| 80 | - @Override | ||
| 81 | - public List<LogRecord> queryLogByBizNo(String bizNo, String type, String subType) { | ||
| 82 | - return Collections.emptyList(); | ||
| 83 | - } | ||
| 84 | - | ||
| 85 | -} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java
0 → 100644
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java renamed to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java renamed to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java
| 1 | -package cn.iocoder.yudao.module.system.framework.bizlog.function; | 1 | +package cn.iocoder.yudao.module.system.framework.operatelog.parse; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.util.StrUtil; | 3 | import cn.hutool.core.util.StrUtil; |
| 4 | import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; | 4 | import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; |
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; | @@ -2,12 +2,11 @@ package cn.iocoder.yudao.module.system.service.logger; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 4 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 5 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; | ||
| 6 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | ||
| 5 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; | 7 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; |
| 6 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; |
| 8 | -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; | ||
| 9 | - | ||
| 10 | -import java.util.List; | ||
| 11 | 10 | ||
| 12 | /** | 11 | /** |
| 13 | * 操作日志 Service 接口 | 12 | * 操作日志 Service 接口 |
| @@ -38,16 +37,14 @@ public interface OperateLogService { | @@ -38,16 +37,14 @@ public interface OperateLogService { | ||
| 38 | * | 37 | * |
| 39 | * @param createReqBO 创建请求 | 38 | * @param createReqBO 创建请求 |
| 40 | */ | 39 | */ |
| 41 | - void createOperateLogV2(OperateLogV2CreateReqBO createReqBO); | 40 | + void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO); |
| 42 | 41 | ||
| 43 | - // TODO @puhui999:module 改成 type | ||
| 44 | /** | 42 | /** |
| 45 | - * 获取指定模块的指定数据的操作日志 | 43 | + * 获得操作日志分页列表 |
| 46 | * | 44 | * |
| 47 | - * @param module 操作模块 | ||
| 48 | - * @param bizId 操作模块编号 | ||
| 49 | - * @return 操作日志 | 45 | + * @param pageReqVO 分页条件 |
| 46 | + * @return 操作日志分页列表 | ||
| 50 | */ | 47 | */ |
| 51 | - List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId); | 48 | + PageResult<OperateLogV2DO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO); |
| 52 | 49 | ||
| 53 | } | 50 | } |
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; | @@ -6,13 +6,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | import cn.iocoder.yudao.framework.common.util.string.StrUtils; | 7 | import cn.iocoder.yudao.framework.common.util.string.StrUtils; |
| 8 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; | 8 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; |
| 9 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; | ||
| 10 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | ||
| 9 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; | 11 | import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; |
| 11 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; | 13 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; |
| 12 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | 14 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 13 | import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; | 15 | import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; |
| 14 | import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper; | 16 | import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper; |
| 15 | -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; | ||
| 16 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; | 17 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 17 | import jakarta.annotation.Resource; | 18 | import jakarta.annotation.Resource; |
| 18 | import lombok.extern.slf4j.Slf4j; | 19 | import lombok.extern.slf4j.Slf4j; |
| @@ -20,7 +21,6 @@ import org.springframework.stereotype.Service; | @@ -20,7 +21,6 @@ import org.springframework.stereotype.Service; | ||
| 20 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 21 | 22 | ||
| 22 | import java.util.Collection; | 23 | import java.util.Collection; |
| 23 | -import java.util.List; | ||
| 24 | 24 | ||
| 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 26 | import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; | 26 | import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; |
| @@ -69,14 +69,17 @@ public class OperateLogServiceImpl implements OperateLogService { | @@ -69,14 +69,17 @@ public class OperateLogServiceImpl implements OperateLogService { | ||
| 69 | // ======================= LOG V2 ======================= | 69 | // ======================= LOG V2 ======================= |
| 70 | 70 | ||
| 71 | @Override | 71 | @Override |
| 72 | - public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) { | 72 | + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { |
| 73 | OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); | 73 | OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); |
| 74 | + log.setJavaMethodArgs(StrUtils.maxLength(log.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); | ||
| 75 | + log.setResultData(StrUtils.maxLength(log.getResultData(), RESULT_MAX_LENGTH)); | ||
| 74 | operateLogV2Mapper.insert(log); | 76 | operateLogV2Mapper.insert(log); |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 79 | + | ||
| 77 | @Override | 80 | @Override |
| 78 | - public List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId) { | ||
| 79 | - return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId); | 81 | + public PageResult<OperateLogV2DO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { |
| 82 | + return operateLogV2Mapper.selectPage(pageReqVO); | ||
| 80 | } | 83 | } |
| 81 | 84 | ||
| 82 | } | 85 | } |
yudao-server/src/main/resources/application-local.yaml
| @@ -188,6 +188,7 @@ logging: | @@ -188,6 +188,7 @@ logging: | ||
| 188 | cn.iocoder.yudao.module.trade.dal.mysql: debug | 188 | cn.iocoder.yudao.module.trade.dal.mysql: debug |
| 189 | cn.iocoder.yudao.module.promotion.dal.mysql: debug | 189 | cn.iocoder.yudao.module.promotion.dal.mysql: debug |
| 190 | cn.iocoder.yudao.module.statistics.dal.mysql: debug | 190 | cn.iocoder.yudao.module.statistics.dal.mysql: debug |
| 191 | + cn.iocoder.yudao.module.crm.dal.mysql: debug | ||
| 191 | 192 | ||
| 192 | debug: false | 193 | debug: false |
| 193 | 194 |
yudao-server/src/main/resources/application.yaml
| @@ -79,7 +79,17 @@ mybatis-plus: | @@ -79,7 +79,17 @@ mybatis-plus: | ||
| 79 | password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 | 79 | password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 |
| 80 | 80 | ||
| 81 | mybatis-plus-join: | 81 | mybatis-plus-join: |
| 82 | - banner: false # 关闭控制台的 Banner 打印 | 82 | + #是否打印 mybatis plus join banner 默认true |
| 83 | + banner: false | ||
| 84 | + #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除 | ||
| 85 | + sub-table-logic: true | ||
| 86 | + #拦截器MappedStatement缓存(默认true) | ||
| 87 | + ms-cache: true | ||
| 88 | + #表别名(默认 t) | ||
| 89 | + table-alias: t | ||
| 90 | + #副表逻辑删除条件的位置,支持where、on | ||
| 91 | + #默认ON (1.4.7.2及之前版本默认为where) | ||
| 92 | + logic-del-type: on | ||
| 83 | 93 | ||
| 84 | # Spring Data Redis 配置 | 94 | # Spring Data Redis 配置 |
| 85 | spring: | 95 | spring: |