From 7e0b172de06b0efb63c90b090d9ed10024b1f9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Wed, 8 Apr 2026 12:40:10 +0800 Subject: [PATCH] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E5=BF=97=20=E8=A1=A5=E9=BD=90=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E5=BF=85=E8=A6=81=E7=9A=84=E8=AE=B0=E5=BD=95=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/log/aspect/LogAspect.java | 20 +++++++-- .../common/log/event/OperLogEvent.java | 30 +++++++++++++ .../common/satoken/utils/LoginHelper.java | 37 ++++++++++++++++ .../org/dromara/system/domain/SysOperLog.java | 30 +++++++++++++ .../system/domain/bo/SysOperLogBo.java | 30 +++++++++++++ .../system/domain/vo/SysOperLogVo.java | 37 ++++++++++++++++ .../service/impl/SysOperLogServiceImpl.java | 6 +++ script/sql/oracle/oracle_ry_vue_5.X.sql | 13 ++++++ script/sql/postgres/postgres_ry_vue_5.X.sql | 13 ++++++ script/sql/ry_vue_5.X.sql | 7 +++ script/sql/sqlserver/sqlserver_ry_vue_5.X.sql | 44 +++++++++++++++++++ 11 files changed, 263 insertions(+), 4 deletions(-) diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index 171e97b0b..fcb61f6fc 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -96,13 +96,25 @@ public class LogAspect { // *========数据库日志=========*// OperLogEvent operLog = new OperLogEvent(); operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + HttpServletRequest request = ServletUtils.getRequest(); // 请求的地址 String ip = ServletUtils.getClientIP(); operLog.setOperIp(ip); - operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); + operLog.setOperUrl(StringUtils.substring(request.getRequestURI(), 0, 255)); + operLog.setClientKey(StringUtils.substring(request.getHeader(LoginHelper.CLIENT_KEY), 0, 32)); LoginUser loginUser = LoginHelper.getLoginUser(); - operLog.setOperName(loginUser.getUsername()); - operLog.setDeptName(loginUser.getDeptName()); + if (ObjectUtil.isNotNull(loginUser)) { + operLog.setOperName(loginUser.getUsername()); + operLog.setUserId(loginUser.getUserId()); + operLog.setDeptId(loginUser.getDeptId()); + operLog.setDeptName(loginUser.getDeptName()); + operLog.setDeviceType(loginUser.getDeviceType()); + operLog.setBrowser(loginUser.getBrowser()); + operLog.setOs(loginUser.getOs()); + if (StringUtils.isBlank(operLog.getClientKey())) { + operLog.setClientKey(loginUser.getClientKey()); + } + } if (e != null) { operLog.setStatus(BusinessStatus.FAIL.ordinal()); @@ -113,7 +125,7 @@ public class LogAspect { String methodName = joinPoint.getSignature().getName(); operLog.setMethod(className + "." + methodName + "()"); // 设置请求方式 - operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + operLog.setRequestMethod(request.getMethod()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); // 设置消耗时间 diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/OperLogEvent.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/OperLogEvent.java index a2b8b1a55..f9aa27d96 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/OperLogEvent.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/event/OperLogEvent.java @@ -58,11 +58,41 @@ public class OperLogEvent implements Serializable { */ private String operName; + /** + * 操作用户ID + */ + private Long userId; + + /** + * 操作部门ID + */ + private Long deptId; + /** * 部门名称 */ private String deptName; + /** + * 客户端 + */ + private String clientKey; + + /** + * 设备类型 + */ + private String deviceType; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + /** * 请求url */ diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java index 37946ea06..0ad29f153 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -4,12 +4,18 @@ import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.parameter.SaLoginParameter; import cn.hutool.core.convert.Convert; +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; import cn.hutool.core.util.ObjectUtil; +import jakarta.servlet.http.HttpServletRequest; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.enums.UserType; +import org.dromara.common.core.utils.ServletUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.ip.AddressUtils; /** @@ -44,6 +50,7 @@ public class LoginHelper { */ public static void login(LoginUser loginUser, SaLoginParameter model) { model = ObjectUtil.defaultIfNull(model, new SaLoginParameter()); + fillRequestContext(loginUser, model); StpUtil.login(loginUser.getLoginId(), model.setExtra(USER_KEY, loginUser.getUserId()) .setExtra(USER_NAME_KEY, loginUser.getUsername()) @@ -54,6 +61,36 @@ public class LoginHelper { StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser); } + /** + * 在登录时补充当前请求上下文,避免登录态中的终端信息缺失。 + * + * @param loginUser 登录用户 + * @param model 登录参数 + */ + private static void fillRequestContext(LoginUser loginUser, SaLoginParameter model) { + HttpServletRequest request = ServletUtils.getRequest(); + if (ObjectUtil.isNull(request)) { + return; + } + String ip = ServletUtils.getClientIP(request); + if (StringUtils.isBlank(loginUser.getIpaddr())) { + loginUser.setIpaddr(ip); + } + if (StringUtils.isBlank(loginUser.getLoginLocation()) && StringUtils.isNotBlank(ip)) { + loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + } + UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); + if (StringUtils.isBlank(loginUser.getBrowser())) { + loginUser.setBrowser(userAgent.getBrowser().getName()); + } + if (StringUtils.isBlank(loginUser.getOs())) { + loginUser.setOs(userAgent.getOs().getName()); + } + if (StringUtils.isBlank(loginUser.getDeviceType()) && StringUtils.isNotBlank(model.getDeviceType())) { + loginUser.setDeviceType(model.getDeviceType()); + } + } + /** * 获取当前 Token 对应的登录用户信息。 * diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOperLog.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOperLog.java index 938dfbdf0..fff077cdc 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOperLog.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOperLog.java @@ -57,11 +57,41 @@ public class SysOperLog implements Serializable { */ private String operName; + /** + * 操作用户ID + */ + private Long userId; + + /** + * 操作部门ID + */ + private Long deptId; + /** * 部门名称 */ private String deptName; + /** + * 客户端 + */ + private String clientKey; + + /** + * 设备类型 + */ + private String deviceType; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + /** * 请求url */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOperLogBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOperLogBo.java index e51ac80e0..454cf803f 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOperLogBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOperLogBo.java @@ -69,11 +69,41 @@ public class SysOperLogBo implements Serializable { */ private String operName; + /** + * 操作用户ID + */ + private Long userId; + + /** + * 操作部门ID + */ + private Long deptId; + /** * 部门名称 */ private String deptName; + /** + * 客户端 + */ + private String clientKey; + + /** + * 设备类型 + */ + private String deviceType; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + /** * 请求URL */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOperLogVo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOperLogVo.java index e99e9bec6..bf1c033eb 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOperLogVo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOperLogVo.java @@ -76,12 +76,49 @@ public class SysOperLogVo implements Serializable { @ExcelProperty(value = "操作人员") private String operName; + /** + * 操作用户ID + */ + @ExcelProperty(value = "操作用户ID") + private Long userId; + + /** + * 操作部门ID + */ + @ExcelProperty(value = "操作部门ID") + private Long deptId; + /** * 部门名称 */ @ExcelProperty(value = "部门名称") private String deptName; + /** + * 客户端 + */ + @ExcelProperty(value = "客户端") + private String clientKey; + + /** + * 设备类型 + */ + @ExcelProperty(value = "设备类型", converter = ExcelDictConvert.class) + @ExcelDictFormat(dictType = "sys_device_type") + private String deviceType; + + /** + * 浏览器类型 + */ + @ExcelProperty(value = "浏览器") + private String browser; + + /** + * 操作系统 + */ + @ExcelProperty(value = "操作系统") + private String os; + /** * 请求URL */ diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java index 175fb0951..84ce7eb38 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java @@ -87,6 +87,12 @@ public class SysOperLogServiceImpl implements ISysOperLogService { .eq(operLog.getStatus() != null, SysOperLog::getStatus, operLog.getStatus()) .like(StringUtils.isNotBlank(operLog.getOperName()), SysOperLog::getOperName, operLog.getOperName()) + .eq(operLog.getUserId() != null, SysOperLog::getUserId, operLog.getUserId()) + .eq(operLog.getDeptId() != null, SysOperLog::getDeptId, operLog.getDeptId()) + .eq(StringUtils.isNotBlank(operLog.getClientKey()), SysOperLog::getClientKey, operLog.getClientKey()) + .eq(StringUtils.isNotBlank(operLog.getDeviceType()), SysOperLog::getDeviceType, operLog.getDeviceType()) + .like(StringUtils.isNotBlank(operLog.getBrowser()), SysOperLog::getBrowser, operLog.getBrowser()) + .like(StringUtils.isNotBlank(operLog.getOs()), SysOperLog::getOs, operLog.getOs()) .between(params.get("beginTime") != null && params.get("endTime") != null, SysOperLog::getOperTime, params.get("beginTime"), params.get("endTime")); } diff --git a/script/sql/oracle/oracle_ry_vue_5.X.sql b/script/sql/oracle/oracle_ry_vue_5.X.sql index 62ab33238..7d1c0c004 100644 --- a/script/sql/oracle/oracle_ry_vue_5.X.sql +++ b/script/sql/oracle/oracle_ry_vue_5.X.sql @@ -664,7 +664,13 @@ create table sys_oper_log ( request_method varchar2(10) default '', operator_type number(1) default 0, oper_name varchar2(50) default '', + user_id number(20) default null, + dept_id number(20) default null, dept_name varchar2(50) default '', + client_key varchar2(32) default '', + device_type varchar2(32) default '', + browser varchar2(50) default '', + os varchar2(50) default '', oper_url varchar2(255) default '', oper_ip varchar2(128) default '', oper_location varchar2(255) default '', @@ -678,6 +684,7 @@ create table sys_oper_log ( alter table sys_oper_log add constraint pk_sys_oper_log primary key (oper_id); create index idx_sys_oper_log_bt on sys_oper_log (business_type); +create index idx_sys_oper_log_uid on sys_oper_log (user_id); create index idx_sys_oper_log_s on sys_oper_log (status); create index idx_sys_oper_log_ot on sys_oper_log (oper_time); @@ -689,7 +696,13 @@ comment on column sys_oper_log.method is '方法名称'; comment on column sys_oper_log.request_method is '请求方式'; comment on column sys_oper_log.operator_type is '操作类别(0其它 1后台用户 2手机端用户)'; comment on column sys_oper_log.oper_name is '操作人员'; +comment on column sys_oper_log.user_id is '操作用户ID'; +comment on column sys_oper_log.dept_id is '操作部门ID'; comment on column sys_oper_log.dept_name is '部门名称'; +comment on column sys_oper_log.client_key is '客户端'; +comment on column sys_oper_log.device_type is '设备类型'; +comment on column sys_oper_log.browser is '浏览器类型'; +comment on column sys_oper_log.os is '操作系统'; comment on column sys_oper_log.oper_url is '请求URL'; comment on column sys_oper_log.oper_ip is '主机地址'; comment on column sys_oper_log.oper_location is '操作地点'; diff --git a/script/sql/postgres/postgres_ry_vue_5.X.sql b/script/sql/postgres/postgres_ry_vue_5.X.sql index 69dedf378..dd9ad6807 100644 --- a/script/sql/postgres/postgres_ry_vue_5.X.sql +++ b/script/sql/postgres/postgres_ry_vue_5.X.sql @@ -662,7 +662,13 @@ create table if not exists sys_oper_log request_method varchar(10) default ''::varchar, operator_type int4 default 0, oper_name varchar(50) default ''::varchar, + user_id int8, + dept_id int8, dept_name varchar(50) default ''::varchar, + client_key varchar(32) default ''::varchar, + device_type varchar(32) default ''::varchar, + browser varchar(50) default ''::varchar, + os varchar(50) default ''::varchar, oper_url varchar(255) default ''::varchar, oper_ip varchar(128) default ''::varchar, oper_location varchar(255) default ''::varchar, @@ -676,6 +682,7 @@ create table if not exists sys_oper_log ); create index idx_sys_oper_log_bt ON sys_oper_log (business_type); +create index idx_sys_oper_log_uid ON sys_oper_log (user_id); create index idx_sys_oper_log_s ON sys_oper_log (status); create index idx_sys_oper_log_ot ON sys_oper_log (oper_time); @@ -687,7 +694,13 @@ comment on column sys_oper_log.method is '方法名称'; comment on column sys_oper_log.request_method is '请求方式'; comment on column sys_oper_log.operator_type is '操作类别(0其它 1后台用户 2手机端用户)'; comment on column sys_oper_log.oper_name is '操作人员'; +comment on column sys_oper_log.user_id is '操作用户ID'; +comment on column sys_oper_log.dept_id is '操作部门ID'; comment on column sys_oper_log.dept_name is '部门名称'; +comment on column sys_oper_log.client_key is '客户端'; +comment on column sys_oper_log.device_type is '设备类型'; +comment on column sys_oper_log.browser is '浏览器类型'; +comment on column sys_oper_log.os is '操作系统'; comment on column sys_oper_log.oper_url is '请求URL'; comment on column sys_oper_log.oper_ip is '主机地址'; comment on column sys_oper_log.oper_location is '操作地点'; diff --git a/script/sql/ry_vue_5.X.sql b/script/sql/ry_vue_5.X.sql index 95b5c2b0f..4af57958b 100644 --- a/script/sql/ry_vue_5.X.sql +++ b/script/sql/ry_vue_5.X.sql @@ -514,7 +514,13 @@ create table sys_oper_log ( request_method varchar(10) default '' comment '请求方式', operator_type int(1) default 0 comment '操作类别(0其它 1后台用户 2手机端用户)', oper_name varchar(50) default '' comment '操作人员', + user_id bigint(20) default null comment '操作用户ID', + dept_id bigint(20) default null comment '操作部门ID', dept_name varchar(50) default '' comment '部门名称', + client_key varchar(32) default '' comment '客户端', + device_type varchar(32) default '' comment '设备类型', + browser varchar(50) default '' comment '浏览器类型', + os varchar(50) default '' comment '操作系统', oper_url varchar(255) default '' comment '请求URL', oper_ip varchar(128) default '' comment '主机地址', oper_location varchar(255) default '' comment '操作地点', @@ -526,6 +532,7 @@ create table sys_oper_log ( cost_time bigint(20) default 0 comment '消耗时间', primary key (oper_id), key idx_sys_oper_log_bt (business_type), + key idx_sys_oper_log_uid (user_id), key idx_sys_oper_log_s (status), key idx_sys_oper_log_ot (oper_time) ) engine=innodb comment = '操作日志记录'; diff --git a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql index 9bf14efa8..46143d457 100644 --- a/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql +++ b/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql @@ -1821,7 +1821,13 @@ CREATE TABLE sys_oper_log request_method nvarchar(10) DEFAULT '' NULL, operator_type int DEFAULT ((0)) NULL, oper_name nvarchar(50) DEFAULT '' NULL, + user_id bigint NULL, + dept_id bigint NULL, dept_name nvarchar(50) DEFAULT '' NULL, + client_key nvarchar(32) DEFAULT '' NULL, + device_type nvarchar(32) DEFAULT '' NULL, + browser nvarchar(50) DEFAULT '' NULL, + os nvarchar(50) DEFAULT '' NULL, oper_url nvarchar(255) DEFAULT '' NULL, oper_ip nvarchar(128) DEFAULT '' NULL, oper_location nvarchar(255) DEFAULT '' NULL, @@ -1840,6 +1846,8 @@ GO CREATE NONCLUSTERED INDEX idx_sys_oper_log_bt ON sys_oper_log (business_type) GO +CREATE NONCLUSTERED INDEX idx_sys_oper_log_uid ON sys_oper_log (user_id) +GO CREATE NONCLUSTERED INDEX idx_sys_oper_log_s ON sys_oper_log (status) GO CREATE NONCLUSTERED INDEX idx_sys_oper_log_ot ON sys_oper_log (oper_time) @@ -1887,12 +1895,48 @@ EXEC sys.sp_addextendedproperty 'TABLE', N'sys_oper_log', 'COLUMN', N'oper_name' GO +EXEC sys.sp_addextendedproperty + 'MS_Description', N'操作用户ID' , + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oper_log', + 'COLUMN', N'user_id' +GO +EXEC sys.sp_addextendedproperty + 'MS_Description', N'操作部门ID' , + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oper_log', + 'COLUMN', N'dept_id' +GO EXEC sys.sp_addextendedproperty 'MS_Description', N'部门名称' , 'SCHEMA', N'dbo', 'TABLE', N'sys_oper_log', 'COLUMN', N'dept_name' GO +EXEC sys.sp_addextendedproperty + 'MS_Description', N'客户端' , + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oper_log', + 'COLUMN', N'client_key' +GO +EXEC sys.sp_addextendedproperty + 'MS_Description', N'设备类型' , + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oper_log', + 'COLUMN', N'device_type' +GO +EXEC sys.sp_addextendedproperty + 'MS_Description', N'浏览器类型' , + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oper_log', + 'COLUMN', N'browser' +GO +EXEC sys.sp_addextendedproperty + 'MS_Description', N'操作系统' , + 'SCHEMA', N'dbo', + 'TABLE', N'sys_oper_log', + 'COLUMN', N'os' +GO EXEC sys.sp_addextendedproperty 'MS_Description', N'请求URL' , 'SCHEMA', N'dbo',