package com.sinata.appointment.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.sinata.appointment.dto.OpLogListVo;
|
import com.sinata.appointment.entity.BizOpLog;
|
import com.sinata.appointment.entity.MpUser;
|
import com.sinata.appointment.entity.SysUser;
|
import com.sinata.appointment.mapper.BizOpLogMapper;
|
import com.sinata.appointment.mapper.MpUserMapper;
|
import com.sinata.appointment.mapper.SysUserMapper;
|
import java.time.LocalDateTime;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.stream.Collectors;
|
import lombok.RequiredArgsConstructor;
|
import org.slf4j.MDC;
|
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.util.StringUtils;
|
import org.springframework.stereotype.Service;
|
|
@Service
|
@RequiredArgsConstructor
|
public class OpLogApplicationService {
|
|
public static final String MDC_TRACE = "traceId";
|
public static final String SOURCE_ADMIN = "ADMIN";
|
public static final String SOURCE_MINI_EMPLOYEE = "MINI_EMPLOYEE";
|
|
private final BizOpLogMapper bizOpLogMapper;
|
private final SysUserMapper sysUserMapper;
|
private final MpUserMapper mpUserMapper;
|
|
public IPage<OpLogListVo> page(long page, long size, String sourceType) {
|
Page<BizOpLog> pager = new Page<>(page, size);
|
LambdaQueryWrapper<BizOpLog> query =
|
new LambdaQueryWrapper<BizOpLog>()
|
.eq(BizOpLog::getDelFlag, 0)
|
.orderByDesc(BizOpLog::getOpTime)
|
.orderByDesc(BizOpLog::getId);
|
String normalizedSourceType = normalizeSourceType(sourceType);
|
if (normalizedSourceType != null) {
|
query.eq(BizOpLog::getSourceType, normalizedSourceType);
|
}
|
IPage<BizOpLog> logPage = bizOpLogMapper.selectPage(pager, query);
|
Page<OpLogListVo> result =
|
new Page<>(logPage.getCurrent(), logPage.getSize(), logPage.getTotal());
|
List<BizOpLog> records = logPage.getRecords();
|
result.setRecords(toListVos(records));
|
return result;
|
}
|
|
@Async("applicationTaskExecutor")
|
public void recordAsync(
|
String sourceType,
|
Long operatorUserId,
|
String module,
|
String action,
|
String resourceType,
|
String resourceId,
|
String detailJson) {
|
String normalizedSourceType = normalizeSourceType(sourceType);
|
if (!StringUtils.hasText(normalizedSourceType)) {
|
return;
|
}
|
if (SOURCE_MINI_EMPLOYEE.equals(normalizedSourceType) && !isEmployee(operatorUserId)) {
|
return;
|
}
|
BizOpLog log = new BizOpLog();
|
log.setSourceType(normalizedSourceType);
|
log.setOperatorUserId(operatorUserId);
|
log.setModule(module);
|
log.setAction(action);
|
log.setResourceType(resourceType);
|
log.setResourceId(resourceId);
|
log.setDetailJson(detailJson);
|
log.setOpTime(LocalDateTime.now());
|
log.setTraceId(MDC.get(MDC_TRACE));
|
bizOpLogMapper.insert(log);
|
}
|
|
private List<OpLogListVo> toListVos(List<BizOpLog> records) {
|
if (records == null || records.isEmpty()) {
|
return List.of();
|
}
|
List<Long> adminUserIds =
|
records.stream()
|
.filter(item -> SOURCE_ADMIN.equals(item.getSourceType()))
|
.map(BizOpLog::getOperatorUserId)
|
.filter(Objects::nonNull)
|
.distinct()
|
.toList();
|
List<Long> mpUserIds =
|
records.stream()
|
.filter(item -> SOURCE_MINI_EMPLOYEE.equals(item.getSourceType()))
|
.map(BizOpLog::getOperatorUserId)
|
.filter(Objects::nonNull)
|
.distinct()
|
.toList();
|
Map<Long, String> adminNameMap = loadAdminNameMap(adminUserIds);
|
Map<Long, String> mpNameMap = loadMpNameMap(mpUserIds);
|
return records.stream()
|
.map(item -> toListVo(item, adminNameMap, mpNameMap))
|
.toList();
|
}
|
|
private OpLogListVo toListVo(
|
BizOpLog item, Map<Long, String> adminNameMap, Map<Long, String> mpNameMap) {
|
OpLogListVo vo = new OpLogListVo();
|
vo.setId(item.getId());
|
vo.setSourceType(item.getSourceType());
|
vo.setSourceTypeText(resolveSourceTypeText(item.getSourceType()));
|
vo.setOperatorUserId(item.getOperatorUserId());
|
vo.setModule(item.getModule());
|
vo.setAction(item.getAction());
|
vo.setResourceType(item.getResourceType());
|
vo.setResourceId(item.getResourceId());
|
vo.setDetailJson(item.getDetailJson());
|
vo.setTraceId(item.getTraceId());
|
vo.setOpTime(item.getOpTime());
|
if (SOURCE_MINI_EMPLOYEE.equals(item.getSourceType())) {
|
vo.setOperatorName(mpNameMap.getOrDefault(item.getOperatorUserId(), "—"));
|
} else {
|
vo.setOperatorName(adminNameMap.getOrDefault(item.getOperatorUserId(), "—"));
|
}
|
return vo;
|
}
|
|
private Map<Long, String> loadAdminNameMap(List<Long> userIds) {
|
if (userIds == null || userIds.isEmpty()) {
|
return Map.of();
|
}
|
return sysUserMapper.selectBatchIds(userIds).stream()
|
.collect(
|
Collectors.toMap(
|
SysUser::getId,
|
user -> firstNonBlank(user.getRealName(), user.getUsername(), "—"),
|
(a, _b) -> a));
|
}
|
|
private Map<Long, String> loadMpNameMap(List<Long> userIds) {
|
if (userIds == null || userIds.isEmpty()) {
|
return Map.of();
|
}
|
return mpUserMapper.selectBatchIds(userIds).stream()
|
.filter(user -> "EMPLOYEE".equals(user.getUserType()))
|
.collect(
|
Collectors.toMap(
|
MpUser::getId,
|
user -> firstNonBlank(user.getNickName(), user.getMobile(), "—"),
|
(a, _b) -> a));
|
}
|
|
private boolean isEmployee(Long operatorUserId) {
|
if (operatorUserId == null) {
|
return false;
|
}
|
MpUser user = mpUserMapper.selectById(operatorUserId);
|
return user != null && "EMPLOYEE".equals(user.getUserType());
|
}
|
|
private String normalizeSourceType(String sourceType) {
|
if (!StringUtils.hasText(sourceType)) {
|
return null;
|
}
|
String normalized = sourceType.trim().toUpperCase();
|
if (SOURCE_ADMIN.equals(normalized)) {
|
return SOURCE_ADMIN;
|
}
|
if (SOURCE_MINI_EMPLOYEE.equals(normalized)) {
|
return SOURCE_MINI_EMPLOYEE;
|
}
|
return null;
|
}
|
|
private String resolveSourceTypeText(String sourceType) {
|
if (SOURCE_MINI_EMPLOYEE.equals(sourceType)) {
|
return "员工端";
|
}
|
return "管理后台";
|
}
|
|
private String firstNonBlank(String... values) {
|
for (String value : values) {
|
if (StringUtils.hasText(value)) {
|
return value.trim();
|
}
|
}
|
return "—";
|
}
|
}
|