2026-06-24 f4bd1f3c89d906131495a0aca5aaf82966378510
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package cn.iocoder.yudao.module.trade.framework.aftersale.core.aop;
 
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum;
import cn.iocoder.yudao.module.trade.framework.aftersale.core.annotations.AfterSaleLog;
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService;
import cn.iocoder.yudao.module.trade.service.aftersale.bo.AfterSaleLogCreateReqBO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
 
import java.util.Map;
 
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static java.util.Collections.emptyMap;
 
/**
 * 售后订单的操作记录的 AOP 切面
 *
 * @author 陈賝
 * @since 2023/6/13 13:54
 */
@Slf4j
@Aspect
public class AfterSaleLogAspect {
 
    /**
     * 用户编号
     *
     * 目前的使用场景:支付回调时,需要强制设置下用户编号
     */
    private static final ThreadLocal<Long> USER_ID = new ThreadLocal<>();
    /**
     * 用户类型
     */
    private static final ThreadLocal<Integer> USER_TYPE = new ThreadLocal<>();
    /**
     * 订单编号
     */
    private static final ThreadLocal<Long> AFTER_SALE_ID = new ThreadLocal<>();
    /**
     * 操作前的状态
     */
    private static final ThreadLocal<Integer> BEFORE_STATUS = new ThreadLocal<>();
    /**
     * 操作后的状态
     */
    private static final ThreadLocal<Integer> AFTER_STATUS = new ThreadLocal<>();
    /**
     * 操作类型(仅“动态场景”需要使用)
     */
    private static final ThreadLocal<AfterSaleOperateTypeEnum> OPERATE_TYPE = new ThreadLocal<>();
    /**
     * 拓展参数 Map,用于格式化操作内容
     */
    private static final ThreadLocal<Map<String, Object>> EXTS = new ThreadLocal<>();
 
    @Resource
    private AfterSaleLogService afterSaleLogService;
 
    @AfterReturning(pointcut = "@annotation(afterSaleLog)")
    public void doAfterReturning(JoinPoint joinPoint, AfterSaleLog afterSaleLog) {
        try {
            // 1.1 操作用户
            Integer userType = getUserType();
            Long userId = getUserId();
            // 1.2 售后信息
            Long afterSaleId = AFTER_SALE_ID.get();
            if (afterSaleId == null) { // 如果未设置,只有注解,说明不需要记录日志
                return;
            }
            AfterSaleOperateTypeEnum operateType = ObjUtil.defaultIfNull(OPERATE_TYPE.get(), afterSaleLog.operateType());
            Integer beforeStatus = BEFORE_STATUS.get();
            Integer afterStatus = AFTER_STATUS.get();
            Map<String, Object> exts = ObjectUtil.defaultIfNull(EXTS.get(), emptyMap());
            String content = StrUtil.format(operateType.getContent(), exts);
 
            // 2. 记录日志
            AfterSaleLogCreateReqBO createBO = new AfterSaleLogCreateReqBO()
                    .setUserId(userId).setUserType(userType)
                    .setAfterSaleId(afterSaleId).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus)
                    .setOperateType(operateType.getType()).setContent(content);
            afterSaleLogService.createAfterSaleLog(createBO);
        } catch (Exception exception) {
            log.error("[doAfterReturning][afterSaleLog({}) 日志记录错误]", toJsonString(afterSaleLog), exception);
        } finally {
            clear();
        }
    }
 
    /**
     * 获得用户类型
     *
     * 如果没有,则约定为 {@link TradeOrderLogDO#getUserType()} 系统
     *
     * @return 用户类型
     */
    private static Integer getUserType() {
        return ObjectUtil.defaultIfNull(WebFrameworkUtils.getLoginUserType(), TradeOrderLogDO.USER_TYPE_SYSTEM);
    }
 
    /**
     * 获得用户编号
     *
     * 如果没有,则约定为 {@link TradeOrderLogDO#getUserId()} 系统
     *
     * @return 用户类型
     */
    private static Long getUserId() {
        if (USER_ID.get() != null) {
            return USER_ID.get();
        }
        return ObjectUtil.defaultIfNull(WebFrameworkUtils.getLoginUserId(), TradeOrderLogDO.USER_ID_SYSTEM);
    }
 
    public static void setAfterSale(Long id, Integer beforeStatus, Integer afterStatus, Map<String, Object> exts) {
        AFTER_SALE_ID.set(id);
        BEFORE_STATUS.set(beforeStatus);
        AFTER_STATUS.set(afterStatus);
        EXTS.set(exts);
    }
 
    public static void setAfterSaleOperateType(AfterSaleOperateTypeEnum operateType) {
        OPERATE_TYPE.set(operateType);
    }
 
    public static void setUserInfo(Long userId, Integer userType) {
        USER_ID.set(userId);
        USER_TYPE.set(userType);
    }
 
    private static void clear() {
        USER_ID.remove();
        USER_TYPE.remove();
        AFTER_SALE_ID.remove();
        BEFORE_STATUS.remove();
        AFTER_STATUS.remove();
        OPERATE_TYPE.remove();
        EXTS.remove();
    }
 
}