package com.trafficaudit.system.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.trafficaudit.security.utils.JwtUtils; import com.trafficaudit.system.entity.OperationLog; import com.trafficaudit.system.entity.User; import com.trafficaudit.system.mapper.OperationLogMapper; import com.trafficaudit.system.mapper.UserMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; /** * 操作日志服务:记录关键操作(报表生成/系列打包等),自动从 Authorization 头解析当前用户。 * 解析失败或未登录时不抛异常,仅记录操作本身。 */ @Slf4j @Service public class OperationLogService { @Resource private OperationLogMapper operationLogMapper; @Resource private UserMapper userMapper; @Resource private JwtUtils jwtUtils; @Resource private HttpServletRequest request; public void record(String module, String action, String detail) { try { OperationLog entry = new OperationLog(); entry.setModule(module); entry.setAction(action); entry.setDetail(detail); entry.setUserId(resolveUserId()); entry.setIpAddress(clientIp()); operationLogMapper.insert(entry); } catch (Exception e) { log.warn("操作日志记录失败: {}", e.getMessage()); } } private Long resolveUserId() { try { String auth = request.getHeader("Authorization"); if (auth == null || !auth.startsWith("Bearer ")) { return null; } String username = jwtUtils.getUsernameFromToken(auth.substring(7)); if (username == null || username.isEmpty()) { return null; } User user = userMapper.selectOne(new LambdaQueryWrapper() .eq(User::getUsername, username).last("limit 1")); return user == null ? null : user.getId(); } catch (Exception e) { return null; } } private String clientIp() { try { String ip = request.getHeader("X-Forwarded-For"); if (ip != null && !ip.isEmpty()) { return ip.split(",")[0].trim(); } return request.getRemoteAddr(); } catch (Exception e) { return ""; } } }