Переглянути джерело

登录日志添加操作系统、浏览器类型、部门名称、登陆地点字段

ZJY 8 місяців тому
батько
коміт
0e13931ecc

+ 1 - 1
base-modules/pom.xml

@@ -10,7 +10,7 @@
 
     <modules>
         <module>service-gen</module>
-        <module>service-job</module>
+<!--        <module>service-job</module>-->
         <module>service-file</module>
         <module>service-system</module>
     </modules>

+ 11 - 0
base-modules/service-system/service-system-biz/pom.xml

@@ -48,6 +48,17 @@
             <artifactId>ruoyi-common-swagger</artifactId>
         </dependency>
 
+        <!-- 解析客户端操作系统、浏览器等 -->
+        <dependency>
+            <groupId>eu.bitwalker</groupId>
+            <artifactId>UserAgentUtils</artifactId>
+            <version>1.21</version>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 41 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/SysLogininfor.java

@@ -51,6 +51,26 @@ public class SysLogininfor extends BaseEntity
      */
     private String createBy;
 
+    /**
+     * 登陆地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 部门名称
+     */
+    private String deptName;
+
     public String getSearchValue() {
         return searchValue;
     }
@@ -168,4 +188,25 @@ public class SysLogininfor extends BaseEntity
     {
         this.createBy = createBy;
     }
+
+    public String getLoginLocation() {return loginLocation;}
+
+    public void setLoginLocation(String loginLocation) {this.loginLocation = loginLocation;}
+
+    public String getBrowser() {return browser;}
+
+    public void setBrowser(String browser) {this.browser = browser;}
+
+    public String getOs() {return os;}
+
+    public void setOs(String os) {this.os = os;}
+    public String getDeptName()
+    {
+        return deptName;
+    }
+
+    public void setDeptName(String deptName)
+    {
+        this.deptName = deptName;
+    }
 }

+ 131 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/domain/WjConfig.java

@@ -0,0 +1,131 @@
+package com.usky.system.domain;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 读取项目相关配置
+ *
+ * @author yq
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "wj")
+public class WjConfig {
+    /** 项目名称 */
+    private String name;
+
+    /** 版本 */
+    private String version;
+
+    /** 版权年份 */
+    private String copyrightYear;
+
+    /** 实例演示开关 */
+    private boolean demoEnabled;
+
+    /** 上传路径 */
+    private static String profile;
+
+    /** 获取地址开关 */
+    private static boolean addressEnabled;
+    /** 验证码开关 */
+    private boolean codeEnabled;
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getVersion()
+    {
+        return version;
+    }
+
+    public void setVersion(String version)
+    {
+        this.version = version;
+    }
+
+    public String getCopyrightYear()
+    {
+        return copyrightYear;
+    }
+
+    public void setCopyrightYear(String copyrightYear)
+    {
+        this.copyrightYear = copyrightYear;
+    }
+
+    public boolean isDemoEnabled()
+    {
+        return demoEnabled;
+    }
+
+    public void setDemoEnabled(boolean demoEnabled)
+    {
+        this.demoEnabled = demoEnabled;
+    }
+
+
+    public boolean isCodeEnabled()
+    {
+        return codeEnabled;
+    }
+
+    public void setCodeEnabled(boolean codeEnabled)
+    {
+        this.codeEnabled = codeEnabled;
+    }
+
+    public static String getProfile()
+    {
+        return profile;
+    }
+
+    public void setProfile(String profile)
+    {
+        WjConfig.profile = profile;
+    }
+
+    public static boolean isAddressEnabled()
+    {
+        return addressEnabled;
+    }
+
+    public void setAddressEnabled(boolean addressEnabled)
+    {
+        WjConfig.addressEnabled = addressEnabled;
+    }
+
+    /**
+     * 获取头像上传路径
+     */
+    public static String getAvatarPath()
+    {
+        return getProfile() + "/avatar";
+    }
+
+    /**
+     * 获取下载路径
+     */
+    public static String getDownloadPath()
+    {
+        return getProfile() + "/download/";
+    }
+
+    /**
+     * 获取上传路径
+     */
+    public static String getUploadPath()
+    {
+        return getProfile() + "/upload";
+    }
+}
+

