提交 4d27926e 编写于 作者: zlt2000's avatar zlt2000

新增审计日志功能(支持spEL表达式)

上级 5167a6b5
......@@ -12,6 +12,8 @@ import com.central.common.annotation.LoginUser;
import com.central.common.constant.CommonConstant;
import com.central.common.model.*;
import com.central.common.utils.ExcelUtil;
//import com.central.log.annotation.AuditLog;
import com.central.log.annotation.AuditLog;
import com.central.search.client.service.IQueryService;
import com.central.search.model.LogicDelDto;
import com.central.search.model.SearchDto;
......@@ -118,7 +120,8 @@ public class SysUserController {
* @param sysUser
*/
@PutMapping("/users")
@CachePut(value = "user", key = "#sysUser.username")
@CachePut(value = "user", key = "#sysUser.username", unless="#result == null")
//@AuditLog(operation = "'更新用户:' + #sysUser")
public void updateSysUser(@RequestBody SysUser sysUser) {
appUserService.updateById(sysUser);
}
......@@ -187,6 +190,7 @@ public class SysUserController {
* @param id
*/
@PutMapping(value = "/users/{id}/password")
//@AuditLog(operation = "'重置用户密码:' + #id")
public Result resetPassword(@PathVariable Long id) {
if (checkAdmin(id)) {
return Result.failed(ADMIN_CHANGE_MSG);
......@@ -213,6 +217,7 @@ public class SysUserController {
* @param id
*/
@DeleteMapping(value = "/users/{id}")
//@AuditLog(operation = "'删除用户:' + #id")
public Result delete(@PathVariable Long id) {
if (checkAdmin(id)) {
return Result.failed(ADMIN_CHANGE_MSG);
......@@ -230,6 +235,7 @@ public class SysUserController {
*/
@CacheEvict(value = "user", key = "#sysUser.username")
@PostMapping("/users/saveOrUpdate")
@AuditLog(operation = "'新增或更新用户:' + #sysUser.username")
public Result saveOrUpdate(@RequestBody SysUser sysUser) {
return appUserService.saveOrUpdateUser(sysUser);
}
......
......@@ -34,4 +34,7 @@ zlt:
- sys_role_user
- sys_role_menu
ignoreSqls:
- com.central.user.mapper.SysRoleMapper.findAll
\ No newline at end of file
- com.central.user.mapper.SysRoleMapper.findAll
#审计日志
# audit-log:
# enabled: true
\ No newline at end of file
......@@ -2,6 +2,8 @@ package com.central.user.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
......@@ -80,7 +82,36 @@ public class SysUserControllerTest {
@Transactional
public void whenDeleteSuccess() throws Exception {
mockMvc.perform(delete("/users/1")
.header("x-userid-header", 1)
.header("x-user-header", "admin")
.header("x-tenant-header", "webApp")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
}
@Test
@Transactional
public void whenSaveOrUpdateSuccess() throws Exception {
String content = "{\"id\":1, \"username\":\"admin\", \"roleId\":\"1,2,3\"}";
mockMvc.perform(post("/users/saveOrUpdate")
.header("x-userid-header", 1)
.header("x-user-header", "admin")
.header("x-tenant-header", "webApp")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(content))
.andExpect(status().isOk());
}
@Test
@Transactional
public void whenUpdateSuccess() throws Exception {
String content = "{\"id\":1, \"username\":\"admin\", \"roleId\":\"1,2,3\"}";
mockMvc.perform(put("/users")
.header("x-userid-header", 1)
.header("x-user-header", "admin")
.header("x-tenant-header", "webApp")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(content))
.andExpect(status().isOk());
}
}
......@@ -37,5 +37,20 @@
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
package com.central.log.annotation;
import java.lang.annotation.*;
/**
* @author zlt
* @date 2020/2/3
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuditLog {
/**
* 操作信息
*/
String operation();
}
package com.central.log.aspect;
import com.central.log.annotation.AuditLog;
import com.central.log.model.Audit;
import com.central.log.properties.AuditLogProperties;
import com.central.log.service.IAuditService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
* 审计日志切面
*
* @author zlt
* @date 2020/2/3
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@Slf4j
@Aspect
@ConditionalOnClass({HttpServletRequest.class, RequestContextHolder.class})
public class AuditLogAspect {
@Value("${spring.application.name}")
private String applicationName;
private AuditLogProperties auditLogProperties;
private IAuditService auditService;
public AuditLogAspect(AuditLogProperties auditLogProperties, IAuditService auditService) {
this.auditLogProperties = auditLogProperties;
this.auditService = auditService;
}
/**
* 用于SpEL表达式解析.
*/
private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
/**
* 用于获取方法参数定义名字.
*/
private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
@Before("@within(auditLog) || @annotation(auditLog)")
public void beforeMethod(JoinPoint joinPoint, AuditLog auditLog) {
//判断功能是否开启
if (auditLogProperties.getEnabled()) {
if (auditService == null) {
log.warn("AuditLogAspect - auditService is null");
return;
}
if (auditLog == null) {
// 获取类上的注解
auditLog = joinPoint.getTarget().getClass().getDeclaredAnnotation(AuditLog.class);
}
Audit audit = getAudit(auditLog, joinPoint);
auditService.save(audit);
}
}
/**
* 解析spEL表达式
*/
private String getValBySpEL(String spEL, MethodSignature methodSignature, Object[] args) {
//获取方法形参名数组
String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod());
if (paramNames != null && paramNames.length > 0) {
Expression expression = spelExpressionParser.parseExpression(spEL);
// spring的表达式上下文对象
EvaluationContext context = new StandardEvaluationContext();
// 给上下文赋值
for(int i = 0; i < args.length; i++) {
context.setVariable(paramNames[i], args[i]);
}
return expression.getValue(context).toString();
}
return null;
}
/**
* 构建审计对象
*/
private Audit getAudit(AuditLog auditLog, JoinPoint joinPoint) {
Audit audit = new Audit();
audit.setTimestamp(LocalDateTime.now());
audit.setApplicationName(applicationName);
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
audit.setClassName(methodSignature.getDeclaringTypeName());
audit.setMethodName(methodSignature.getName());
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String userId = request.getHeader("x-userid-header");
String userName = request.getHeader("x-user-header");
String clientId = request.getHeader("x-tenant-header");
audit.setUserId(userId);
audit.setUserName(userName);
audit.setClientId(clientId);
String operation = auditLog.operation();
if (operation.contains("#")) {
//获取方法参数值
Object[] args = joinPoint.getArgs();
operation = getValBySpEL(operation, methodSignature, args);
}
audit.setOperation(operation);
return audit;
}
}
package com.central.log.config;
import com.central.log.properties.AuditLogProperties;
import com.central.log.properties.TraceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
......@@ -9,7 +10,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
* @author zlt
* @date 2019/8/13
*/
@EnableConfigurationProperties(TraceProperties.class)
@EnableConfigurationProperties({TraceProperties.class, AuditLogProperties.class})
public class LogAutoConfigure {
}
package com.central.log.model;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
/**
* 审计日志
*
* @author zlt
* @date 2020/2/3
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
public class Audit {
/**
* 操作时间
*/
private LocalDateTime timestamp;
/**
* 应用名
*/
private String applicationName;
/**
* 类名
*/
private String className;
/**
* 方法名
*/
private String methodName;
/**
* 用户id
*/
private String userId;
/**
* 用户名
*/
private String userName;
/**
* 租户id
*/
private String clientId;
/**
* 操作信息
*/
private String operation;
}
package com.central.log.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
/**
* 审计日志配置
*
* @author zlt
* @date 2020/2/3
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
@ConfigurationProperties(prefix = "zlt.audit-log")
@RefreshScope
public class AuditLogProperties {
/**
* 是否开启审计日志
*/
private Boolean enabled = false;
/**
* 日志记录类型(logger/redis/db/es)
*/
private String logType;
}
package com.central.log.service;
import com.central.log.model.Audit;
/**
* 审计日志接口
*
* @author zlt
* @date 2020/2/3
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
public interface IAuditService {
void save(Audit audit);
}
package com.central.log.service.impl;
import com.central.log.model.Audit;
import com.central.log.service.IAuditService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import java.time.format.DateTimeFormatter;
/**
* 审计日志实现类-打印日志
*
* @author zlt
* @date 2020/2/3
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@Slf4j
@Service
@ConditionalOnProperty(name = "zlt.audit-log.log-type", havingValue = "logger", matchIfMissing = true)
public class LoggerAuditServiceImpl implements IAuditService {
private static final String MSG_PATTERN = "{}|{}|{}|{}|{}|{}|{}|{}";
/**
* 格式为:{时间}|{应用名}|{类名}|{方法名}|{用户id}|{用户名}|{租户id}|{操作信息}
* 例子:2020-02-04 09:13:34.650|user-center|com.central.user.controller.SysUserController|saveOrUpdate|1|admin|webApp|新增用户:admin
*/
@Override
public void save(Audit audit) {
log.debug(MSG_PATTERN
, audit.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
, audit.getApplicationName(), audit.getClassName(), audit.getMethodName()
, audit.getUserId(), audit.getUserName(), audit.getClientId()
, audit.getOperation());
}
}
......@@ -2,4 +2,5 @@ org.springframework.context.ApplicationContextInitializer=\
com.central.log.config.TtlMDCAdapterInitializer
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.central.log.config.LogAutoConfigure
com.central.log.config.LogAutoConfigure,\
com.central.log.aspect.AuditLogAspect
......@@ -4,6 +4,7 @@
<springProperty name="APP_NAME" scope="context" source="spring.application.name"/>
<springProperty name="LOG_FILE" scope="context" source="logging.file" defaultValue="../logs/application/${APP_NAME}"/>
<springProperty name="LOG_POINT_FILE" scope="context" source="logging.file" defaultValue="../logs/point"/>
<springProperty name="LOG_AUDIT_FILE" scope="context" source="logging.file" defaultValue="../logs/audit"/>
<springProperty name="LOG_MAXFILESIZE" scope="context" source="logback.filesize" defaultValue="50MB"/>
<springProperty name="LOG_FILEMAXDAY" scope="context" source="logback.filemaxday" defaultValue="7"/>
<springProperty name="ServerIP" scope="context" source="spring.cloud.client.ip-address" defaultValue="0.0.0.0"/>
......@@ -64,9 +65,23 @@
<maxFileSize>${LOG_MAXFILESIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
</appender>
<appender name="audit_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_AUDIT_FILE}/audit.log</file>
<encoder>
<pattern>%msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 基于时间的分包策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_AUDIT_FILE}/audit.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--保留时间,单位:天-->
<maxHistory>${LOG_FILEMAXDAY}</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${LOG_MAXFILESIZE}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>
<appender name="point_log_async" class="ch.qos.logback.classic.AsyncAppender">
......@@ -77,9 +92,16 @@
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="FileAppender"/>
</appender>
<appender name="audit_log_async" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="audit_log"/>
</appender>
<logger name="com.central.log.monitor" level="debug" addtivity="false">
<appender-ref ref="point_log_async" />
</logger>
<logger name="com.central.log.service.impl.LoggerAuditServiceImpl" level="debug" addtivity="false">
<appender-ref ref="audit_log_async" />
</logger>
<root level="INFO">
<appender-ref ref="StdoutAppender"/>
......
......@@ -128,15 +128,15 @@ INSERT INTO `sys_menu` VALUES (11, 12, '我的信息', '#!myInfo', 'system/myInf
INSERT INTO `sys_menu` VALUES (12, -1, '认证管理', 'javascript:;', '', NULL, 'layui-icon-set', 1, '2017-11-17 16:56:59', '2018-12-13 15:02:49', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (35, 12, '应用管理', '#!app', 'attestation/app.html', NULL, 'layui-icon-link', 5, '2017-11-17 16:56:59', '2019-01-14 15:35:15', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (37, -1, '系统管理', 'javascript:;', '', NULL, 'layui-icon-set', 2, '2018-08-25 10:41:58', '2019-01-23 14:01:58', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (62, 63, '应用监控', '#!admin', 'http://127.0.0.1:6500/#/wallboard', NULL, 'layui-icon-chart-screen', 3, '2019-01-08 15:32:19', '2019-01-17 20:22:44', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (62, 63, '应用监控', '#!admin', 'http://127.0.0.1:6500/#/wallboard', NULL, 'layui-icon-chart-screen', 4, '2019-01-08 15:32:19', '2019-01-17 20:22:44', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (63, -1, '系统监控', 'javascript:;', '', NULL, 'layui-icon-set', 2, '2019-01-10 18:35:05', '2019-01-10 18:35:05', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (64, 63, '系统日志', '#!sysLog', 'log/sysLog.html', NULL, 'layui-icon-file-b', 1, '2019-01-10 18:35:55', '2019-01-12 00:27:20', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (65, 37, '代码生成器', '#!generator', 'generator/list.html', NULL, 'layui-icon-template', 2, '2019-01-14 00:47:36', '2019-01-23 14:06:31', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (66, 63, '慢查询SQL', '#!slowQueryLog', 'log/slowQueryLog.html', NULL, 'layui-icon-snowflake', 2, '2019-01-16 12:00:27', '2019-01-16 15:32:31', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (67, -1, '任务管理', '#!job', 'http://127.0.0.1:8081/', NULL, 'layui-icon-date', 3, '2019-01-17 20:18:22', '2019-01-23 14:01:53', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (68, 63, '应用吞吐量监控', '#!sentinel', 'http://127.0.0.1:6999', NULL, 'layui-icon-chart', 4, '2019-01-22 16:31:55', '2019-01-22 16:34:03', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (68, 63, '应用吞吐量监控', '#!sentinel', 'http://127.0.0.1:6999', NULL, 'layui-icon-chart', 5, '2019-01-22 16:31:55', '2019-01-22 16:34:03', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (69, 37, '配置中心', '#!nacos', 'http://127.0.0.1:8848/nacos', NULL, 'layui-icon-tabs', 1, '2019-01-23 14:06:10', '2019-01-23 14:06:10', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (70, 63, 'APM监控', '#!apm', 'http://127.0.0.1:8080', null, 'layui-icon-engine', 5, '2019-02-27 10:31:55', '2019-02-27 10:31:55', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (70, 63, 'APM监控', '#!apm', 'http://127.0.0.1:8080', null, 'layui-icon-engine', 6, '2019-02-27 10:31:55', '2019-02-27 10:31:55', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (71, -1, '搜索管理', 'javascript:;', '', NULL, 'layui-icon-set', 3, '2018-08-25 10:41:58', '2019-01-23 15:07:07', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (72, 71, '索引管理', '#!index', 'search/index_manager.html', NULL, 'layui-icon-template', 1, '2019-01-10 18:35:55', '2019-01-12 00:27:20', 1, 0, 'webApp');
INSERT INTO `sys_menu` VALUES (73, 71, '用户搜索', '#!userSearch', 'search/user_search.html', NULL, 'layui-icon-user', 2, '2019-01-10 18:35:55', '2019-01-12 00:27:20', 1, 0, 'webApp');
......@@ -151,6 +151,7 @@ INSERT INTO `sys_menu` VALUES (81, -1, '商品管理', '#!product', '', NULL, NU
INSERT INTO `sys_menu` VALUES (82, -1, '支付管理', '#!pay', '', NULL, NULL, 3, '2019-08-06 20:02:12.604', '2019-08-06 20:02:12.604', 1, 0, 'zlt');
INSERT INTO `sys_menu` VALUES (83, -1, '交易管理', '#!trading', '', NULL, NULL, 4, '2019-08-06 20:02:12.604', '2019-08-06 20:02:12.604', 1, 0, 'zlt');
INSERT INTO `sys_menu` VALUES (84, -1, '系统管理', '#!system', '', NULL, NULL, 1, '2019-08-06 20:02:12.604', '2019-08-06 20:02:12.604', 1, 0, 'app');
INSERT INTO `sys_menu` VALUES (85, 63, '审计日志', '#!auditLog', 'log/auditLog.html', NULL, 'layui-icon-snowflake', 3, '2020-02-04 12:00:27', '2020-02-04 15:32:31', 1, 0, 'webApp');
-- ----------------------------
-- Table structure for sys_role_menu
......@@ -192,6 +193,7 @@ INSERT INTO `sys_role_menu` VALUES (1, 76);
INSERT INTO `sys_role_menu` VALUES (1, 77);
INSERT INTO `sys_role_menu` VALUES (1, 78);
INSERT INTO `sys_role_menu` VALUES (1, 79);
INSERT INTO `sys_role_menu` VALUES (1, 85);
INSERT INTO `sys_role_menu` VALUES (2, 2);
INSERT INTO `sys_role_menu` VALUES (2, 3);
INSERT INTO `sys_role_menu` VALUES (2, 4);
......
package com.central.log.controller;
import com.alibaba.fastjson.JSONObject;
import com.central.common.model.PageResult;
import com.central.search.client.service.IQueryService;
import com.central.search.model.SearchDto;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 审计日志
*
* @author zlt
* @date 2020/2/4
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@RestController
public class AuditLogController {
private final IQueryService queryService;
public AuditLogController(IQueryService queryService) {
this.queryService = queryService;
}
@ApiOperation(value = "审计日志全文搜索列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "分页起始位置", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "limit", value = "分页结束位置", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "queryStr", value = "搜索关键字", dataType = "String")
})
@GetMapping(value = "/auditLog")
public PageResult<JSONObject> getPage(SearchDto searchDto) {
searchDto.setIsHighlighter(true);
searchDto.setSortCol("timestamp");
return queryService.strQuery("audit-log-*", searchDto);
}
}
<div class="layui-card">
<div class="layui-card-header">
<h2 class="header-title">审计日志</h2>
<span class="layui-breadcrumb pull-right">
<a href="#!console">首页</a>
<a><cite>审计日志</cite></a>
</span>
</div>
<div class="layui-card-body">
<div class="layui-form toolbar">
搜索:
<select id="auditLog-search-key">
<option value="_all">全文搜索</option>
<option value="appName">应用名</option>
<option value="className">类名</option>
<option value="methodName">方法名</option>
<option value="userId">用户id</option>
<option value="userName">用户名</option>
<option value="clientId">租户id</option>
<option value="operation">操作信息</option>
</select>&emsp;
<input id="auditLog-search-value" class="layui-input search-input" style="width: 300px" type="text" placeholder="输入关键字"/>&emsp;
<button id="auditLog-btn-search" class="layui-btn icon-btn"><i class="layui-icon">&#xe615;</i>搜索</button>
</div>
<table class="layui-table" id="auditLog-table" lay-filter="auditLog-table"></table>
</div>
</div>
<script>
layui.use(['form', 'table', 'util', 'config', 'admin', 'upload'], function () {
let table = layui.table;
let config = layui.config;
let util = layui.util;
// 渲染表格
table.render({
elem: '#auditLog-table',
url: config.base_server + 'api-log/auditLog',
method: 'GET',
headers:{'Authorization': 'Bearer ' + config.getToken().access_token},
page: true,
cols: [[
{type: 'numbers'},
{
field: 'timestamp', width: 170, sort: true, templet: function (d) {
return util.toDateString(d.timestamp, 'yyyy-MM-dd HH:mm:ss');
}, title: '日志时间'
},
{field: 'userId', sort: true, title: '用户id', width: 80},
{field: 'userName', sort: true, title: '用户名', width: 100},
{field: 'clientId', sort: true, title: '租户id', width: 80},
{field: 'operation', sort: true, title: '操作信息', width: 350},
{field: 'appName', sort: true, title: '应用名', width: 120},
{field: 'className', sort: true, title: '类名', width: 250},
{field: 'methodName', sort: true, title: '方法名', width: 130}
]]
});
// 搜索按钮点击事件
$('#auditLog-btn-search').click(function () {
let key = $('#auditLog-search-key').val();
let value = $('#auditLog-search-value').val();
if (key != '_all' && value) {
value = key + ':' + value;
}
table.reload('auditLog-table', {where: {queryStr: value}});
});
});
</script>
\ No newline at end of file
......@@ -34,7 +34,7 @@
// 渲染表格
table.render({
elem: '#sysLog-table',
url: config.base_server + 'api-log/sysLog?data',
url: config.base_server + 'api-log/sysLog',
method: 'GET',
headers:{'Authorization': 'Bearer ' + config.getToken().access_token},
page: true,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册