新增操作日志记录

This commit is contained in:
RuoYi 2018-02-27 22:55:46 +08:00
parent dbbead881e
commit f88a906dc9
30 changed files with 465 additions and 81 deletions

View File

@ -1,5 +1,5 @@
-- ----------------------------
-- 1、创建部门表
-- 1、部门表
-- ----------------------------
drop table if exists sys_dept;
create table sys_dept (
@ -28,7 +28,7 @@ insert into sys_dept values('10', '3', '市场二部', '2', '0');
-- ----------------------------
-- 2、创建用户信息表
-- 2、用户信息表
-- ----------------------------
drop table if exists sys_user;
create table sys_user (
@ -55,7 +55,7 @@ insert into sys_user values('2', '1', 'ry', '阳若依', 'ry@163.com', '
-- ----------------------------
-- 3、创建角色信息表
-- 3、角色信息表
-- ----------------------------
drop table if exists sys_role;
create table sys_role (
@ -79,7 +79,7 @@ insert into sys_role values('2', '普通角色', 'common', 0, '2018-01-01', '',
-- ----------------------------
-- 4、创建菜单权限表
-- 4、菜单权限表
-- ----------------------------
drop table if exists sys_menu;
create table sys_menu (
@ -136,7 +136,7 @@ insert into sys_menu values('25', '登录日志查询', '4', '5', '/system/userl
-- ----------------------------
-- 5、创建用户和角色关联表 用户N-1角色
-- 5、用户和角色关联表 用户N-1角色
-- ----------------------------
drop table if exists sys_user_role;
create table sys_user_role (
@ -154,7 +154,7 @@ insert into sys_user_role values ('2', '2');
-- ----------------------------
-- 6、创建角色和菜单关联表 角色1-N菜单
-- 6、角色和菜单关联表 角色1-N菜单
-- ----------------------------
drop table if exists sys_role_menu;
create table sys_role_menu (
@ -178,26 +178,29 @@ insert into sys_role_menu values ('1', '9');
-- ----------------------------
-- 7、创建操作日志管理表
-- 7、操作日志记录
-- ----------------------------
drop table if exists oper_log;
create table oper_log (
operid int(11) not null auto_increment comment '日志主键',
opername varchar(50) default '' comment '操作员名称',
opertime varchar(30) default null comment '操作时间',
opertype varchar(50) default '' comment '操作类型',
opertparam varchar(255) default '' comment '操作参数',
opertip varchar(30) default '' comment '执行地址',
operturl varchar(255) default '' comment '请求URL',
status varchar(3) default '' comment '状态0正常 1错误',
message varchar(255) default '' comment '错误消息',
primary key (operid)
drop table if exists sys_oper_log;
create table sys_oper_log (
oper_id int(11) not null auto_increment comment '日志主键',
title varchar(50) default '' comment '功能请求',
action varchar(50) default '' comment '模块标题',
channel varchar(50) default '' comment '来源渠道',
login_name varchar(50) default '' comment '登录名称',
dept_name varchar(50) default '' comment '部门名称',
opert_url varchar(255) default '' comment '请求URL',
opert_ip varchar(30) default '' comment '操作地址',
oper_param varchar(255) default '' comment '请求参数',
status int(1) default 0 comment '状态0正常 1异常',
error_msg varchar(255) default '' comment '错误消息',
oper_time timestamp default current_timestamp comment '操作时间',
primary key (oper_id)
) engine=innodb auto_increment=100 default charset=utf8;
insert into oper_log values(1, 'admin', '2018-01-01', '系统管理-启用/停用-用户', 'delete.do?id=1', '127.0.0.1', 'system/changeUserStatus', '0', '');
insert into sys_oper_log values(1, '监控管理', '在线用户-踢出用户', 'web', 'admin', '研发部门', 'delete.do?id=1', '127.0.0.1', 'JSON参数', 0, '错误描述', '2018-01-01');
-- ----------------------------
-- 8、创建数据字典表
-- 8、数据字典表
-- ----------------------------
drop table if exists sys_code;
create table sys_code (
@ -233,17 +236,17 @@ insert into sys_code values('system-operlog-status', '1', '失败', '', '', '2')
-- ----------------------------
-- 9、系统访问日志情况信息
-- 9、系统访问记录
-- ----------------------------
drop table if exists sys_logininfor;
create table sys_logininfor (
info_id int(11) not null auto_increment comment '访问ID',
login_name varchar(50) default '' comment '登录名',
status int(1) default 0 comment '登录状态 0成功 1失败',
ipaddr varchar(50) default '' comment '登录IP地址',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
msg varchar(255) default '' comment '提示消息',
info_id int(11) not null auto_increment comment '访问ID',
login_name varchar(50) default '' comment '登录名',
status int(1) default 0 comment '登录状态 0成功 1失败',
ipaddr varchar(50) default '' comment '登录IP地址',
browser varchar(50) default '' comment '浏览器类型',
os varchar(50) default '' comment '操作系统',
msg varchar(255) default '' comment '提示消息',
logondate timestamp default current_timestamp comment '访问时间',
primary key (info_id)
) engine=innodb auto_increment=100 default charset=utf8;
@ -251,7 +254,7 @@ create table sys_logininfor (
insert into sys_logininfor values(1, 'admin', 0 , '127.0.0.1', 'Chrome 45', 'Windows 7', '登录成功' ,'2018-01-01');
-- ----------------------------
-- 10、在线用户
-- 10、在线用户记录
-- ----------------------------
drop table if exists sys_user_online;
create table sys_user_online (

View File

@ -7,23 +7,22 @@ package com.ruoyi.common.constant;
*/
public class UserConstants
{
/** 用户正常状态 */
public static final String USER_NORMAL = "0";
/** 正常状态 */
public static final int NORMAL = 0;
/** 异常状态 */
public static final int EXCEPTION = 1;
/** 用户封禁状态 */
public static final String USER_BLOCKED = "1";
/** 角色正常状态 */
public static final String ROLE_NORMAL = "0";
/** 角色封禁状态 */
public static final String ROLE_BLOCKED = "1";
/** 异常状态 */
public static final String EXCEPTION = "1";
/** 名称是否唯一的返回结果码 */
public final static String NAME_UNIQUE = "0";
public final static String NAME_NOT_UNIQUE = "1";
/**

View File

@ -0,0 +1,168 @@
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import java.util.Map;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.utils.HttpContextUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
import com.ruoyi.project.monitor.operlog.service.IOperLogService;
import com.ruoyi.project.system.user.domain.User;
import lombok.extern.slf4j.Slf4j;
/**
* 操作日志记录处理
*
* @author yangzz
*/
@Aspect
@Component
@Slf4j
public class LogAspect
{
@Autowired
private IOperLogService operLogService;
// 配置织入点
@Pointcut("@annotation(com.ruoyi.framework.aspectj.lang.annotation.Log)")
public void logPointCut()
{
}
/**
* 前置通知 用于拦截操作
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()")
public void doBefore(JoinPoint joinPoint)
{
handleLog(joinPoint, null);
}
/**
* 拦截异常操作
*
* @param joinPoint
* @param e
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfter(JoinPoint joinPoint, Exception e)
{
handleLog(joinPoint, e);
}
private void handleLog(JoinPoint joinPoint, Exception e)
{
try
{
// 获得注解
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null)
{
return;
}
// 获取当前的用户
User currentUser = ShiroUtils.getUser();
// *========数据库日志=========*//
OperLog operLog = new OperLog();
operLog.setStatus(UserConstants.NORMAL);
// 请求的地址
String ip = ShiroUtils.getIp();
operLog.setOpertIp(ip);
operLog.setOpertUrl(HttpContextUtils.getHttpServletRequest().getRequestURI());
if (currentUser != null)
{
operLog.setLoginName(currentUser.getLoginName());
operLog.setDeptName(currentUser.getDept().getDeptName());
}
if (e != null)
{
operLog.setStatus(UserConstants.EXCEPTION);
operLog.setErrorMsg(e.getMessage());
}
// 处理设置注解上的参数
getControllerMethodDescription(controllerLog, operLog);
// 保存数据库
operLogService.insertOperlog(operLog);
}
catch (Exception exp)
{
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param joinPoint 切点
* @return 方法描述
* @throws Exception
*/
public static void getControllerMethodDescription(Log log, OperLog operLog) throws Exception
{
// 设置action动作
operLog.setAction(log.action());
// 设置标题
operLog.setTitle(log.title());
// 设置channel
operLog.setChannel(log.channel());
// 是否需要保存request参数和值
if (log.isSaveRequestData())
{
// 获取参数的信息传入到数据库中
setRequestValue(operLog);
}
}
/**
* 获取请求的参数放到log中
*
* @param operLog
* @param request
*/
private static void setRequestValue(OperLog operLog)
{
if (operLog == null)
operLog = new OperLog();
Map<String, String[]> map = HttpContextUtils.getHttpServletRequest().getParameterMap();
String params = JSONObject.toJSONString(map);
operLog.setOpertParam(params);
}
/**
* 是否存在注解如果存在就获取
*/
private static Log getAnnotationLog(JoinPoint joinPoint) throws Exception
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(Log.class);
}
return null;
}
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.framework.aspectj.lang.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义操作日志记录注解
*
* @author yangzz
*
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
/** 模块 */
String title() default "";
/** 功能 */
String action() default "";
/** 渠道 */
String channel() default "web";
/** 是否保存请求的参数 */
boolean isSaveRequestData() default true;
}

View File

@ -50,7 +50,6 @@ public class OnlineSessionFactory implements SessionFactory
String browser = userAgent.getBrowser().getName();
session.setHost(IpUtils.getIpAddr(request));
session.setBrowser(browser);
session.setHost(request.getLocalAddr() + ":" + request.getLocalPort());
session.setOs(os);
}
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.framework.core.controller;
package com.ruoyi.framework.web.controller;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.project.system.user.domain.User;

View File

@ -1,4 +1,4 @@
package com.ruoyi.framework.core.dao;
package com.ruoyi.framework.web.dao;
import java.util.List;
import javax.annotation.Resource;

View File

@ -1,4 +1,4 @@
package com.ruoyi.framework.core.domain;
package com.ruoyi.framework.web.domain;
import java.util.HashMap;
import java.util.Map;

View File

@ -0,0 +1,35 @@
package com.ruoyi.framework.web.exception;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import com.ruoyi.framework.web.domain.R;
import lombok.extern.slf4j.Slf4j;
/**
* 自定义异常处理器
*
* @author yangzz
*
*/
@Slf4j
@RestControllerAdvice
public class DefaultExceptionHandler
{
@ExceptionHandler(AuthorizationException.class)
public R handleAuthorizationException(AuthorizationException e)
{
log.error(e.getMessage(), e);
return R.error("未授权");
}
@ExceptionHandler(Exception.class)
public R handleException(Exception e)
{
log.error(e.getMessage(), e);
return R.error("服务器错误," + e.getMessage());
}
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.framework.page;
package com.ruoyi.framework.web.page;
import java.util.Map;
import com.ruoyi.common.utils.StringUtils;

View File

@ -1,4 +1,4 @@
package com.ruoyi.framework.page;
package com.ruoyi.framework.web.page;
import java.io.Serializable;
import java.util.List;

View File

@ -1,6 +1,7 @@
package com.ruoyi.project.monitor.online.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@ -9,10 +10,12 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.core.controller.BaseController;
import com.ruoyi.framework.core.domain.R;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.project.monitor.online.domain.OnlineSession;
import com.ruoyi.project.monitor.online.domain.UserOnline;
import com.ruoyi.project.monitor.online.service.IUserOnlineService;
@ -72,32 +75,25 @@ public class UserOnlineController extends BaseController
}
}
@ResponseBody
@Log(title = "监控管理", action = "在线用户-踢出用户")
@RequestMapping("/forceLogout/{sessionId}")
@ResponseBody
public R forceLogout(@PathVariable("sessionId") String sessionId)
{
try
UserOnline online = userOnlineService.selectByOnlineId(sessionId);
if (online == null)
{
UserOnline online = userOnlineService.selectByOnlineId(sessionId);
if (online == null)
{
return R.error("用户已下线。数据不存在");
}
OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
if (onlineSession == null)
{
return R.error("用户已下线。会话不存在");
}
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
online.setStatus(OnlineSession.OnlineStatus.off_line);
userOnlineService.saveByOnline(online);
return R.ok();
return R.error("用户已下线。数据不存在");
}
catch (Exception e)
OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId());
if (onlineSession == null)
{
return R.error(e.getMessage());
return R.error("用户已下线。会话不存在");
}
onlineSession.setStatus(OnlineSession.OnlineStatus.off_line);
online.setStatus(OnlineSession.OnlineStatus.off_line);
userOnlineService.saveByOnline(online);
return R.ok();
}
}

View File

@ -2,7 +2,8 @@ package com.ruoyi.project.monitor.online.dao;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.ruoyi.framework.core.dao.DynamicObjectBaseDao;
import com.ruoyi.framework.web.dao.DynamicObjectBaseDao;
import com.ruoyi.project.monitor.online.domain.UserOnline;
@Repository("userOnlineDao")

View File

@ -0,0 +1,18 @@
package com.ruoyi.project.monitor.operlog.dao;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
/**
* 操作日志 数据层
*
* @author yangzz
*/
public interface IOperLogDao
{
/**
* 新增操作日志
*
* @param operLog 系统日志对象
*/
public void insertOperlog(OperLog operLog);
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.project.monitor.operlog.dao;
import org.springframework.stereotype.Repository;
import com.ruoyi.framework.web.dao.DynamicObjectBaseDao;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
@Repository("operLogDao")
public class OperLogDaoImpl extends DynamicObjectBaseDao implements IOperLogDao
{
/**
* 新增操作日志
*
* @param operLog 系统日志对象
*/
public void insertOperlog(OperLog operLog)
{
this.save("SystemOperLogMapper.insertOperlog", operLog);
}
}

View File

@ -0,0 +1,38 @@
package com.ruoyi.project.monitor.operlog.domain;
import java.util.Date;
import lombok.Data;
/**
* 操作日志记录 oper_log
*
* @author yangzz
*/
@Data
public class OperLog
{
// 日志主键
private Integer operId;
// 模块标题
private String title;
// 功能请求
private String action;
// 来源渠道
private String channel;
// 操作员名称
private String loginName;
// 部门名称
private String deptName;
// 请求url
private String opertUrl;
// 操作地址
private String opertIp;
// 请求参数
private String opertParam;
// 状态0正常 1异常
private int status;
// 错误消息
private String errorMsg;
// 操作时间
private Date operTime;
}

View File

@ -0,0 +1,18 @@
package com.ruoyi.project.monitor.operlog.service;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
/**
* 操作日志 服务层
*
* @author yangzz
*/
public interface IOperLogService
{
/**
* 新增操作日志
*
* @param operLog 系统日志对象
*/
public void insertOperlog(OperLog operLog);
}

View File

@ -0,0 +1,28 @@
package com.ruoyi.project.monitor.operlog.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.project.monitor.operlog.dao.IOperLogDao;
import com.ruoyi.project.monitor.operlog.domain.OperLog;
/**
* 操作日志 服务层处理
*
* @author yangzz
*/
@Service("operLogService")
public class OperLogServiceImpl implements IOperLogService
{
@Autowired
private IOperLogDao operLogDao;
/**
* 新增操作日志
*
* @param operLog 系统日志对象
*/
public void insertOperlog(OperLog operLog)
{
operLogDao.insertOperlog(operLog);
}
}

View File

@ -2,7 +2,7 @@ package com.ruoyi.project.system.logininfor.dao;
import org.springframework.stereotype.Repository;
import com.ruoyi.framework.core.dao.DynamicObjectBaseDao;
import com.ruoyi.framework.web.dao.DynamicObjectBaseDao;
import com.ruoyi.project.system.logininfor.domain.Logininfor;
@Repository("logininforDao")

View File

@ -2,7 +2,8 @@ package com.ruoyi.project.system.menu.dao;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.ruoyi.framework.core.dao.DynamicObjectBaseDao;
import com.ruoyi.framework.web.dao.DynamicObjectBaseDao;
import com.ruoyi.project.system.menu.domain.Menu;
/**

View File

@ -4,7 +4,7 @@ import java.util.List;
import org.springframework.stereotype.Repository;
import com.ruoyi.framework.core.dao.DynamicObjectBaseDao;
import com.ruoyi.framework.web.dao.DynamicObjectBaseDao;
/**
* 角色 数据层处理

View File

@ -5,7 +5,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.ruoyi.framework.core.controller.BaseController;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.project.system.menu.domain.Menu;
import com.ruoyi.project.system.menu.service.IMenuService;
import com.ruoyi.project.system.user.domain.User;

View File

@ -9,8 +9,8 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.core.controller.BaseController;
import com.ruoyi.framework.core.domain.R;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.R;
/**
* 登录验证

View File

@ -10,8 +10,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.framework.core.controller.BaseController;
import com.ruoyi.framework.page.TableDataInfo;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.service.IUserService;

View File

@ -2,7 +2,7 @@ package com.ruoyi.project.system.user.dao;
import java.util.List;
import com.ruoyi.framework.page.PageUtilEntity;
import com.ruoyi.framework.web.page.PageUtilEntity;
import com.ruoyi.project.system.user.domain.User;
/**

View File

@ -4,8 +4,8 @@ import java.util.List;
import org.springframework.stereotype.Repository;
import com.ruoyi.framework.core.dao.DynamicObjectBaseDao;
import com.ruoyi.framework.page.PageUtilEntity;
import com.ruoyi.framework.web.dao.DynamicObjectBaseDao;
import com.ruoyi.framework.web.page.PageUtilEntity;
import com.ruoyi.project.system.user.domain.User;
/**

View File

@ -2,7 +2,7 @@ package com.ruoyi.project.system.user.service;
import java.util.List;
import com.ruoyi.framework.page.PageUtilEntity;
import com.ruoyi.framework.web.page.PageUtilEntity;
import com.ruoyi.project.system.user.domain.User;
/**

View File

@ -4,7 +4,7 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.framework.page.PageUtilEntity;
import com.ruoyi.framework.web.page.PageUtilEntity;
import com.ruoyi.project.system.user.dao.IUserDao;
import com.ruoyi.project.system.user.domain.User;

View File

@ -7,8 +7,8 @@ spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://10.213.24.45:3306/ry?useUnicode=true&characterEncoding=utf8
#url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8
#url: jdbc:mysql://10.213.24.45:3306/ry?useUnicode=true&characterEncoding=utf8
url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8
username: root
password: password
# 初始化大小,最小,最大

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="SystemOperLogMapper">
<resultMap type="OperLog" id="OperLogResult">
<id property="operId" column="oper_id" />
<result property="title" column="title" />
<result property="action" column="action" />
<result property="channel" column="channel" />
<result property="loginName" column="login_name" />
<result property="deptName" column="dept_name" />
<result property="opertUrl" column="opert_url" />
<result property="opertIp" column="opert_ip" />
<result property="opertParam" column="oper_param" />
<result property="status" column="status" />
<result property="errorMsg" column="error_msg" />
<result property="operTime" column="oper_time" />
</resultMap>
<insert id="insertOperlog" parameterType="OperLog">
insert into sys_oper_log(oper_id, title, action, channel, login_name, dept_name, opert_url, opert_ip, oper_param, status, error_msg)
values (#{operId}, #{title}, #{action}, #{channel}, #{loginName}, #{deptName}, #{opertUrl}, #{opertIp}, #{opertParam}, #{status}, #{errorMsg})
</insert>
</mapper>