完善新操作日志的页面修改
This commit is contained in:
parent
2fccaa2b9a
commit
1768d27e11
2
pom.xml
2
pom.xml
@ -22,7 +22,7 @@
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.boot.version>2.4.1</spring.boot.version>
|
||||
<spring.boot.version>2.4.2</spring.boot.version>
|
||||
|
||||
<!-- <ruoyi.version>3.3.0</ruoyi.version>-->
|
||||
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
|
||||
|
@ -23,28 +23,12 @@ import com.ruoyi.system.service.ISysOperLogService;
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/monitor/operlog")
|
||||
|
||||
public class SysOperlogController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ISysOperLogService operLogService;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(SysOperLog operLog) {
|
||||
startPage();
|
||||
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
|
||||
@PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
|
||||
@GetMapping("/export")
|
||||
public AjaxResult export(SysOperLog operLog) {
|
||||
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
|
||||
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
|
||||
return util.exportExcel(list, "操作日志");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
|
||||
<description>
|
||||
common通用工具
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- yml解析器 -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器等 -->
|
||||
<dependency>
|
||||
<groupId>eu.bitwalker</groupId>
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -1,41 +0,0 @@
|
||||
package com.ruoyi.common.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;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.enums.OperatorType;
|
||||
|
||||
/**
|
||||
* 自定义操作日志记录注解
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@Target({ ElementType.PARAMETER, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Log
|
||||
{
|
||||
/**
|
||||
* 模块
|
||||
*/
|
||||
public String title() default "";
|
||||
|
||||
/**
|
||||
* 功能
|
||||
*/
|
||||
public BusinessType businessType() default BusinessType.OTHER;
|
||||
|
||||
/**
|
||||
* 操作人类别
|
||||
*/
|
||||
public OperatorType operatorType() default OperatorType.MANAGE;
|
||||
|
||||
/**
|
||||
* 是否保存请求的参数
|
||||
*/
|
||||
public boolean isSaveRequestData() default true;
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
package com.ruoyi.framework.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.enums.BusinessStatus;
|
||||
import com.ruoyi.common.enums.HttpMethod;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.ip.IpUtils;
|
||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.system.domain.SysOperLog;
|
||||
|
||||
/**
|
||||
* 操作日志记录处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class LogAspect {
|
||||
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
|
||||
|
||||
// 配置织入点
|
||||
@Pointcut("@annotation(com.ruoyi.common.annotation.Log)")
|
||||
public void logPointCut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理完请求后执行
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
*/
|
||||
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
|
||||
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
|
||||
handleLog(joinPoint, null, jsonResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截异常操作
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @param e 异常
|
||||
*/
|
||||
@AfterThrowing(value = "logPointCut()", throwing = "e")
|
||||
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
|
||||
handleLog(joinPoint, e, null);
|
||||
}
|
||||
|
||||
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
|
||||
try {
|
||||
// 获得注解
|
||||
Log controllerLog = getAnnotationLog(joinPoint);
|
||||
if (controllerLog == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前的用户
|
||||
LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
|
||||
|
||||
// *========数据库日志=========*//
|
||||
SysOperLog operLog = new SysOperLog();
|
||||
operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
|
||||
// 请求的地址
|
||||
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
|
||||
operLog.setOperIp(ip);
|
||||
// 返回参数
|
||||
operLog.setJsonResult(JSON.toJSONString(jsonResult));
|
||||
|
||||
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
|
||||
if (loginUser != null) {
|
||||
operLog.setOperName(loginUser.getUsername());
|
||||
}
|
||||
|
||||
if (e != null) {
|
||||
operLog.setStatus(BusinessStatus.FAIL.ordinal());
|
||||
operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
|
||||
}
|
||||
// 设置方法名称
|
||||
String className = joinPoint.getTarget().getClass().getName();
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
operLog.setMethod(className + "." + methodName + "()");
|
||||
// 设置请求方式
|
||||
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
|
||||
// 处理设置注解上的参数
|
||||
getControllerMethodDescription(joinPoint, controllerLog, operLog);
|
||||
// 保存数据库
|
||||
AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
|
||||
} catch (Exception exp) {
|
||||
// 记录本地异常日志
|
||||
log.error("==前置通知异常==");
|
||||
log.error("异常信息:{}", exp.getMessage());
|
||||
exp.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数拼装
|
||||
*/
|
||||
private String argsArrayToString(Object[] paramsArray) {
|
||||
String params = "";
|
||||
if (paramsArray != null && paramsArray.length > 0) {
|
||||
for (int i = 0; i < paramsArray.length; i++) {
|
||||
if (!isFilterObject(paramsArray[i])) {
|
||||
Object jsonObj = JSON.toJSON(paramsArray[i]);
|
||||
params += jsonObj.toString() + " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
return params.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要过滤的对象。
|
||||
*
|
||||
* @param o 对象信息。
|
||||
* @return 如果是需要过滤的对象,则返回true;否则返回false。
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean isFilterObject(final Object o) {
|
||||
Class<?> clazz = o.getClass();
|
||||
if (clazz.isArray()) {
|
||||
return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
|
||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||
Collection collection = (Collection) o;
|
||||
for (Iterator iter = collection.iterator(); iter.hasNext(); ) {
|
||||
return iter.next() instanceof MultipartFile;
|
||||
}
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
Map map = (Map) o;
|
||||
for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
return entry.getValue() instanceof MultipartFile;
|
||||
}
|
||||
}
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
/**
|
||||
* 程序注解配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
// 指定要扫描的Mapper类的包的路径
|
||||
@MapperScan("com.ruoyi.**.mapper")
|
||||
public class ApplicationConfig {
|
||||
/**
|
||||
* 时区配置
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
|
||||
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询操作日志列表
|
||||
export function list(query) {
|
||||
return request({
|
||||
url: '/monitor/operlog/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 删除操作日志
|
||||
export function delOperlog(operId) {
|
||||
return request({
|
||||
url: '/monitor/operlog/' + operId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 清空操作日志
|
||||
export function cleanOperlog() {
|
||||
return request({
|
||||
url: '/monitor/operlog/clean',
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 导出操作日志
|
||||
export function exportOperlog(query) {
|
||||
return request({
|
||||
url: '/monitor/operlog/export',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
19
ruoyi-ui/src/api/system/operatelog.js
Normal file
19
ruoyi-ui/src/api/system/operatelog.js
Normal file
@ -0,0 +1,19 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询操作日志列表
|
||||
export function listOperateLog(query) {
|
||||
return request({
|
||||
url: '/system/operate-log/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 导出操作日志
|
||||
export function exportOperateLog(query) {
|
||||
return request({
|
||||
url: '/system/operate-log/export',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
@ -23,6 +23,7 @@ import RightToolbar from "@/components/RightToolbar"
|
||||
// 代码高亮插件
|
||||
import hljs from 'highlight.js'
|
||||
import 'highlight.js/styles/github-gist.css'
|
||||
import {DICT_TYPE, getDictDataLabel, getDictDatas} from "@/utils/dict";
|
||||
|
||||
// 全局方法挂载
|
||||
Vue.prototype.getDicts = getDicts
|
||||
@ -32,6 +33,9 @@ Vue.prototype.resetForm = resetForm
|
||||
Vue.prototype.addDateRange = addDateRange
|
||||
Vue.prototype.selectDictLabel = selectDictLabel
|
||||
Vue.prototype.selectDictLabels = selectDictLabels
|
||||
Vue.prototype.getDictDatas = getDictDatas
|
||||
Vue.prototype.getDictDataLabel = getDictDataLabel
|
||||
Vue.prototype.DICT_TYPE = DICT_TYPE
|
||||
Vue.prototype.download = download
|
||||
Vue.prototype.downloadExcel = downloadExcel
|
||||
Vue.prototype.handleTree = handleTree
|
||||
|
@ -12,6 +12,7 @@ export const DICT_TYPE = {
|
||||
SYS_DATA_SCOPE: 'sys_data_scope',
|
||||
SYS_USER_SEX: 'sys_user_sex',
|
||||
SYS_NOTICE_TYPE: 'sys_notice_type',
|
||||
SYS_OPERATE_TYPE: 'sys_operate_type'
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,318 +1,275 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="系统模块" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入系统模块"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人员" prop="operName">
|
||||
<el-input
|
||||
v-model="queryParams.operName"
|
||||
placeholder="请输入操作人员"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="businessType">
|
||||
<el-select
|
||||
v-model="queryParams.businessType"
|
||||
placeholder="操作类型"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in typeOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="操作状态"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in statusOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
@click="handleClean"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['system:config:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="日志编号" align="center" prop="operId" />
|
||||
<el-table-column label="系统模块" align="center" prop="title" />
|
||||
<el-table-column label="操作类型" align="center" prop="businessType" :formatter="typeFormat" />
|
||||
<el-table-column label="请求方式" align="center" prop="requestMethod" />
|
||||
<el-table-column label="操作人员" align="center" prop="operName" />
|
||||
<el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作地点" align="center" prop="operLocation" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作状态" align="center" prop="status" :formatter="statusFormat" />
|
||||
<el-table-column label="操作日期" align="center" prop="operTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.operTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row,scope.index)"
|
||||
v-hasPermi="['monitor:operlog:query']"
|
||||
>详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 操作日志详细 -->
|
||||
<el-dialog title="操作日志详细" :visible.sync="open" width="700px" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="100px" size="mini">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
|
||||
<el-form-item
|
||||
label="登录信息:"
|
||||
>{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
|
||||
<el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="操作方法:">{{ form.method }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作状态:">
|
||||
<div v-if="form.status === 0">正常</div>
|
||||
<div v-else-if="form.status === 1">失败</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { list, delOperlog, cleanOperlog, exportOperlog } from "@/api/monitor/operlog";
|
||||
|
||||
export default {
|
||||
name: "Operlog",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 类型数据字典
|
||||
typeOptions: [],
|
||||
// 类型数据字典
|
||||
statusOptions: [],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
title: undefined,
|
||||
operName: undefined,
|
||||
businessType: undefined,
|
||||
status: undefined
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDicts("sys_oper_type").then(response => {
|
||||
this.typeOptions = response.data;
|
||||
});
|
||||
this.getDicts("sys_common_status").then(response => {
|
||||
this.statusOptions = response.data;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/** 查询登录日志 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
list(this.addDateRange(this.queryParams, this.dateRange)).then( response => {
|
||||
this.list = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
// 操作日志状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status);
|
||||
},
|
||||
// 操作日志类型字典翻译
|
||||
typeFormat(row, column) {
|
||||
return this.selectDictLabel(this.typeOptions, row.businessType);
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.operId)
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 详细按钮操作 */
|
||||
handleView(row) {
|
||||
this.open = true;
|
||||
this.form = row;
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const operIds = row.operId || this.ids;
|
||||
this.$confirm('是否确认删除日志编号为"' + operIds + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return delOperlog(operIds);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
/** 清空按钮操作 */
|
||||
handleClean() {
|
||||
this.$confirm('是否确认清空所有操作日志数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return cleanOperlog();
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("清空成功");
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$confirm('是否确认导出所有操作日志数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportOperlog(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="系统模块" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入系统模块"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人员" prop="operName">
|
||||
<el-input
|
||||
v-model="queryParams.operName"
|
||||
placeholder="请输入操作人员"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
placeholder="操作类型"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in this.getDictDatas(DICT_TYPE.SYS_OPERATE_TYPE)"
|
||||
:key="parseInt(dict.value)"
|
||||
:label="dict.label"
|
||||
:value="parseInt(dict.value)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.success"
|
||||
placeholder="操作状态"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
:key="true"
|
||||
label="成功"
|
||||
:value="true"
|
||||
/>
|
||||
<el-option
|
||||
:key="false"
|
||||
label="失败"
|
||||
:value="false"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
size="small"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['system:config:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="日志编号" align="center" prop="id" />
|
||||
<el-table-column label="操作模块" align="center" prop="module" />
|
||||
<el-table-column label="操作名" align="center" prop="name" width="180" />
|
||||
<el-table-column label="操作类型" align="center" prop="type">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getDictDataLabel(DICT_TYPE.SYS_OPERATE_TYPE, scope.row.type) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作人" align="center" prop="userNickname" />
|
||||
<el-table-column label="操作结果" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.resultCode === 0 ? '成功' : '失败' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作日期" align="center" prop="startTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.startTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="执行时长" align="center" prop="startTime">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.duration }} ms</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row,scope.index)"
|
||||
v-hasPermi="['system:operate-log:query']"
|
||||
>详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 操作日志详细 -->
|
||||
<el-dialog title="操作日志详细" :visible.sync="open" width="700px" append-to-body>
|
||||
<el-form ref="form" :model="form" label-width="100px" size="mini">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
|
||||
<el-form-item
|
||||
label="登录信息:"
|
||||
>{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
|
||||
<el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="操作方法:">{{ form.method }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作状态:">
|
||||
<div v-if="form.status === 0">正常</div>
|
||||
<div v-else-if="form.status === 1">失败</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOperateLog, exportOperateLog } from "@/api/system/operatelog";
|
||||
|
||||
export default {
|
||||
name: "Operlog",
|
||||
data() {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 表格数据
|
||||
list: [],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 类型数据字典
|
||||
typeOptions: [],
|
||||
// 类型数据字典
|
||||
statusOptions: [],
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
title: undefined,
|
||||
operName: undefined,
|
||||
businessType: undefined,
|
||||
status: undefined
|
||||
},
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询登录日志 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listOperateLog(this.addDateRange(this.queryParams, [
|
||||
this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
|
||||
this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
|
||||
])).then( response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
},
|
||||
// 操作日志状态字典翻译
|
||||
statusFormat(row, column) {
|
||||
return this.selectDictLabel(this.statusOptions, row.status);
|
||||
},
|
||||
// 操作日志类型字典翻译
|
||||
typeFormat(row, column) {
|
||||
return this.selectDictLabel(this.typeOptions, row.businessType);
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRange = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 详细按钮操作 */
|
||||
handleView(row) {
|
||||
this.open = true;
|
||||
this.form = row;
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams;
|
||||
this.$confirm('是否确认导出所有操作日志数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return exportOperateLog(queryParams);
|
||||
}).then(response => {
|
||||
this.download(response.msg);
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
29
sql/ruoyi-vue-pro-data.sql
Normal file
29
sql/ruoyi-vue-pro-data.sql
Normal file
@ -0,0 +1,29 @@
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (1, 1, '男', '1', 'sys_user_sex', 0, '性别男', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 05:48:53', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (2, 2, '女', '2', 'sys_user_sex', 0, '性别女', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 05:48:55', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (8, 1, '正常', '0', 'sys_job_status', 0, '正常状态', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (9, 2, '暂停', '1', 'sys_job_status', 0, '停用状态', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', 0, '默认分组', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', 0, '系统分组', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (12, 1, '是', 'Y', 'sys_yes_no', 0, '系统默认是', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (13, 2, '否', 'N', 'sys_yes_no', 0, '系统默认否', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (14, 1, '通知', '1', 'sys_notice_type', 0, '通知', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (15, 2, '公告', '2', 'sys_notice_type', 0, '公告', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 00:02:28', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (16, 0, '其它', '0', 'sys_operate_type', 0, '其它操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:12', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (17, 1, '查询', '1', 'sys_operate_type', 0, '查询操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:10', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (18, 2, '新增', '2', 'sys_operate_type', 0, '新增操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:17', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (19, 3, '修改', '3', 'sys_operate_type', 0, '修改操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:20', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (20, 4, '删除', '4', 'sys_operate_type', 0, '删除操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:51:24', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (22, 5, '导出', '5', 'sys_operate_type', 0, '导出操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:49:20', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (23, 6, '导入', '6', 'sys_operate_type', 0, '导入操作', 'admin', '2021-01-05 17:03:48', '', '2021-01-16 13:49:24', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (27, 1, '开启', '0', 'sys_common_status', 0, '开启状态', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 02:57:12', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (28, 2, '关闭', '1', 'sys_common_status', 0, '关闭状态', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 05:48:32', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (29, 1, '目录', '1', 'sys_menu_type', 0, '目录', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:33:30', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (30, 2, '菜单', '2', 'sys_menu_type', 0, '菜单', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:33:35', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (31, 3, '按钮', '3', 'sys_menu_type', 0, '按钮', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:33:38', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (32, 1, '内置', '1', 'sys_role_type', 0, '内置角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:34:22', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (33, 2, '自定义', '2', 'sys_role_type', 0, '自定义角色', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 13:34:26', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (34, 1, '全部数据权限', '1', 'sys_data_scope', 0, '全部数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:02', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (35, 2, '指定部门数据权限', '2', 'sys_data_scope', 0, '指定部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:20', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (36, 3, '本部门数据权限', '3', 'sys_data_scope', 0, '本部门数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:29', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (37, 4, '本部门及以下数据权限', '4', 'sys_data_scope', 0, '本部门及以下数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:32', b'0');
|
||||
INSERT INTO `ruoyi-vue-pro`.`sys_dict_data`(`id`, `sort`, `label`, `value`, `dict_type`, `status`, `remark`, `create_by`, `create_time`, `update_by`, `update_time`, `deleted`) VALUES (38, 5, '仅本人数据权限', '5', 'sys_data_scope', 0, '仅本人数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:38', b'0');
|
@ -31,4 +31,8 @@ public final class PageResult<T> implements Serializable {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public static <T> PageResult<T> empty() {
|
||||
return new PageResult<>(0L);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(proxyTargetClass = true)
|
||||
@EnableAsync
|
||||
public class AsyncConfiguration {
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.dashboard.framework.logger.operatelog.core.annotations;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.enums.logger.SysOperateLogTypeEnum;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
@ -32,7 +32,7 @@ public @interface OperateLog {
|
||||
*
|
||||
* 实际并不是数组,因为枚举不能设置 null 作为默认值
|
||||
*/
|
||||
SysOperateLogTypeEnum[] type() default {};
|
||||
OperateLogTypeEnum[] type() default {};
|
||||
|
||||
// ========== 开关字段 ==========
|
||||
|
||||
|
@ -6,11 +6,11 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService;
|
||||
import cn.iocoder.dashboard.framework.security.core.util.SecurityUtils;
|
||||
import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.logger.SysOperateLogTypeEnum;
|
||||
import cn.iocoder.dashboard.util.servlet.ServletUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Maps;
|
||||
@ -180,7 +180,7 @@ public class OperateLogAspect {
|
||||
}
|
||||
if (operateLogVO.getType() == null) {
|
||||
RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint));
|
||||
SysOperateLogTypeEnum operateLogType = convertOperateLogType(requestMethod);
|
||||
OperateLogTypeEnum operateLogType = convertOperateLogType(requestMethod);
|
||||
operateLogVO.setType(operateLogType != null ? operateLogType.getType() : null);
|
||||
}
|
||||
// content 和 exts 属性
|
||||
@ -275,21 +275,21 @@ public class OperateLogAspect {
|
||||
return requestMethods[0];
|
||||
}
|
||||
|
||||
private static SysOperateLogTypeEnum convertOperateLogType(RequestMethod requestMethod) {
|
||||
private static OperateLogTypeEnum convertOperateLogType(RequestMethod requestMethod) {
|
||||
if (requestMethod == null) {
|
||||
return null;
|
||||
}
|
||||
switch (requestMethod) {
|
||||
case GET:
|
||||
return SysOperateLogTypeEnum.GET;
|
||||
return OperateLogTypeEnum.GET;
|
||||
case POST:
|
||||
return SysOperateLogTypeEnum.CREATE;
|
||||
return OperateLogTypeEnum.CREATE;
|
||||
case PUT:
|
||||
return SysOperateLogTypeEnum.UPDATE;
|
||||
return OperateLogTypeEnum.UPDATE;
|
||||
case DELETE:
|
||||
return SysOperateLogTypeEnum.DELETE;
|
||||
return OperateLogTypeEnum.DELETE;
|
||||
default:
|
||||
return SysOperateLogTypeEnum.OTHER;
|
||||
return OperateLogTypeEnum.OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.dashboard.modules.system.enums.logger;
|
||||
package cn.iocoder.dashboard.framework.logger.operatelog.core.enums;
|
||||
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -11,7 +11,7 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SysOperateLogTypeEnum {
|
||||
public enum OperateLogTypeEnum {
|
||||
|
||||
/**
|
||||
* 查询
|
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.dashboard.framework.mybatis.core.mapper;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageParam;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
|
||||
*/
|
||||
public interface BaseMapperX<T> extends BaseMapper<T> {
|
||||
|
||||
default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
|
||||
// MyBatis Plus 查询
|
||||
IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
|
||||
selectPage(mpPage, queryWrapper);
|
||||
// 转换返回
|
||||
return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
|
||||
}
|
||||
|
||||
}
|
@ -54,7 +54,6 @@ public class SysAuthController {
|
||||
|
||||
@ApiOperation("获取登陆用户的权限信息")
|
||||
@GetMapping("/get-permission-info")
|
||||
@OperateLog
|
||||
public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
|
||||
// 获得用户信息
|
||||
SysUserDO user = userService.getUser(getLoginUserId());
|
||||
|
@ -1,2 +1,2 @@
|
||||
### 请求 /captcha/get-image 接口 => 成功
|
||||
GET {{baseUrl}}/captcha/get-image
|
||||
GET {{baseUrl}}/system/captcha/get-image
|
||||
|
@ -23,7 +23,7 @@ public class SysCaptchaController {
|
||||
|
||||
@ApiOperation("生成图片验证码")
|
||||
@GetMapping("/get-image")
|
||||
private CommonResult<SysCaptchaImageRespVO> getCaptchaImage() {
|
||||
public CommonResult<SysCaptchaImageRespVO> getCaptchaImage() {
|
||||
return success(captchaService.getCaptchaImage());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
### 请求 /system/operate-log/demo 接口 => 成功
|
||||
GET {{baseUrl}}/system/operate-log/demo
|
||||
Authorization: Bearer {{token}}
|
@ -0,0 +1,86 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.logger;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.util.OperateLogUtils;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
|
||||
import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService;
|
||||
import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
|
||||
import cn.iocoder.dashboard.util.collection.CollectionUtils;
|
||||
import cn.iocoder.dashboard.util.collection.MapUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "操作日志 API")
|
||||
@RestController
|
||||
@RequestMapping("/system/operate-log")
|
||||
public class SysOperateLogController {
|
||||
|
||||
@Resource
|
||||
private SysOperateLogService operateLogService;
|
||||
|
||||
@Resource
|
||||
private SysUserService userService;
|
||||
|
||||
@ApiOperation("示例")
|
||||
@OperateLog(type = OperateLogTypeEnum.OTHER)
|
||||
@GetMapping("/demo")
|
||||
public CommonResult<Boolean> demo() {
|
||||
// 这里可以调用业务逻辑
|
||||
|
||||
// 补全操作日志的明细
|
||||
OperateLogUtils.setContent("将编号 1 的数据,xxx 字段修改成了 yyyy");
|
||||
OperateLogUtils.addExt("orderId", 1);
|
||||
|
||||
// 响应
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ApiOperation("查看操作日志分页列表")
|
||||
@GetMapping("/page")
|
||||
// @PreAuthorize("@ss.hasPermi('system:operate-log:query')")
|
||||
public CommonResult<PageResult<SysOperateLogRespVO>> pageOperateLog(@Validated SysOperateLogPageReqVO reqVO) {
|
||||
PageResult<SysOperateLogDO> pageResult = operateLogService.pageOperateLog(reqVO);
|
||||
|
||||
// 获得拼接需要的数据
|
||||
Collection<Long> userIds = CollectionUtils.convertList(pageResult.getList(), SysOperateLogDO::getUserId);
|
||||
Map<Long, SysUserDO> userMap = userService.getUserMap(userIds);
|
||||
// 拼接数据
|
||||
List<SysOperateLogRespVO> list = new ArrayList<>(pageResult.getList().size());
|
||||
pageResult.getList().forEach(operateLog -> {
|
||||
SysOperateLogRespVO respVO = SysOperateLogConvert.INSTANCE.convert(operateLog);
|
||||
list.add(respVO);
|
||||
// 拼接用户信息
|
||||
MapUtils.findAndThen(userMap, operateLog.getUserId(), user -> respVO.setUserNickname(user.getNickname()));
|
||||
});
|
||||
return success(new PageResult<>(list, pageResult.getTotal()));
|
||||
}
|
||||
|
||||
// @Log(title = "操作日志", businessType = BusinessType.EXPORT)
|
||||
// @PreAuthorize("@ss.hasPermi('system:operate-log:export')")
|
||||
// @GetMapping("/export")
|
||||
// public AjaxResult export(SysOperLog operLog) {
|
||||
// List<SysOperLog> list = operLogService.selectOperLogList(operLog);
|
||||
// ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
|
||||
// return util.exportExcel(list, "操作日志");
|
||||
// }
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.logger;
|
@ -6,6 +6,7 @@ import lombok.Data;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 操作日志 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
@ -30,10 +31,16 @@ public class SysOperateLogBaseVO {
|
||||
@NotEmpty(message = "操作名")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "操作分类", required = true, example = "操作分类", notes = "参见 SysOperateLogTypeEnum 枚举类")
|
||||
@ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类")
|
||||
@NotNull(message = "操作分类不能为空")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}")
|
||||
private Map<String, Object> exts;
|
||||
|
||||
@ApiModelProperty(value = "请求方法名", required = true, example = "GET")
|
||||
@NotEmpty(message = "请求方法名不能为空")
|
||||
private String requestMethod;
|
||||
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.logger.vo;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("操作日志分页列表 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysOperateLogPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "操作模块", example = "订单", notes = "模拟匹配")
|
||||
private String module;
|
||||
|
||||
@ApiModelProperty(value = "用户昵称", example = "芋道", notes = "模拟匹配")
|
||||
private String userNickname;
|
||||
|
||||
@ApiModelProperty(value = "操作分类", example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "操作状态", example = "true")
|
||||
private Boolean success;
|
||||
|
||||
@ApiModelProperty(value = "开始时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date beginTime;
|
||||
|
||||
@ApiModelProperty(value = "结束时间", example = "2020-10-24")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private Date endTime;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.logger.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@ApiModel("操作日志 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class SysOperateLogRespVO extends SysOperateLogBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "日志编号", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
|
||||
private String userNickname;
|
||||
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.dashboard.modules.system.convert.logger;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogRespVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@ -12,4 +14,8 @@ public interface SysOperateLogConvert {
|
||||
|
||||
SysOperateLogDO convert(SysOperateLogCreateReqVO bean);
|
||||
|
||||
PageResult<SysOperateLogRespVO> convertPage(PageResult<SysOperateLogDO> page);
|
||||
|
||||
SysOperateLogRespVO convert(SysOperateLogDO bean);
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,30 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Mapper
|
||||
public interface SysOperateLogMapper extends BaseMapper<SysOperateLogDO> {
|
||||
public interface SysOperateLogMapper extends BaseMapperX<SysOperateLogDO> {
|
||||
|
||||
default PageResult<SysOperateLogDO> selectPage(SysOperateLogPageReqVO reqVO, Collection<Long> userIds) {
|
||||
QueryWrapperX<SysOperateLogDO> query = new QueryWrapperX<SysOperateLogDO>()
|
||||
.likeIfPresent("module", reqVO.getModule())
|
||||
.inIfPresent("user_id", userIds)
|
||||
.eqIfPresent("operate_type", reqVO.getType())
|
||||
.betweenIfPresent("start_time", reqVO.getBeginTime(), reqVO.getEndTime());
|
||||
if (Boolean.TRUE.equals(reqVO.getSuccess())) {
|
||||
query.eq("result_code", GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||
} else if (Boolean.FALSE.equals(reqVO.getSuccess())) {
|
||||
query.gt("result_code", GlobalErrorCodeConstants.SUCCESS.getCode());
|
||||
}
|
||||
return selectPage(reqVO, query);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,5 +45,9 @@ public interface SysUserMapper extends BaseMapper<SysUserDO> {
|
||||
.inIfPresent("dept_id", deptIds));
|
||||
}
|
||||
|
||||
default List<SysUserDO> selectListByNickname(String nickname) {
|
||||
return selectList(new QueryWrapperX<SysUserDO>().like("nickname", nickname));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.logger.SysOperateLogTypeEnum;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@ -62,22 +62,18 @@ public class SysOperateLogDO extends BaseDO {
|
||||
/**
|
||||
* 操作分类
|
||||
*
|
||||
* 枚举 {@link SysOperateLogTypeEnum}
|
||||
* 枚举 {@link OperateLogTypeEnum}
|
||||
*/
|
||||
@TableField("operate_type")
|
||||
private Integer type;
|
||||
/**
|
||||
* 操作内容,记录整个操作的明细
|
||||
* 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
|
||||
*
|
||||
* TODO 预留字段
|
||||
*/
|
||||
private String content;
|
||||
/**
|
||||
* 拓展字段,有些复杂的业务,需要记录一些字段
|
||||
* 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号
|
||||
*
|
||||
* TODO 预留字段
|
||||
*/
|
||||
@TableField(typeHandler = FastjsonTypeHandler.class)
|
||||
private Map<String, Object> exts;
|
||||
|
@ -1,9 +1,21 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.logger;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
|
||||
|
||||
/**
|
||||
* 操作日志 Service 接口
|
||||
*/
|
||||
public interface SysOperateLogService extends OperateLogFrameworkService {
|
||||
|
||||
/**
|
||||
* 获得操作日志分页列表
|
||||
*
|
||||
* @param reqVO 分页条件
|
||||
* @return 操作日志分页列表
|
||||
*/
|
||||
PageResult<SysOperateLogDO> pageOperateLog(SysOperateLogPageReqVO reqVO);
|
||||
|
||||
}
|
||||
|
@ -1,18 +1,27 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.logger.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
|
||||
import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysOperateLogMapper;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
|
||||
import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService;
|
||||
import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
|
||||
import cn.iocoder.dashboard.util.string.StrUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
|
||||
import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.*;
|
||||
import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH;
|
||||
import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.RESULT_MAX_LENGTH;
|
||||
import static cn.iocoder.dashboard.util.collection.CollectionUtils.convertSet;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@ -21,6 +30,9 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
|
||||
@Resource
|
||||
private SysOperateLogMapper operateLogMapper;
|
||||
|
||||
@Resource
|
||||
private SysUserService userService;
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createOperateLogAsync(SysOperateLogCreateReqVO reqVO) {
|
||||
@ -35,4 +47,18 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SysOperateLogDO> pageOperateLog(SysOperateLogPageReqVO reqVO) {
|
||||
// 处理基于用户昵称的查询
|
||||
Collection<Long> userIds = null;
|
||||
if (StrUtil.isNotEmpty(reqVO.getUserNickname())) {
|
||||
userIds = convertSet(userService.listUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId);
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
}
|
||||
// 查询分页
|
||||
return operateLogMapper.selectPage(reqVO, userIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,15 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.user;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
|
||||
import cn.iocoder.dashboard.util.collection.CollectionUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用户 Service 接口
|
||||
@ -45,6 +50,35 @@ public interface SysUserService {
|
||||
*/
|
||||
List<SysUserDO> listUsers(SysUserExportReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 获得用户列表
|
||||
*
|
||||
* @param ids 用户编号数组
|
||||
* @return 用户列表
|
||||
*/
|
||||
List<SysUserDO> listUsers(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得用户 Map
|
||||
*
|
||||
* @param ids 用户编号数组
|
||||
* @return 用户 Map
|
||||
*/
|
||||
default Map<Long, SysUserDO> getUserMap(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
return CollectionUtils.convertMap(listUsers(ids), SysUserDO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得用户列表,基于昵称模糊匹配
|
||||
*
|
||||
* @param nickname 昵称
|
||||
* @return 用户列表
|
||||
*/
|
||||
List<SysUserDO> listUsersByNickname(String nickname);
|
||||
|
||||
/**
|
||||
* 创建用户
|
||||
*
|
||||
|
@ -83,6 +83,16 @@ public class SysUserServiceImpl implements SysUserService {
|
||||
return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysUserDO> listUsers(Collection<Long> ids) {
|
||||
return userMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysUserDO> listUsersByNickname(String nickname) {
|
||||
return userMapper.selectListByNickname(nickname);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得部门条件:查询指定部门的子部门编号们,包括自身
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user