mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 02:28:03 +08:00 
			
		
		
		
	售后日志优化
This commit is contained in:
		| @ -96,11 +96,6 @@ | ||||
|                 <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> | ||||
|                 <version>${revision}</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>cn.iocoder.boot</groupId> | ||||
|                 <artifactId>yudao-spring-boot-starter-biz-trade</artifactId> | ||||
|                 <version>${revision}</version> | ||||
|             </dependency> | ||||
|             <dependency> | ||||
|                 <groupId>cn.iocoder.boot</groupId> | ||||
|                 <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> | ||||
|  | ||||
| @ -31,7 +31,6 @@ | ||||
|         <module>yudao-spring-boot-starter-biz-sms</module> | ||||
|  | ||||
|         <module>yudao-spring-boot-starter-biz-pay</module> | ||||
|         <module>yudao-spring-boot-starter-biz-trade</module> | ||||
|         <module>yudao-spring-boot-starter-biz-weixin</module> | ||||
|         <module>yudao-spring-boot-starter-biz-social</module> | ||||
|         <module>yudao-spring-boot-starter-biz-tenant</module> | ||||
|  | ||||
| @ -1,82 +0,0 @@ | ||||
| package cn.iocoder.yudao.framework.common.util.spel; | ||||
|  | ||||
| import org.aspectj.lang.JoinPoint; | ||||
| import org.aspectj.lang.reflect.MethodSignature; | ||||
| import org.springframework.core.DefaultParameterNameDiscoverer; | ||||
| import org.springframework.expression.EvaluationContext; | ||||
| import org.springframework.expression.spel.standard.SpelExpressionParser; | ||||
| import org.springframework.expression.spel.support.StandardEvaluationContext; | ||||
|  | ||||
| // TODO @Chopper:和 SpringExpressionUtils 合并下 | ||||
| /** | ||||
|  * SpelUtil | ||||
|  * | ||||
|  * @author Chopper | ||||
|  * @version v1.0 | ||||
|  * @since 2021-01-11 10:45 | ||||
|  */ | ||||
| public class SpelUtil { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * spel表达式解析器 | ||||
|      */ | ||||
|     private static SpelExpressionParser spelExpressionParser = new SpelExpressionParser(); | ||||
|     /** | ||||
|      * 参数名发现器 | ||||
|      */ | ||||
|     private static DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); | ||||
|  | ||||
|     /** | ||||
|      * 转换 jspl参数 | ||||
|      * | ||||
|      * @param joinPoint | ||||
|      * @param spel | ||||
|      * @return | ||||
|      */ | ||||
|     public static String compileParams(JoinPoint joinPoint, String spel) { //Spel表达式解析日志信息 | ||||
|         //获得方法参数名数组 | ||||
|         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||||
|  | ||||
|         String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod()); | ||||
|         if (parameterNames != null && parameterNames.length > 0) { | ||||
|             EvaluationContext context = new StandardEvaluationContext(); | ||||
|  | ||||
|             //获取方法参数值 | ||||
|             Object[] args = joinPoint.getArgs(); | ||||
|             for (int i = 0; i < args.length; i++) { | ||||
|                 //替换spel里的变量值为实际值, 比如 #user -->  user对象 | ||||
|                 context.setVariable(parameterNames[i], args[i]); | ||||
|             } | ||||
|             return spelExpressionParser.parseExpression(spel).getValue(context).toString(); | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 转换 jspl参数 | ||||
|      * | ||||
|      * @param joinPoint | ||||
|      * @param spel | ||||
|      * @return | ||||
|      */ | ||||
|     public static String compileParams(JoinPoint joinPoint, Object rvt, String spel) { //Spel表达式解析日志信息 | ||||
|         //获得方法参数名数组 | ||||
|         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||||
|  | ||||
|         String[] parameterNames = parameterNameDiscoverer.getParameterNames(signature.getMethod()); | ||||
|         if (parameterNames != null && parameterNames.length > 0) { | ||||
|             EvaluationContext context = new StandardEvaluationContext(); | ||||
|  | ||||
|             //获取方法参数值 | ||||
|             Object[] args = joinPoint.getArgs(); | ||||
|             for (int i = 0; i < args.length; i++) { | ||||
|                 //替换spel里的变量值为实际值, 比如 #user -->  user对象 | ||||
|                 context.setVariable(parameterNames[i], args[i]); | ||||
|             } | ||||
|             context.setVariable("rvt", rvt); | ||||
|             return spelExpressionParser.parseExpression(spel).getValue(context).toString(); | ||||
|         } | ||||
|         return ""; | ||||
|     } | ||||
| } | ||||
| @ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.spring; | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.map.MapUtil; | ||||
| import cn.hutool.core.util.ArrayUtil; | ||||
| import org.aspectj.lang.JoinPoint; | ||||
| import org.aspectj.lang.ProceedingJoinPoint; | ||||
| import org.aspectj.lang.reflect.MethodSignature; | ||||
| import org.springframework.core.DefaultParameterNameDiscoverer; | ||||
| @ -24,7 +25,15 @@ import java.util.Map; | ||||
|  */ | ||||
| public class SpringExpressionUtils { | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * spel表达式解析器 | ||||
|      */ | ||||
|     private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser(); | ||||
|     /** | ||||
|      * 参数名发现器 | ||||
|      */ | ||||
|     private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer(); | ||||
|  | ||||
|     private SpringExpressionUtils() { | ||||
| @ -79,4 +88,47 @@ public class SpringExpressionUtils { | ||||
|         }); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * JoinPoint 切面 批量解析 EL 表达式,转换 jspl参数 | ||||
|      * | ||||
|      * @param joinPoint 切面点 | ||||
|      * @param rvt       返回值 | ||||
|      * @param expressionStrings      EL 表达式数组 | ||||
|      * @return java.lang.String 结果 | ||||
|      * @author 陈賝 | ||||
|      * @since 2023/6/18 11:20 | ||||
|      */ | ||||
|     public static Map<String, Object> parseExpression(JoinPoint joinPoint, Object rvt, List<String> expressionStrings) { | ||||
|         // 如果为空,则不进行解析 | ||||
|         if (CollUtil.isEmpty(expressionStrings)) { | ||||
|             return MapUtil.newHashMap(); | ||||
|         } | ||||
|  | ||||
|         // 第一步,构建解析的上下文 EvaluationContext | ||||
|         // 通过 joinPoint 获取被注解方法 | ||||
|         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||||
|         Method method = signature.getMethod(); | ||||
|         // 使用 spring 的 ParameterNameDiscoverer 获取方法形参名数组 | ||||
|         String[] parameterNames = PARAMETER_NAME_DISCOVERER.getParameterNames(method); | ||||
|         // Spring 的表达式上下文对象 | ||||
|         EvaluationContext context = new StandardEvaluationContext(); | ||||
|         if (ArrayUtil.isNotEmpty(parameterNames)) { | ||||
|             //获取方法参数值 | ||||
|             Object[] args = joinPoint.getArgs(); | ||||
|             for (int i = 0; i < args.length; i++) { | ||||
|                 //替换spel里的变量值为实际值, 比如 #user -->  user对象 | ||||
|                 context.setVariable(parameterNames[i], args[i]); | ||||
|             } | ||||
|             context.setVariable("rvt", rvt); | ||||
|         } | ||||
|         // 第二步,逐个参数解析 | ||||
|         Map<String, Object> result = MapUtil.newHashMap(expressionStrings.size(), true); | ||||
|         expressionStrings.forEach(key -> { | ||||
|             Object value = EXPRESSION_PARSER.parseExpression(key).getValue(context); | ||||
|             result.put(key, value); | ||||
|         }); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -1,50 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <parent> | ||||
|         <groupId>cn.iocoder.boot</groupId> | ||||
|         <artifactId>yudao-framework</artifactId> | ||||
|         <version>${revision}</version> | ||||
|     </parent> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>yudao-spring-boot-starter-biz-trade</artifactId> | ||||
|     <packaging>jar</packaging> | ||||
|  | ||||
|     <name>${project.artifactId}</name> | ||||
|     <description>交易模块</description> | ||||
|     <url>https://github.com/YunaiV/ruoyi-vue-pro</url> | ||||
|  | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-common</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Spring 核心 --> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-aop</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Web 相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-web</artifactId> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 业务组件 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-system-api</artifactId> <!-- 需要使用它,进行操作日志的记录 --> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 工具类相关 --> | ||||
|         <dependency> | ||||
|             <groupId>com.google.guava</groupId> | ||||
|             <artifactId>guava</artifactId> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| </project> | ||||
| @ -1,16 +0,0 @@ | ||||
| package cn.iocoder.yudao.framework.trade.config; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.trade.core.aop.AfterSaleLogAspect; | ||||
| import org.springframework.boot.autoconfigure.AutoConfiguration; | ||||
| import org.springframework.context.annotation.Bean; | ||||
|  | ||||
| // TODO @Chopper:和 yudao-module-trade-biz 的 framework 里 | ||||
| @AutoConfiguration | ||||
| public class YudaoAfterSaleLogAutoConfiguration { | ||||
|  | ||||
|     @Bean | ||||
|     public AfterSaleLogAspect afterSaleLogAspect() { | ||||
|         return new AfterSaleLogAspect(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,73 +0,0 @@ | ||||
| package cn.iocoder.yudao.framework.trade.core.aop; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.hutool.extra.spring.SpringUtil; | ||||
| import cn.iocoder.yudao.framework.common.util.spel.SpelUtil; | ||||
| import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog; | ||||
| import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogCreateReqDTO; | ||||
| import cn.iocoder.yudao.framework.trade.core.enums.AfterSaleStatusEnum; | ||||
| import cn.iocoder.yudao.framework.trade.core.service.AfterSaleLogService; | ||||
| import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.aspectj.lang.JoinPoint; | ||||
| import org.aspectj.lang.annotation.AfterReturning; | ||||
| import org.aspectj.lang.annotation.Aspect; | ||||
| import org.aspectj.lang.reflect.MethodSignature; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * 记录售后日志的 AOP 切面 | ||||
|  * | ||||
|  * @author 陈賝 | ||||
|  * @since 2023/6/13 13:54 | ||||
|  */ | ||||
| @Slf4j | ||||
| @Aspect | ||||
| public class AfterSaleLogAspect { | ||||
|  | ||||
|     @AfterReturning(pointcut = "@annotation(afterSaleLog)", returning = "info") | ||||
|     public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog, Object info) { | ||||
|         try { | ||||
|             // 日志对象拼接 | ||||
|             Integer userType = WebFrameworkUtils.getLoginUserType(); | ||||
|             Long id = WebFrameworkUtils.getLoginUserId(); | ||||
|             Map<String, String> formatObj = spelFormat(joinPoint, info); | ||||
|             TradeAfterSaleLogCreateReqDTO dto = new TradeAfterSaleLogCreateReqDTO() | ||||
|                     .setUserId(id).setUserType(userType) | ||||
| //            MapUtil.getLong() TODO @陈賝:试试这个方法 | ||||
|                     .setAfterSaleId(Long.valueOf(formatObj.get("id"))) | ||||
|                     .setContent(formatObj.get("content")) | ||||
|                     .setOperateType(formatObj.get("operateType")); | ||||
|             // 异步存入数据库 TODO 可以注入哈; | ||||
|             SpringUtil.getBean(AfterSaleLogService.class).insert(dto); | ||||
|         } catch (Exception exception) { | ||||
|             // TODO @陈賝:日志要记录下参数哈,不然排查问题不好搞; | ||||
|             log.error("日志记录错误", exception); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取描述信息 | ||||
|      */ | ||||
|     public static Map<String, String> spelFormat(JoinPoint joinPoint, Object info) { | ||||
|         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||||
|         AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class); | ||||
|         Map<String, String> result = new HashMap<>(2); // TODO @陈賝:Maps.newExpectedXXX(3) | ||||
|         // 售后ID | ||||
|         String id = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.id()); | ||||
|         result.put("id", id); | ||||
|         // 操作类型 | ||||
|         String operateType = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.operateType()); | ||||
|         result.put("operateType", operateType); | ||||
|         // 日志内容 | ||||
|         String content = SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.content()); | ||||
|         if (StrUtil.isNotEmpty(afterSaleLogPoint.operateType())) { | ||||
|             content += AfterSaleStatusEnum.valueOf(SpelUtil.compileParams(joinPoint, info, afterSaleLogPoint.operateType())).description(); | ||||
|         } | ||||
|         result.put("content", content); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,18 +0,0 @@ | ||||
| package cn.iocoder.yudao.framework.trade.core.service; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogCreateReqDTO; | ||||
|  | ||||
| // TODO @陈賝:类注释 | ||||
| public interface AfterSaleLogService { | ||||
|  | ||||
|     /** | ||||
|      * 创建售后日志 | ||||
|      * | ||||
|      * @param logDTO 日志记录 | ||||
|      * @author 陈賝 | ||||
|      * @since 2023/6/12 14:18 | ||||
|      */ | ||||
|     // TODO @陈賝:createLog 方法名 | ||||
|     void insert(TradeAfterSaleLogCreateReqDTO logDTO); | ||||
|  | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| cn.iocoder.yudao.framework.trade.config.YudaoAfterSaleLogAutoConfiguration | ||||
| @ -58,10 +58,6 @@ | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-trade</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Web 相关 --> | ||||
|         <dependency> | ||||
|  | ||||
| @ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale; | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog; | ||||
| import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||||
| import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||||
| import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; | ||||
| @ -15,6 +14,8 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal | ||||
| import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; | ||||
| import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; | ||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.enums.AfterSaleStatusEnum; | ||||
| import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; | ||||
| import io.swagger.v3.oas.annotations.Operation; | ||||
| import io.swagger.v3.oas.annotations.Parameter; | ||||
| @ -122,7 +123,7 @@ public class TradeAfterSaleController { | ||||
|      * @date 2023/6/14 21:39 | ||||
|      */ | ||||
|     @PostMapping(value = "/create") | ||||
|     @AfterSaleLog(id = "#createReqVO.orderItemId", content = "'申请售后:售后编号['+#createReqVO.orderItemId+'] , '", operateType = "#createReqVO.operateType") | ||||
|     @AfterSaleLog(id = "#createReqVO.orderItemId", content = "'申请售后:售后编号['+#createReqVO.orderItemId+'] , '", operateType = AfterSaleStatusEnum.APPLY) | ||||
|     public CommonResult<Long> createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) { | ||||
|         return success(1L); | ||||
| //        return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO)); | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.common.validation.InEnum; | ||||
| import cn.iocoder.yudao.framework.trade.core.enums.AfterSaleStatusEnum; | ||||
| import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
| @ -32,14 +31,6 @@ public class AppTradeAfterSaleCreateReqVO { | ||||
|     @NotNull(message = "申请原因不能为空") | ||||
|     private String applyReason; | ||||
|  | ||||
|     // TODO @陈賝:这个参数不应该有呀。 | ||||
|     /** | ||||
|      * @see AfterSaleStatusEnum | ||||
|      */ | ||||
|     @Schema(description = "操作类型", required = true, example = "1") | ||||
|     @NotNull(message = "操作类型不能为空") | ||||
|     private String operateType; | ||||
|  | ||||
|     @Schema(description = "补充描述", example = "商品质量不好") | ||||
|     private String applyDescription; | ||||
|  | ||||
|  | ||||
| @ -0,0 +1,21 @@ | ||||
| package cn.iocoder.yudao.module.trade.framework.aftersalelog.config; | ||||
|  | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop.AfterSaleLogAspect; | ||||
| import org.springframework.boot.autoconfigure.AutoConfiguration; | ||||
| import org.springframework.context.annotation.Bean; | ||||
|  | ||||
| /** | ||||
|  * trade 模块的 afterSaleLog 组件的 Configuration | ||||
|  * | ||||
|  * @author 陈賝 | ||||
|  * @since 2023/6/18 11:09 | ||||
|  */ | ||||
| @AutoConfiguration | ||||
| public class AfterSaleLogConfiguration { | ||||
|  | ||||
|     @Bean | ||||
|     public AfterSaleLogAspect afterSaleLogAspect() { | ||||
|         return new AfterSaleLogAspect(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,4 +1,6 @@ | ||||
| package cn.iocoder.yudao.framework.trade.core.annotations; | ||||
| package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations; | ||||
| 
 | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.enums.AfterSaleStatusEnum; | ||||
| 
 | ||||
| import java.lang.annotation.*; | ||||
| 
 | ||||
| @ -18,11 +20,10 @@ public @interface AfterSaleLog { | ||||
|      */ | ||||
|     String id(); | ||||
| 
 | ||||
|     // TODO @陈賝:是不是改成一个操作的枚举? | ||||
|     /** | ||||
|      * 操作类型 | ||||
|      */ | ||||
|     String operateType() default ""; | ||||
|     AfterSaleStatusEnum operateType() default AfterSaleStatusEnum.APPLY; | ||||
| 
 | ||||
|     /** | ||||
|      * 日志内容 | ||||
| @ -0,0 +1,80 @@ | ||||
| package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.aop; | ||||
|  | ||||
| import cn.hutool.core.map.MapUtil; | ||||
| import cn.hutool.core.util.ObjectUtil; | ||||
| import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; | ||||
| import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.annotations.AfterSaleLog; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; | ||||
| import com.google.common.collect.Maps; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.aspectj.lang.JoinPoint; | ||||
| import org.aspectj.lang.ProceedingJoinPoint; | ||||
| import org.aspectj.lang.annotation.AfterReturning; | ||||
| import org.aspectj.lang.annotation.Aspect; | ||||
| import org.aspectj.lang.reflect.MethodSignature; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||||
| import static java.util.Arrays.asList; | ||||
|  | ||||
| /** | ||||
|  * 记录售后日志的 AOP 切面 | ||||
|  * | ||||
|  * @author 陈賝 | ||||
|  * @since 2023/6/13 13:54 | ||||
|  */ | ||||
| @Slf4j | ||||
| @Aspect | ||||
| public class AfterSaleLogAspect { | ||||
|     @Resource | ||||
|     private AfterSaleLogService saleLogService; | ||||
|  | ||||
|     @AfterReturning(pointcut = "@annotation(afterSaleLog)", returning = "info") | ||||
|     public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog, Object info) { | ||||
|         try { | ||||
|             // 日志对象拼接 | ||||
|             Integer userType = WebFrameworkUtils.getLoginUserType(); | ||||
|             Long id = WebFrameworkUtils.getLoginUserId(); | ||||
|             Map<String, String> formatObj = spelFormat(joinPoint, info); | ||||
|             TradeAfterSaleLogCreateReqDTO dto = new TradeAfterSaleLogCreateReqDTO() | ||||
|                     .setUserId(id).setUserType(userType) | ||||
|                     .setAfterSaleId(MapUtil.getLong(formatObj, "id")) | ||||
|                     .setContent(formatObj.get("content")) | ||||
|                     .setOperateType(formatObj.get("operateType")); | ||||
|             // 异步存入数据库 | ||||
|             saleLogService.createLog(dto); | ||||
|         } catch (Exception exception) { | ||||
|             log.error("[afterSaleLog({}) 日志记录错误]", toJsonString(afterSaleLog), exception); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取描述信息 | ||||
|      */ | ||||
|     public static Map<String, String> spelFormat(JoinPoint joinPoint, Object info) { | ||||
|         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); | ||||
|         AfterSaleLog afterSaleLogPoint = signature.getMethod().getAnnotation(AfterSaleLog.class); | ||||
|         HashMap<String, String> result = Maps.newHashMapWithExpectedSize(3); | ||||
|         Map<String, Object> spelMap = SpringExpressionUtils.parseExpression(joinPoint, info, | ||||
|                 asList(afterSaleLogPoint.id(), afterSaleLogPoint.operateType().description(), afterSaleLogPoint.content())); | ||||
|         // 售后ID | ||||
|         String id = MapUtil.getStr(spelMap, afterSaleLogPoint.id()); | ||||
|         result.put("id", id); | ||||
|         // 操作类型 | ||||
|         String operateType = MapUtil.getStr(spelMap, afterSaleLogPoint.operateType().description()); | ||||
|         result.put("operateType", operateType); | ||||
|         // 日志内容 | ||||
|         String content = MapUtil.getStr(spelMap, afterSaleLogPoint.content()); | ||||
|         if (ObjectUtil.isNotNull(afterSaleLogPoint.operateType())) { | ||||
|             content += MapUtil.getStr(spelMap, afterSaleLogPoint.operateType().description()); | ||||
|         } | ||||
|         result.put("content", content); | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| package cn.iocoder.yudao.framework.trade.core.dto; | ||||
| package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto; | ||||
| 
 | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Data; | ||||
| @ -6,6 +6,9 @@ import lombok.NoArgsConstructor; | ||||
| 
 | ||||
| /** | ||||
|  * 售后日志的创建 Request DTO | ||||
|  * | ||||
|  * @author 陈賝 | ||||
|  * @since 2023/6/19 09:54 | ||||
|  */ | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @ -18,7 +21,7 @@ public class TradeAfterSaleLogCreateReqDTO { | ||||
|     private Long id; | ||||
|     /** | ||||
|      * 用户编号 | ||||
|      * | ||||
|      * <p> | ||||
|      * 关联 1:AdminUserDO 的 id 字段 | ||||
|      * 关联 2:MemberUserDO 的 id 字段 | ||||
|      */ | ||||
| @ -1,4 +1,4 @@ | ||||
| package cn.iocoder.yudao.framework.trade.core.enums; | ||||
| package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.enums; | ||||
| 
 | ||||
| /** | ||||
|  * 售后状态的枚举 | ||||
| @ -0,0 +1,23 @@ | ||||
| package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service; | ||||
|  | ||||
|  | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; | ||||
|  | ||||
| /** | ||||
|  * 交易售后日志 Service 接口 | ||||
|  * | ||||
|  * @author 陈賝 | ||||
|  * @since 2023/6/12 14:18 | ||||
|  */ | ||||
| public interface AfterSaleLogService { | ||||
|  | ||||
|     /** | ||||
|      * 创建售后日志 | ||||
|      * | ||||
|      * @param logDTO 日志记录 | ||||
|      * @author 陈賝 | ||||
|      * @since 2023/6/12 14:18 | ||||
|      */ | ||||
|     void createLog(TradeAfterSaleLogCreateReqDTO logDTO); | ||||
|  | ||||
| } | ||||
| @ -5,8 +5,6 @@ import cn.hutool.core.util.RandomUtil; | ||||
| import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | ||||
| import cn.iocoder.yudao.framework.trade.core.dto.TradeAfterSaleLogCreateReqDTO; | ||||
| import cn.iocoder.yudao.framework.trade.core.service.AfterSaleLogService; | ||||
| import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; | ||||
| import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | ||||
| import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; | ||||
| @ -26,6 +24,8 @@ import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleTypeEnum; | ||||
| import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; | ||||
| import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; | ||||
| import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; | ||||
| import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; | ||||
| import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | ||||
| import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| @ -40,6 +40,7 @@ import javax.annotation.Resource; | ||||
| import java.time.LocalDateTime; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||||
| import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; | ||||
|  | ||||
| /** | ||||
| @ -394,7 +395,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | ||||
|                 .setAfterSaleId(afterSale.getId()) | ||||
|                 .setOperateType(afterStatus.toString()); | ||||
|         // TODO 废弃,待删除 | ||||
|         this.insert(logDTO); | ||||
|         this.createLog(logDTO); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @ -406,7 +407,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | ||||
|      */ | ||||
|     @Override | ||||
|     @Async | ||||
|     public void insert(TradeAfterSaleLogCreateReqDTO logDTO) { | ||||
|     public void createLog(TradeAfterSaleLogCreateReqDTO logDTO) { | ||||
|         try { | ||||
|             TradeAfterSaleLogDO afterSaleLog = new TradeAfterSaleLogDO() | ||||
|                     .setUserId(logDTO.getUserId()) | ||||
| @ -416,7 +417,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | ||||
|                     .setContent(logDTO.getContent()); | ||||
|             tradeAfterSaleLogMapper.insert(afterSaleLog); | ||||
|         }catch (Exception exception){ | ||||
|             log.error("日志记录错误", exception); | ||||
|             log.error("[request({}) 日志记录错误]", toJsonString(logDTO), exception); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -84,11 +84,11 @@ | ||||
| <!--            <version>${revision}</version>--> | ||||
| <!--        </dependency>--> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-point-biz</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
| <!--        <dependency>--> | ||||
| <!--            <groupId>cn.iocoder.boot</groupId>--> | ||||
| <!--            <artifactId>yudao-module-point-biz</artifactId>--> | ||||
| <!--            <version>${revision}</version>--> | ||||
| <!--        </dependency>--> | ||||
|  | ||||
|         <!-- spring boot 配置所需依赖 --> | ||||
|         <dependency> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 chenchen
					chenchen