+ 50 - 30
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/SysLoginService.java

@@ -8,11 +8,11 @@ import com.usky.common.core.util.*;
 import com.usky.common.redis.core.RedisHelper;
 import com.usky.common.security.utils.SecurityUtils;
 import com.usky.common.core.exception.BusinessException;
-import com.usky.system.RuoYiSystemApplication;
 import com.usky.system.domain.*;
 import com.usky.system.domain.constants.UserConstants;
 import com.usky.system.model.LoginUser;
 import com.usky.system.service.enums.UserStatus;
+import com.usky.system.service.util.AsyncManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -47,6 +47,9 @@ public class SysLoginService {
     @Autowired
     private  SysTenantService sysTenantService;
 
+    @Autowired
+    AsyncManager asyncManager;
+
 
     public final String LOGIN_QRCODE_VERIFY ="login_qrcode_verify";
 
@@ -56,21 +59,22 @@ public class SysLoginService {
      * 登录
      */
     public LoginUser login(String username, String password, Integer tenantId) {
+
         // 用户名或密码为空 错误
         if (StringUtils.isAnyBlank(username, password)) {
-            recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "用户/密码必须填写");
+            asyncManager.insertLog(tenantId,username,Constants.LOGIN_FAIL, "用户/密码必须填写", null);
             throw new BusinessException("用户/密码必须填写");
         }
         // 密码如果不在指定范围内 错误
         if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                 || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
-            recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
+            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
             throw new BusinessException("用户密码不在指定范围");
         }
         // 用户名不在指定范围内 错误
         if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                 || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
-            recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "用户名不在指定范围");
+            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户名不在指定范围", null);
             throw new BusinessException("用户名不在指定范围");
         }
 
@@ -84,17 +88,18 @@ public class SysLoginService {
 
         SysUserVO user = loginUser.getSysUser();
         if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
-            recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
+            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
-            recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
+            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已停用");
         }
         if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
-            recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "用户密码错误");
+            asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "用户密码错误", null);
             throw new BusinessException("用户不存在/密码错误");
         }
+
         //判断租户状态是否停用
         LambdaQueryWrapper<SysTenant> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.select(SysTenant::getStatus, SysTenant::getDomain)
@@ -104,14 +109,26 @@ public class SysLoginService {
             String status = list.get(0).getStatus();
             String domain = list.get(0).getDomain();
             if(status.equals("1")){
-                recordLogininfor(tenantId,username, Constants.LOGIN_FAIL, "系统已停用,请联系管理员");
+                asyncManager.insertLog(tenantId,username, Constants.LOGIN_FAIL, "系统已停用,请联系管理员", null);
                 throw new BusinessException("对不起,系统已停用,请联系管理员");
             }
         }
 
+        // 获取部门ID
+        LambdaQueryWrapper<SysUser> deptQueryWrapper = Wrappers.lambdaQuery();
+        deptQueryWrapper.select(SysUser::getDeptId)
+                .eq(SysUser::getDelFlag, 0)
+                .eq(SysUser::getTenantId, tenantId)
+                .and(w -> w.eq(SysUser::getUserName, username).or().eq(SysUser::getPhonenumber, username));
+        SysUser sysUser = sysUserService.getOne(deptQueryWrapper);
+        Integer deptId = 0; // 默认值为0,假设0表示没有部门ID
+        if (sysUser != null) {
+            deptId = sysUser.getDeptId().intValue(); // 将Long转换为Integer
+        }
+
         SysPerson sysPerson = sysPersonService.getsysPerson(user.getUserId());
         loginUser.setSysPerson(sysPerson);
-        recordLogininfor(tenantId,username, Constants.LOGIN_SUCCESS, "登录成功");
+        asyncManager.insertLog(tenantId,username, Constants.LOGIN_SUCCESS, "登录成功", deptId);
         return loginUser;
     }
 
