package cn.iocoder.yudao.module.mes.service.trace.consumer;
|
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.crypto.digest.DigestUtil;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
import cn.iocoder.yudao.framework.ip.core.utils.IPUtils;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.trace.consumer.MesTraceConsumerScanEventDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.trace.consumer.MesTraceConsumerScanEventMapper;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
|
import java.time.LocalDateTime;
|
|
/**
|
* 消费者扫码访问事件 Service 实现
|
*
|
* @author 超级管理员
|
*/
|
@Service
|
@Slf4j
|
public class MesTraceConsumerScanEventServiceImpl implements MesTraceConsumerScanEventService {
|
|
private static final int TRACE_CODE_MAX_LENGTH = 255;
|
private static final int NORMALIZED_CODE_MAX_LENGTH = 128;
|
|
@Resource
|
private MesTraceConsumerScanEventMapper eventMapper;
|
|
@Override
|
public MesTraceConsumerScanEventDO recordScan(String traceCode, String normalizedCode, String sourceType,
|
Long batchId, boolean success, String errorCode) {
|
try {
|
MesTraceConsumerScanEventDO event = new MesTraceConsumerScanEventDO();
|
event.setTraceCode(limit(traceCode, TRACE_CODE_MAX_LENGTH));
|
event.setNormalizedCode(limit(normalizedCode, NORMALIZED_CODE_MAX_LENGTH));
|
event.setSourceType(sourceType);
|
event.setChannel(limit(channel(), 32));
|
String[] region = region(ServletUtils.getClientIP());
|
event.setProvince(limit(region[0], 64));
|
event.setCity(limit(region[1], 64));
|
event.setBatchId(batchId);
|
event.setSuccess(success);
|
event.setErrorCode(limit(errorCode, 64));
|
event.setIpHash(hash(ServletUtils.getClientIP()));
|
event.setUserAgentHash(hash(ServletUtils.getUserAgent()));
|
event.setEventTime(LocalDateTime.now());
|
eventMapper.insert(event);
|
return event;
|
} catch (Exception ex) {
|
log.warn("[recordScan][记录消费者扫码访问事件失败] traceCode={}", limit(traceCode, 64), ex);
|
return null;
|
}
|
}
|
|
@Override
|
public MesTraceConsumerScanEventDO getEvent(Long id) {
|
return eventMapper.selectById(id);
|
}
|
|
/**
|
* 根据 User-Agent 识别扫码入口渠道
|
*/
|
private String channel() {
|
String ua = ServletUtils.getUserAgent();
|
if (StrUtil.isBlank(ua)) {
|
return null;
|
}
|
String lower = ua.toLowerCase();
|
if (lower.contains("micromessenger")) {
|
return "微信";
|
}
|
if (lower.contains("alipayclient")) {
|
return "支付宝";
|
}
|
return "浏览器";
|
}
|
|
/**
|
* 根据客户端 IP 解析省份、城市;解析失败返回空,不影响事件记录
|
*/
|
private String[] region(String ip) {
|
if (StrUtil.isBlank(ip)) {
|
return new String[]{null, null};
|
}
|
Area area = IPUtils.getArea(ip);
|
if (area == null) {
|
return new String[]{null, null};
|
}
|
String province = null;
|
String city = null;
|
Area node = area;
|
while (node != null) {
|
Integer type = node.getType();
|
if (AreaTypeEnum.PROVINCE.getType().equals(type)) {
|
province = node.getName();
|
} else if (AreaTypeEnum.CITY.getType().equals(type)) {
|
city = node.getName();
|
}
|
node = node.getParent();
|
}
|
return new String[]{province, city};
|
}
|
|
private String hash(String value) {
|
return value == null || value.isBlank() ? null : DigestUtil.sha256Hex(value);
|
}
|
|
private String limit(String value, int maxLength) {
|
if (value == null || value.length() <= maxLength) {
|
return value;
|
}
|
return value.substring(0, maxLength);
|
}
|
|
}
|