content: 
  package com.platform.service.impl;
  
  import cn.hutool.core.lang.Dict;
  import cn.hutool.core.util.ObjectUtil;
  import cn.hutool.json.JSONObject;
  import cn.hutool.json.JSONUtil;
  import lombok.RequiredArgsConstructor;
  import com.platform.domain.Log;
  import com.platform.repository.LogRepository;
  import com.platform.service.LogService;
  import com.platform.service.dto.LogQueryCriteria;
  import com.platform.service.mapstruct.LogErrorMapper;
  import com.platform.service.mapstruct.LogSmallMapper;
  import com.platform.utils.*;
  import org.aspectj.lang.ProceedingJoinPoint;
  import org.aspectj.lang.reflect.MethodSignature;
  import org.springframework.data.domain.Page;
  import org.springframework.data.domain.Pageable;
  import org.springframework.stereotype.Service;
  import org.springframework.transaction.annotation.Transactional;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RequestParam;
  
  
  import javax.servlet.http.HttpServletResponse;
  import java.io.IOException;
  import java.lang.reflect.Method;
  import java.lang.reflect.Parameter;
  import java.util.*;
  
  /**
   * @author AllDataDC
   * @date 2023-01-27
   */
  @Service
  @RequiredArgsConstructor
  public class LogServiceImpl implements LogService {
      private final LogRepository logRepository;
      private final LogErrorMapper logErrorMapper;
      private final LogSmallMapper logSmallMapper;
  
      @Override
      public Object queryAll(LogQueryCriteria criteria, Pageable pageable) {
          Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
          String status = "ERROR";
          if (status.equals(criteria.getLogType())) {
              return PageUtil.toPage(page.map(logErrorMapper::toDto));
          }
          return page;
      }
  
      @Override
      public List<Log> queryAll(LogQueryCriteria criteria) {
          return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)));
      }
  
      @Override
      public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) {
          Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
          return PageUtil.toPage(page.map(logSmallMapper::toDto));
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log) {
          if (log == null) {
              throw new IllegalArgumentException("Log 不能为 null!");
          }
          MethodSignature signature = (MethodSignature) joinPoint.getSignature();
          Method method = signature.getMethod();
          com.platform.annotation.Log aopLog = method.getAnnotation(com.platform.annotation.Log.class);
  
          // 方法路径
          String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
  
          // 描述
          log.setDescription(aopLog.value());
          
          log.setRequestIp(ip);
          log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
          log.setMethod(methodName);
          log.setUsername(username);
          log.setParams(getParameter(method, joinPoint.getArgs()));
          // 记录登录用户，隐藏密码信息
          if(signature.getName().equals("login") && StringUtils.isNotEmpty(log.getParams())){
              JSONObject obj = JSONUtil.parseObj(log.getParams());
              log.setUsername(obj.getStr("username", ""));
              log.setParams(JSONUtil.toJsonStr(Dict.create().set("username", log.getUsername())));
          }
          log.setBrowser(browser);
          logRepository.save(log);
      }
  
      /**
       * 根据方法和传入的参数获取请求参数
       */
      private String getParameter(Method method, Object[] args) {
          List<Object> argList = new ArrayList<>();
          Parameter[] parameters = method.getParameters();
          for (int i = 0; i < parameters.length; i++) {
              //将RequestBody注解修饰的参数作为请求参数
              RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
              if (requestBody != null) {
                  argList.add(args[i]);
              }
              //将RequestParam注解修饰的参数作为请求参数
              RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
              if (requestParam != null) {
                  Map<String, Object> map = new HashMap<>(2);
                  String key = parameters[i].getName();
                  if (!StringUtils.isEmpty(requestParam.value())) {
                      key = requestParam.value();
                  }
                  map.put(key, args[i]);
                  argList.add(map);
              }
          }
          if (argList.isEmpty()) {
              return "";
          }
          return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : JSONUtil.toJsonStr(argList);
      }
  
      @Override
      public Object findByErrDetail(Long id) {
          Log log = logRepository.findById(id).orElseGet(Log::new);
          ValidationUtil.isNull(log.getId(), "Log", "id", id);
          byte[] details = log.getExceptionDetail();
          return Dict.create().set("exception", new String(ObjectUtil.isNotNull(details) ? details : "".getBytes()));
      }
  
      @Override
      public void download(List<Log> logs, HttpServletResponse response) throws IOException {
          List<Map<String, Object>> list = new ArrayList<>();
          for (Log log : logs) {
              Map<String, Object> map = new LinkedHashMap<>();
              map.put("用户名", log.getUsername());
              map.put("IP", log.getRequestIp());
              map.put("IP来源", log.getAddress());
              map.put("描述", log.getDescription());
              map.put("浏览器", log.getBrowser());
              map.put("请求耗时/毫秒", log.getTime());
              map.put("异常详情", new String(ObjectUtil.isNotNull(log.getExceptionDetail()) ? log.getExceptionDetail() : "".getBytes()));
              map.put("创建日期", log.getCreateTime());
              list.add(map);
          }
          FileUtil.downloadExcel(list, response);
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void delAllByError() {
          logRepository.deleteByLogType("ERROR");
      }
  
      @Override
      @Transactional(rollbackFor = Exception.class)
      public void delAllByInfo() {
          logRepository.deleteByLogType("INFO");
      }
  }
  