@@ -123,32 +140,32 @@ public class SysLoginService {
         if (!StringUtils.isBlank(username) && !StringUtils.isBlank(password)) {
             // 用户名或密码为空 错误
             if (StringUtils.isAnyBlank(username, password)) {
-                recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户/密码必须填写");
+                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户/密码必须填写", null);
                 throw new BusinessException("用户/密码必须填写");
             }
 
             // 密码如果不在指定范围内 错误
             if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                     || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
-                recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码不在指定范围");
+                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码不在指定范围", null);
                 throw new BusinessException("用户密码不在指定范围");
             }
 
             // 用户名不在指定范围内 错误
             if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                     || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
-                recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户名不在指定范围");
+                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户名不在指定范围", null);
                 throw new BusinessException("用户名不在指定范围");
             }
 
 
             if (Objects.isNull(loginUser)) {
-                recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户不存在");
+                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户不存在", null);
                 throw new BusinessException("用户不存在");
             }
 
             if (!SecurityUtils.matchesPassword(password, loginUser.getPassword())) {
-                recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码错误");
+                asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户密码错误", null);
                 throw new BusinessException("用户不存在/密码错误");
             }
         } else if(!StringUtils.isBlank(phone) && !StringUtils.isBlank(verify)) {
@@ -176,21 +193,32 @@ public class SysLoginService {
         }
 
         if (UserStatus.DELETED.getCode().equals(loginUser.getDelFlag())) {
-            recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
+            asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "对不起,您的账号已被删除", null);
             throw new BusinessException("对不起,您的账号:" + username + " 已被删除");
         }
         if (UserStatus.DISABLE.getCode().equals(loginUser.getStatus())) {
-            recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
+            asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_FAIL, "用户已停用,请联系管理员", null);
             throw new BusinessException("对不起,您的账号:" + loginUser.getUserName() + " 已停用");
         }
 
-        recordLogininfor(tenantId,loginUser.getUserName(), Constants.LOGIN_SUCCESS, "登录成功");
+        // 获取部门ID
+        LambdaQueryWrapper<SysUser> deptQueryWrapper = Wrappers.lambdaQuery();
+        deptQueryWrapper.select(SysUser::getDeptId)
+                .eq(SysUser::getDelFlag, 0)
+                .eq(SysUser::getTenantId, tenantId)
+                .and(w -> w.eq(SysUser::getUserName, username).or().eq(SysUser::getPhonenumber, username));
+        SysUser sysUser = sysUserService.getOne(deptQueryWrapper);
+        Integer deptId = 0; // 默认值为0,假设0表示没有部门ID
+        if (sysUser != null) {
+            deptId = sysUser.getDeptId().intValue(); // 将Long转换为Integer
+        }
+        asyncManager.insertLog(tenantId,loginUser.getUserName(), Constants.LOGIN_SUCCESS, "登录成功", deptId);
         return loginUser;
     }
 
 
     public void logout(Integer tenantId,String loginName) {
-        recordLogininfor(tenantId,loginName, Constants.LOGOUT, "退出成功");
+        asyncManager.insertLog(tenantId,loginName, Constants.LOGOUT, "退出成功", null);
     }
 
     /**
@@ -216,18 +244,10 @@ public class SysLoginService {
         sysUser.setNickName(username);
         sysUser.setPassword(SecurityUtils.encryptPassword(password));
         sysUserService.register(BeanMapperUtils.map(sysUser, SysUser.class));
-        recordLogininfor(SecurityUtils.getTenantId(),username, Constants.REGISTER, "注册成功");
+        asyncManager.insertLog(SecurityUtils.getTenantId(),username, Constants.REGISTER, "注册成功", null);
     }
 
-    /**
-     * 记录登录信息
-     *
-     * @param username 用户名
-     * @param status   状态
-     * @param message  消息内容
-     * @return
-     */
-    public void recordLogininfor(Integer tenantId,String username, String status, String message) {
+    /*public void recordLogininfor(Integer tenantId,String username, String status, String message) {
         SysLogininforVO logininfor = new SysLogininforVO();
         logininfor.setUserName(username);
         logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
@@ -253,7 +273,7 @@ public class SysLoginService {
         }
         LOGGER.debug(JsonUtils.toJson(logininfor));
         sysLogininforService.insertLogininfor(BeanMapperUtils.map(logininfor, SysLogininfor.class));
-    }
+    }*/
 
 
     public String getQrCodeResult(@RequestParam String qrCode){
@@ -262,7 +282,7 @@ public class SysLoginService {
             String result = String.valueOf(o);
             return result;
         }
-       return null;
+        return null;
     }
 
 

+ 45 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/util/AddressUtils.java

@@ -0,0 +1,45 @@
+package com.usky.system.service.util;
+
+import cn.hutool.http.HttpUtil;
+import com.ruoyi.common.core.utils.ip.IpUtils;
+import com.usky.system.domain.WjConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
+
+/**
+ * 获取地址类
+ *
+ * @author xy
+ */
+public class AddressUtils {
+    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
+
+    // IP地址查询
+    public static  String IP_URL = "http://whois.pconline.com.cn/ip.jsp?ip=";
+
+    // 未知地址
+    public static final String UNKNOWN = "未知地址";
+
+    public static String getRealAddressByIP(String ip) {
+        // 内网不查询
+        if (IpUtils.internalIp(ip)) {
+            return "内网IP";
+        }
+        if (WjConfig.isAddressEnabled()) {
+            try {
+                String url = IP_URL + ip;
+                String rspStr = HttpUtil.get(url);
+                log.info("ip is {}, repStr is {}, url is {}", ip, rspStr, url);
+                if (StringUtils.isEmpty(rspStr.trim())) {
+                    log.error("获取地理位置异常 {}, {}", ip, rspStr);
+                    return UNKNOWN;
+                }
+                return rspStr.trim();
+            } catch (Exception e) {
+                log.error("获取地理位置异常 {}", ip);
+            }
+        }
+        return UNKNOWN;
+    }
+}

+ 106 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/util/AsyncFactory.java

@@ -0,0 +1,106 @@
+package com.usky.system.service.util;
+
+
+import com.alibaba.fastjson.JSON;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.utils.ServletUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.ip.IpUtils;
+import com.usky.common.core.util.SpringContextUtils;
+import com.usky.system.domain.SysLogininfor;
+import com.usky.system.domain.SysOperLog;
+import com.usky.system.service.ISysLogininforService;
+import com.usky.system.service.ISysOperLogService;
+import com.usky.system.service.SysLoginService;
+import eu.bitwalker.useragentutils.UserAgent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.TimerTask;
+
+/**
+ * @description: 异步工厂(产生任务用)
+ * @author: XiaoYu
+ * @date: 2024/08/20 13:58
+ */
+public class AsyncFactory
+{
+    private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
+
+    /**
+     * 记录登录信息
+     *
+     * @param username 用户名
+     * @param status 状态
+     * @param message 消息
+     * @param args 列表
+     * @return 任务task
+     */
+    public static void recordLoginInfo(final Integer tenantId,final String username,final String status, final String message, final Integer deptId,
+                                       final Object... args) {
+        final eu.bitwalker.useragentutils.UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+        final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
+        String address = AddressUtils.getRealAddressByIP(ip);
+        StringBuilder s = new StringBuilder();
+        s.append(getBlock(ip));
+        s.append(address);
+        s.append(getBlock(username));
+        s.append(getBlock(status));
+        s.append(getBlock(message));
+        // 打印信息到日志
+        sys_user_logger.info(s.toString(), args);
+        // 获取客户端操作系统
+        String os = userAgent.getOperatingSystem().getName();
+        // 获取客户端浏览器
+        String browser = userAgent.getBrowser().getName();
+        // 封装对象
+        SysLogininfor logininfor = new SysLogininfor();
+        logininfor.setUserName(username);
+        logininfor.setIpaddr(ip);
+        logininfor.setLoginLocation(address);
+        logininfor.setBrowser(browser);
+        logininfor.setOs(os);
+        logininfor.setMsg(message);
+        logininfor.setCreateBy(username);
+        logininfor.setTenantId(tenantId);
+        logininfor.setDeptId(deptId);
+        // 日志状态
+        if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
+            logininfor.setStatus(String.valueOf(Constants.LOGIN_SUCCESS_STATUS)); // 使用String.valueOf进行转换
+        } else if (Constants.LOGIN_FAIL.equals(status)) {
+            logininfor.setStatus(String.valueOf(Constants.LOGIN_FAIL_STATUS)); // 使用String.valueOf进行转换
+        }
+        sys_user_logger.info("log is {}", JSON.toJSONString(logininfor));
+        // 插入数据
+        SpringContextUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
+    }
+
+    public static String getBlock(Object msg)
+    {
+        if (msg == null)
+        {
+            msg = "";
+        }
+        return "[" + msg.toString() + "]";
+    }
+
+    /**
+     * 操作日志记录
+     *
+     * @param operLog 操作日志信息
+     * @return 任务task
+     */
+    public static TimerTask recordOper(final SysOperLog operLog)
+    {
+        return new TimerTask()
+        {
+            @Override
+            public void run()
+            {
+                // 远程查询操作地点
+                operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
+                SpringContextUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
+            }
+        };
+    }
+}

+ 45 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/util/AsyncManager.java

@@ -0,0 +1,45 @@
+package com.usky.system.service.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @description: 异步任务管理器
+ * @author: XiaoYu
+ * @date: 2024/08/20 13:58
+ */
+@Component
+public class AsyncManager {
+
+    private static final Logger logger = LoggerFactory.getLogger(AsyncManager.class);
+
+    /**
+     * 异步操作任务调度线程池
+     */
+
+    private static final ThreadPoolExecutor executorEvent = new ThreadPoolExecutor(
+            20, 30, 0L, TimeUnit.MILLISECONDS,
+            new ArrayBlockingQueue<Runnable>(1024),
+            new ThreadPoolExecutor.AbortPolicy()
+    );
+
+
+    public void insertLog(Integer tenantId, final String username, final String status, final String message, final Integer deptId) {
+        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        RequestContextHolder.setRequestAttributes(sra, true);
+        executorEvent.execute(() -> {
+            logger.info("new Log is {} , {}", username, message);
+            AsyncFactory.recordLoginInfo(tenantId, username, status, message, deptId);
+        });
+    }
+
+
+}
+

+ 16 - 0
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/vo/SysLoginExportVO.java

@@ -40,6 +40,10 @@ public class SysLoginExportVO {
     @Excel(name = "用户名称")
     private String userName;
 
+    /** 组织机构 */
+    @Excel(name = "组织机构")
+    private String deptName;
+
     /** 登录状态 0成功 1失败 */
     @Excel(name = "登录状态")
     private String status;
@@ -51,4 +55,16 @@ public class SysLoginExportVO {
     /** 访问时间 */
     @Excel(name = "访问时间")
     private LocalDateTime accessTime;
+
+    /** 登陆地点 */
+    @Excel(name = "登陆地点")
+    private String loginLocation;
+
+    /** 浏览器类型 */
+    @Excel(name = "浏览器类型")
+    private String browser;
+
+    /** 操作系统 */
+    @Excel(name = "操作系统")
+    private String os;
 }

+ 9 - 1
base-modules/service-system/service-system-biz/src/main/resources/config/application-dev.yml

@@ -81,4 +81,12 @@ spring:
     enable: true
   mvc:
     pathmatch:
-      matching-strategy: ant_path_matcher
+      matching-strategy: ant_path_matcher
+# project
+wj.name: xy
+wj.version: 3.6.0
+wj.copyrightYear: 2021
+wj.demoEnabled: true
+wj.addressEnabled: true
+wj.captchaType: math
+wj.codeEnabled: false

+ 9 - 1
base-modules/service-system/service-system-biz/src/main/resources/config/application-prod.yml

@@ -81,4 +81,12 @@ spring:
     enable: true
   mvc:
     pathmatch:
-      matching-strategy: ant_path_matcher
+      matching-strategy: ant_path_matcher
+# project
+wj.name: xy
+wj.version: 3.6.0
+wj.copyrightYear: 2021
+wj.demoEnabled: true
+wj.addressEnabled: true
+wj.captchaType: math
+wj.codeEnabled: false

+ 88 - 18
base-modules/service-system/service-system-biz/src/main/resources/mapper/system/SysLogininforMapper.xml

@@ -12,8 +12,12 @@
 		<result property="msg"           column="msg"               />
 		<result property="accessTime"    column="access_time"       />
 		<result property="deptId"        column="dept_id"           />
+		<result property="deptName"      column="dept_name"         />
 		<result property="tenantId"      column="tenant_id"         />
 		<result property="createBy"      column="create_by"         />
+		<result property="loginLocation"    column="login_location"       />
+		<result property="browser"    column="browser"       />
+		<result property="os"    column="os"       />
 	</resultMap>
 
 	<insert id="insertLogininfor" parameterType="com.usky.system.domain.SysLogininfor">
@@ -27,6 +31,9 @@
 			<if test="deptId != null"> dept_id, </if>
 			<if test="tenantId != null"> tenant_id, </if>
 			<if test="createBy != null"> create_by, </if>
+			<if test="loginLocation != null"> login_location, </if>
+			<if test="browser != null"> browser, </if>
+			<if test="os != null"> os, </if>
 		</trim>
 		values
 		<trim prefix="(" suffix=")" suffixOverrides=",">
@@ -38,60 +45,123 @@
 			<if test="deptId != null"> #{deptId},</if>
 			<if test="tenantId != null"> #{tenantId},</if>
 			<if test="createBy != null"> #{createBy},</if>
+			<if test="loginLocation != null"> #{loginLocation},</if>
+			<if test="browser != null"> #{browser},</if>
+			<if test="os != null"> #{os},</if>
 		</trim>
 	</insert>
 
+	<!--	<select id="selectLogininforList" parameterType="com.usky.system.domain.SysLogininfor" resultMap="SysLogininforResult">-->
+	<!--		select info_id, user_name, ipaddr, status, msg, access_time,login_location, browser, os from sys_logininfor d-->
+	<!--		<where>-->
+	<!--			<if test="ipaddr != null and ipaddr != ''">-->
+	<!--				AND ipaddr like concat('%', #{ipaddr}, '%')-->
+	<!--			</if>-->
+	<!--			<if test="status != null and status != ''">-->
+	<!--				AND status = #{status}-->
+	<!--			</if>-->
+	<!--			<if test="userName != null and userName != ''">-->
+	<!--				AND user_name like concat('%', #{userName}, '%')-->
+	<!--			</if>-->
+	<!--			<if test="params.beginTime != null and params.beginTime != ''">&lt;!&ndash; 开始时间检索 &ndash;&gt;-->
+	<!--				and date_format(access_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')-->
+	<!--			</if>-->
+	<!--			<if test="params.endTime != null and params.endTime != ''">&lt;!&ndash; 结束时间检索 &ndash;&gt;-->
+	<!--				and date_format(access_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')-->
+	<!--			</if>-->
+	<!--			<if test="1 == 1">-->
+	<!--				and tenant_id = #{tenantId}-->
+	<!--			</if>-->
+	<!--			&lt;!&ndash; 数据范围过滤 &ndash;&gt;-->
+	<!--			${params.dataScope}-->
+	<!--		</where>-->
+	<!--		order by info_id desc-->
+	<!--	</select>-->
+
 	<select id="selectLogininforList" parameterType="com.usky.system.domain.SysLogininfor" resultMap="SysLogininforResult">
-		select info_id, user_name, ipaddr, status, msg, access_time from sys_logininfor d
+		select d.info_id, d.user_name, d.ipaddr, d.status, d.msg, d.access_time, d.login_location, d.browser, d.os, sd.dept_name
+		from sys_logininfor d
+		left join sys_dept sd on d.dept_id = sd.dept_id
 		<where>
 			<if test="ipaddr != null and ipaddr != ''">
-				AND ipaddr like concat('%', #{ipaddr}, '%')
+				AND d.ipaddr like concat('%', #{ipaddr}, '%')
 			</if>
 			<if test="status != null and status != ''">
-				AND status = #{status}
+				AND d.status = #{status}
 			</if>
 			<if test="userName != null and userName != ''">
-				AND user_name like concat('%', #{userName}, '%')
+				AND d.user_name like concat('%', #{userName}, '%')
 			</if>
 			<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
-				and date_format(access_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+				and date_format(d.access_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
 			</if>
 			<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
-				and date_format(access_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+				and date_format(d.access_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
 			</if>
 			<if test="1 == 1">
-				and tenant_id = #{tenantId}
+				and d.tenant_id = #{tenantId}
 			</if>
 			<!-- 数据范围过滤 -->
 			${params.dataScope}
 		</where>
-		order by info_id desc
+		order by d.info_id desc
 	</select>
 
+	<!--	<select id="selectLogininforListExport" parameterType="com.usky.system.domain.SysLogininfor" resultType="com.usky.system.service.vo.SysLoginExportVO">-->
+	<!--		select info_id, ipaddr, user_name, (case status when '0' then '成功' else '失败' end) as status, msg, access_time,login_location, browser, os  from sys_logininfor d-->
+	<!--		<where>-->
+	<!--			<if test="ipaddr != null and ipaddr != ''">-->
+	<!--				AND ipaddr like concat('%', #{ipaddr}, '%')-->
+	<!--			</if>-->
+	<!--			<if test="status != null and status != ''">-->
+	<!--				AND status = #{status}-->
+	<!--			</if>-->
+	<!--			<if test="userName != null and userName != ''">-->
+	<!--				AND user_name like concat('%', #{userName}, '%')-->
+	<!--			</if>-->
+	<!--			<if test="params.beginTime != null and params.beginTime != ''">&lt;!&ndash; 开始时间检索 &ndash;&gt;-->
+	<!--				and date_format(access_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')-->
+	<!--			</if>-->
+	<!--			<if test="params.endTime != null and params.endTime != ''">&lt;!&ndash; 结束时间检索 &ndash;&gt;-->
+	<!--				and date_format(access_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')-->
+	<!--			</if>-->
+	<!--			<if test="1 == 1">-->
+	<!--				and tenant_id = #{tenantId}-->
+	<!--			</if>-->
+	<!--			${params.dataScope}-->
+	<!--		</where>-->
+	<!--		order by info_id desc-->
+	<!--	</select>-->
+
 	<select id="selectLogininforListExport" parameterType="com.usky.system.domain.SysLogininfor" resultType="com.usky.system.service.vo.SysLoginExportVO">
-		select info_id, ipaddr, user_name, (case status when '0' then '成功' else '失败' end) as status, msg, access_time from sys_logininfor d
+		select d.info_id, d.ipaddr, d.user_name,
+		(case when d.status = '0' then '成功' else '失败' end) as status,
+		d.msg, d.access_time, d.login_location, d.browser, d.os,
+		sd.dept_name
+		from sys_logininfor d
+		left join sys_dept sd on d.dept_id = sd.dept_id
 		<where>
 			<if test="ipaddr != null and ipaddr != ''">
-				AND ipaddr like concat('%', #{ipaddr}, '%')
+				AND d.ipaddr like concat('%', #{ipaddr}, '%')
 			</if>
 			<if test="status != null and status != ''">
-				AND status = #{status}
+				AND d.status = #{status}
 			</if>
 			<if test="userName != null and userName != ''">
-				AND user_name like concat('%', #{userName}, '%')
+				AND d.user_name like concat('%', #{userName}, '%')
 			</if>
 			<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
-				and date_format(access_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
+				and date_format(d.access_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
 			</if>
 			<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
-				and date_format(access_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
+				and date_format(d.access_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
 			</if>
 			<if test="1 == 1">
-				and tenant_id = #{tenantId}
+				and d.tenant_id = #{tenantId}
 			</if>
 			${params.dataScope}
 		</where>
-		order by info_id desc
+		order by d.info_id desc
 	</select>
 
 	<delete id="deleteLogininforByIds" parameterType="Long">
@@ -102,7 +172,7 @@
 	</delete>
 
 	<update id="cleanLogininfor">
-        truncate table sys_logininfor
-    </update>
+		truncate table sys_logininfor
+	</update>
 
 </mapper>