Commit 1768d27e1154c1d5486f0c6e4cd3107ddbeda4ac

Authored by YunaiV
1 parent 2fccaa2b

完善新操作日志的页面修改

Showing 34 changed files with 649 additions and 664 deletions
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 <maven.compiler.target>${java.version}</maven.compiler.target> 22 <maven.compiler.target>${java.version}</maven.compiler.target>
23 <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> 23 <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
24 <!-- 统一依赖管理 --> 24 <!-- 统一依赖管理 -->
25 - <spring.boot.version>2.4.1</spring.boot.version> 25 + <spring.boot.version>2.4.2</spring.boot.version>
26 26
27 <!-- <ruoyi.version>3.3.0</ruoyi.version>--> 27 <!-- <ruoyi.version>3.3.0</ruoyi.version>-->
28 <!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>--> 28 <!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
@@ -23,28 +23,12 @@ import com.ruoyi.system.service.ISysOperLogService; @@ -23,28 +23,12 @@ import com.ruoyi.system.service.ISysOperLogService;
23 * 23 *
24 * @author ruoyi 24 * @author ruoyi
25 */ 25 */
26 -@RestController  
27 -@RequestMapping("/monitor/operlog") 26 +
28 public class SysOperlogController extends BaseController { 27 public class SysOperlogController extends BaseController {
29 28
30 @Autowired 29 @Autowired
31 private ISysOperLogService operLogService; 30 private ISysOperLogService operLogService;
32 31
33 - @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")  
34 - @GetMapping("/list")  
35 - public TableDataInfo list(SysOperLog operLog) {  
36 - startPage();  
37 - List<SysOperLog> list = operLogService.selectOperLogList(operLog);  
38 - return getDataTable(list);  
39 - }  
40 -  
41 - @Log(title = "操作日志", businessType = BusinessType.EXPORT)  
42 - @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")  
43 - @GetMapping("/export")  
44 - public AjaxResult export(SysOperLog operLog) {  
45 - List<SysOperLog> list = operLogService.selectOperLogList(operLog);  
46 - ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);  
47 - return util.exportExcel(list, "操作日志");  
48 - } 32 +
49 33
50 } 34 }
ruoyi-common/pom.xml deleted
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<project xmlns="http://maven.apache.org/POM/4.0.0"  
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
5 - <parent>  
6 - <artifactId>ruoyi</artifactId>  
7 - <groupId>com.ruoyi</groupId>  
8 - <version>3.3.0</version>  
9 - </parent>  
10 - <modelVersion>4.0.0</modelVersion>  
11 -  
12 - <artifactId>ruoyi-common</artifactId>  
13 -  
14 - <description>  
15 - common通用工具  
16 - </description>  
17 -  
18 - <dependencies>  
19 -  
20 - <!-- yml解析器 -->  
21 - <dependency>  
22 - <groupId>org.yaml</groupId>  
23 - <artifactId>snakeyaml</artifactId>  
24 - </dependency>  
25 -  
26 - <!-- 解析客户端操作系统、浏览器等 -->  
27 - <dependency>  
28 - <groupId>eu.bitwalker</groupId>  
29 - <artifactId>UserAgentUtils</artifactId>  
30 - </dependency>  
31 -  
32 -  
33 - </dependencies>  
34 -  
35 -</project>  
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java deleted
1 -package com.ruoyi.common.annotation;  
2 -  
3 -import java.lang.annotation.Documented;  
4 -import java.lang.annotation.ElementType;  
5 -import java.lang.annotation.Retention;  
6 -import java.lang.annotation.RetentionPolicy;  
7 -import java.lang.annotation.Target;  
8 -import com.ruoyi.common.enums.BusinessType;  
9 -import com.ruoyi.common.enums.OperatorType;  
10 -  
11 -/**  
12 - * 自定义操作日志记录注解  
13 - *  
14 - * @author ruoyi  
15 - *  
16 - */  
17 -@Target({ ElementType.PARAMETER, ElementType.METHOD })  
18 -@Retention(RetentionPolicy.RUNTIME)  
19 -@Documented  
20 -public @interface Log  
21 -{  
22 - /**  
23 - * 模块  
24 - */  
25 - public String title() default "";  
26 -  
27 - /**  
28 - * 功能  
29 - */  
30 - public BusinessType businessType() default BusinessType.OTHER;  
31 -  
32 - /**  
33 - * 操作人类别  
34 - */  
35 - public OperatorType operatorType() default OperatorType.MANAGE;  
36 -  
37 - /**  
38 - * 是否保存请求的参数  
39 - */  
40 - public boolean isSaveRequestData() default true;  
41 -}  
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java deleted
1 -package com.ruoyi.framework.aspectj;  
2 -  
3 -import java.lang.reflect.Method;  
4 -import java.util.Collection;  
5 -import java.util.Iterator;  
6 -import java.util.Map;  
7 -import javax.servlet.http.HttpServletRequest;  
8 -import javax.servlet.http.HttpServletResponse;  
9 -  
10 -import org.aspectj.lang.JoinPoint;  
11 -import org.aspectj.lang.Signature;  
12 -import org.aspectj.lang.annotation.AfterReturning;  
13 -import org.aspectj.lang.annotation.AfterThrowing;  
14 -import org.aspectj.lang.annotation.Aspect;  
15 -import org.aspectj.lang.annotation.Pointcut;  
16 -import org.aspectj.lang.reflect.MethodSignature;  
17 -import org.slf4j.Logger;  
18 -import org.slf4j.LoggerFactory;  
19 -import org.springframework.stereotype.Component;  
20 -import org.springframework.web.multipart.MultipartFile;  
21 -import org.springframework.web.servlet.HandlerMapping;  
22 -import com.alibaba.fastjson.JSON;  
23 -import com.ruoyi.common.annotation.Log;  
24 -import com.ruoyi.common.core.domain.model.LoginUser;  
25 -import com.ruoyi.common.enums.BusinessStatus;  
26 -import com.ruoyi.common.enums.HttpMethod;  
27 -import com.ruoyi.common.utils.ServletUtils;  
28 -import com.ruoyi.common.utils.StringUtils;  
29 -import com.ruoyi.common.utils.ip.IpUtils;  
30 -import com.ruoyi.common.utils.spring.SpringUtils;  
31 -import com.ruoyi.framework.manager.AsyncManager;  
32 -import com.ruoyi.framework.manager.factory.AsyncFactory;  
33 -import com.ruoyi.framework.web.service.TokenService;  
34 -import com.ruoyi.system.domain.SysOperLog;  
35 -  
36 -/**  
37 - * 操作日志记录处理  
38 - *  
39 - * @author ruoyi  
40 - */  
41 -@Aspect  
42 -@Component  
43 -public class LogAspect {  
44 - private static final Logger log = LoggerFactory.getLogger(LogAspect.class);  
45 -  
46 - // 配置织入点  
47 - @Pointcut("@annotation(com.ruoyi.common.annotation.Log)")  
48 - public void logPointCut() {  
49 - }  
50 -  
51 - /**  
52 - * 处理完请求后执行  
53 - *  
54 - * @param joinPoint 切点  
55 - */  
56 - @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")  
57 - public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {  
58 - handleLog(joinPoint, null, jsonResult);  
59 - }  
60 -  
61 - /**  
62 - * 拦截异常操作  
63 - *  
64 - * @param joinPoint 切点  
65 - * @param e 异常  
66 - */  
67 - @AfterThrowing(value = "logPointCut()", throwing = "e")  
68 - public void doAfterThrowing(JoinPoint joinPoint, Exception e) {  
69 - handleLog(joinPoint, e, null);  
70 - }  
71 -  
72 - protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {  
73 - try {  
74 - // 获得注解  
75 - Log controllerLog = getAnnotationLog(joinPoint);  
76 - if (controllerLog == null) {  
77 - return;  
78 - }  
79 -  
80 - // 获取当前的用户  
81 - LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());  
82 -  
83 - // *========数据库日志=========*//  
84 - SysOperLog operLog = new SysOperLog();  
85 - operLog.setStatus(BusinessStatus.SUCCESS.ordinal());  
86 - // 请求的地址  
87 - String ip = IpUtils.getIpAddr(ServletUtils.getRequest());  
88 - operLog.setOperIp(ip);  
89 - // 返回参数  
90 - operLog.setJsonResult(JSON.toJSONString(jsonResult));  
91 -  
92 - operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());  
93 - if (loginUser != null) {  
94 - operLog.setOperName(loginUser.getUsername());  
95 - }  
96 -  
97 - if (e != null) {  
98 - operLog.setStatus(BusinessStatus.FAIL.ordinal());  
99 - operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));  
100 - }  
101 - // 设置方法名称  
102 - String className = joinPoint.getTarget().getClass().getName();  
103 - String methodName = joinPoint.getSignature().getName();  
104 - operLog.setMethod(className + "." + methodName + "()");  
105 - // 设置请求方式  
106 - operLog.setRequestMethod(ServletUtils.getRequest().getMethod());  
107 - // 处理设置注解上的参数  
108 - getControllerMethodDescription(joinPoint, controllerLog, operLog);  
109 - // 保存数据库  
110 - AsyncManager.me().execute(AsyncFactory.recordOper(operLog));  
111 - } catch (Exception exp) {  
112 - // 记录本地异常日志  
113 - log.error("==前置通知异常==");  
114 - log.error("异常信息:{}", exp.getMessage());  
115 - exp.printStackTrace();  
116 - }  
117 - }  
118 -  
119 - /**  
120 - * 参数拼装  
121 - */  
122 - private String argsArrayToString(Object[] paramsArray) {  
123 - String params = "";  
124 - if (paramsArray != null && paramsArray.length > 0) {  
125 - for (int i = 0; i < paramsArray.length; i++) {  
126 - if (!isFilterObject(paramsArray[i])) {  
127 - Object jsonObj = JSON.toJSON(paramsArray[i]);  
128 - params += jsonObj.toString() + " ";  
129 - }  
130 - }  
131 - }  
132 - return params.trim();  
133 - }  
134 -  
135 - /**  
136 - * 判断是否需要过滤的对象。  
137 - *  
138 - * @param o 对象信息。  
139 - * @return 如果是需要过滤的对象,则返回true;否则返回false。  
140 - */  
141 - @SuppressWarnings("rawtypes")  
142 - public boolean isFilterObject(final Object o) {  
143 - Class<?> clazz = o.getClass();  
144 - if (clazz.isArray()) {  
145 - return clazz.getComponentType().isAssignableFrom(MultipartFile.class);  
146 - } else if (Collection.class.isAssignableFrom(clazz)) {  
147 - Collection collection = (Collection) o;  
148 - for (Iterator iter = collection.iterator(); iter.hasNext(); ) {  
149 - return iter.next() instanceof MultipartFile;  
150 - }  
151 - } else if (Map.class.isAssignableFrom(clazz)) {  
152 - Map map = (Map) o;  
153 - for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {  
154 - Map.Entry entry = (Map.Entry) iter.next();  
155 - return entry.getValue() instanceof MultipartFile;  
156 - }  
157 - }  
158 - return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;  
159 - }  
160 -}  
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java deleted
1 -package com.ruoyi.framework.config;  
2 -  
3 -import java.util.TimeZone;  
4 -  
5 -import org.mybatis.spring.annotation.MapperScan;  
6 -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;  
7 -import org.springframework.context.annotation.Bean;  
8 -import org.springframework.context.annotation.Configuration;  
9 -import org.springframework.context.annotation.EnableAspectJAutoProxy;  
10 -  
11 -/**  
12 - * 程序注解配置  
13 - *  
14 - * @author ruoyi  
15 - */  
16 -@Configuration  
17 -// 表示通过aop框架暴露该代理对象,AopContext能够访问  
18 -@EnableAspectJAutoProxy(exposeProxy = true)  
19 -// 指定要扫描的Mapper类的包的路径  
20 -@MapperScan("com.ruoyi.**.mapper")  
21 -public class ApplicationConfig {  
22 - /**  
23 - * 时区配置  
24 - */  
25 - @Bean  
26 - public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {  
27 - return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());  
28 - }  
29 -}  
ruoyi-ui/src/api/monitor/operlog.js renamed to ruoyi-ui/src/api/system/operatelog.js
1 -import request from '@/utils/request'  
2 -  
3 -// 查询操作日志列表  
4 -export function list(query) {  
5 - return request({  
6 - url: '/monitor/operlog/list',  
7 - method: 'get',  
8 - params: query  
9 - })  
10 -}  
11 -  
12 -// 删除操作日志  
13 -export function delOperlog(operId) {  
14 - return request({  
15 - url: '/monitor/operlog/' + operId,  
16 - method: 'delete'  
17 - })  
18 -}  
19 -  
20 -// 清空操作日志  
21 -export function cleanOperlog() {  
22 - return request({  
23 - url: '/monitor/operlog/clean',  
24 - method: 'delete'  
25 - })  
26 -}  
27 -  
28 -// 导出操作日志  
29 -export function exportOperlog(query) {  
30 - return request({  
31 - url: '/monitor/operlog/export',  
32 - method: 'get',  
33 - params: query  
34 - })  
35 -}  
36 \ No newline at end of file 1 \ No newline at end of file
  2 +import request from '@/utils/request'
  3 +
  4 +// 查询操作日志列表
  5 +export function listOperateLog(query) {
  6 + return request({
  7 + url: '/system/operate-log/page',
  8 + method: 'get',
  9 + params: query
  10 + })
  11 +}
  12 +
  13 +// 导出操作日志
  14 +export function exportOperateLog(query) {
  15 + return request({
  16 + url: '/system/operate-log/export',
  17 + method: 'get',
  18 + params: query
  19 + })
  20 +}
ruoyi-ui/src/main.js
@@ -23,6 +23,7 @@ import RightToolbar from &quot;@/components/RightToolbar&quot; @@ -23,6 +23,7 @@ import RightToolbar from &quot;@/components/RightToolbar&quot;
23 // 代码高亮插件 23 // 代码高亮插件
24 import hljs from 'highlight.js' 24 import hljs from 'highlight.js'
25 import 'highlight.js/styles/github-gist.css' 25 import 'highlight.js/styles/github-gist.css'
  26 +import {DICT_TYPE, getDictDataLabel, getDictDatas} from "@/utils/dict";
26 27
27 // 全局方法挂载 28 // 全局方法挂载
28 Vue.prototype.getDicts = getDicts 29 Vue.prototype.getDicts = getDicts
@@ -32,6 +33,9 @@ Vue.prototype.resetForm = resetForm @@ -32,6 +33,9 @@ Vue.prototype.resetForm = resetForm
32 Vue.prototype.addDateRange = addDateRange 33 Vue.prototype.addDateRange = addDateRange
33 Vue.prototype.selectDictLabel = selectDictLabel 34 Vue.prototype.selectDictLabel = selectDictLabel
34 Vue.prototype.selectDictLabels = selectDictLabels 35 Vue.prototype.selectDictLabels = selectDictLabels
  36 +Vue.prototype.getDictDatas = getDictDatas
  37 +Vue.prototype.getDictDataLabel = getDictDataLabel
  38 +Vue.prototype.DICT_TYPE = DICT_TYPE
35 Vue.prototype.download = download 39 Vue.prototype.download = download
36 Vue.prototype.downloadExcel = downloadExcel 40 Vue.prototype.downloadExcel = downloadExcel
37 Vue.prototype.handleTree = handleTree 41 Vue.prototype.handleTree = handleTree
ruoyi-ui/src/utils/dict.js
@@ -12,6 +12,7 @@ export const DICT_TYPE = { @@ -12,6 +12,7 @@ export const DICT_TYPE = {
12 SYS_DATA_SCOPE: 'sys_data_scope', 12 SYS_DATA_SCOPE: 'sys_data_scope',
13 SYS_USER_SEX: 'sys_user_sex', 13 SYS_USER_SEX: 'sys_user_sex',
14 SYS_NOTICE_TYPE: 'sys_notice_type', 14 SYS_NOTICE_TYPE: 'sys_notice_type',
  15 + SYS_OPERATE_TYPE: 'sys_operate_type'
15 } 16 }
16 17
17 /** 18 /**
ruoyi-ui/src/views/monitor/operlog/index.vue renamed to ruoyi-ui/src/views/system/operatelog/index.vue
1 -<template>  
2 - <div class="app-container">  
3 - <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">  
4 - <el-form-item label="系统模块" prop="title">  
5 - <el-input  
6 - v-model="queryParams.title"  
7 - placeholder="请输入系统模块"  
8 - clearable  
9 - style="width: 240px;"  
10 - size="small"  
11 - @keyup.enter.native="handleQuery"  
12 - />  
13 - </el-form-item>  
14 - <el-form-item label="操作人员" prop="operName">  
15 - <el-input  
16 - v-model="queryParams.operName"  
17 - placeholder="请输入操作人员"  
18 - clearable  
19 - style="width: 240px;"  
20 - size="small"  
21 - @keyup.enter.native="handleQuery"  
22 - />  
23 - </el-form-item>  
24 - <el-form-item label="类型" prop="businessType">  
25 - <el-select  
26 - v-model="queryParams.businessType"  
27 - placeholder="操作类型"  
28 - clearable  
29 - size="small"  
30 - style="width: 240px"  
31 - >  
32 - <el-option  
33 - v-for="dict in typeOptions"  
34 - :key="dict.dictValue"  
35 - :label="dict.dictLabel"  
36 - :value="dict.dictValue"  
37 - />  
38 - </el-select>  
39 - </el-form-item>  
40 - <el-form-item label="状态" prop="status">  
41 - <el-select  
42 - v-model="queryParams.status"  
43 - placeholder="操作状态"  
44 - clearable  
45 - size="small"  
46 - style="width: 240px"  
47 - >  
48 - <el-option  
49 - v-for="dict in statusOptions"  
50 - :key="dict.dictValue"  
51 - :label="dict.dictLabel"  
52 - :value="dict.dictValue"  
53 - />  
54 - </el-select>  
55 - </el-form-item>  
56 - <el-form-item label="操作时间">  
57 - <el-date-picker  
58 - v-model="dateRange"  
59 - size="small"  
60 - style="width: 240px"  
61 - value-format="yyyy-MM-dd"  
62 - type="daterange"  
63 - range-separator="-"  
64 - start-placeholder="开始日期"  
65 - end-placeholder="结束日期"  
66 - ></el-date-picker>  
67 - </el-form-item>  
68 - <el-form-item>  
69 - <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>  
70 - <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>  
71 - </el-form-item>  
72 - </el-form>  
73 -  
74 - <el-row :gutter="10" class="mb8">  
75 - <el-col :span="1.5">  
76 - <el-button  
77 - type="danger"  
78 - icon="el-icon-delete"  
79 - size="mini"  
80 - :disabled="multiple"  
81 - @click="handleDelete"  
82 - v-hasPermi="['monitor:operlog:remove']"  
83 - >删除</el-button>  
84 - </el-col>  
85 - <el-col :span="1.5">  
86 - <el-button  
87 - type="danger"  
88 - icon="el-icon-delete"  
89 - size="mini"  
90 - @click="handleClean"  
91 - v-hasPermi="['monitor:operlog:remove']"  
92 - >清空</el-button>  
93 - </el-col>  
94 - <el-col :span="1.5">  
95 - <el-button  
96 - type="warning"  
97 - icon="el-icon-download"  
98 - size="mini"  
99 - @click="handleExport"  
100 - v-hasPermi="['system:config:export']"  
101 - >导出</el-button>  
102 - </el-col>  
103 - <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>  
104 - </el-row>  
105 -  
106 - <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">  
107 - <el-table-column type="selection" width="55" align="center" />  
108 - <el-table-column label="日志编号" align="center" prop="operId" />  
109 - <el-table-column label="系统模块" align="center" prop="title" />  
110 - <el-table-column label="操作类型" align="center" prop="businessType" :formatter="typeFormat" />  
111 - <el-table-column label="请求方式" align="center" prop="requestMethod" />  
112 - <el-table-column label="操作人员" align="center" prop="operName" />  
113 - <el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />  
114 - <el-table-column label="操作地点" align="center" prop="operLocation" :show-overflow-tooltip="true" />  
115 - <el-table-column label="操作状态" align="center" prop="status" :formatter="statusFormat" />  
116 - <el-table-column label="操作日期" align="center" prop="operTime" width="180">  
117 - <template slot-scope="scope">  
118 - <span>{{ parseTime(scope.row.operTime) }}</span>  
119 - </template>  
120 - </el-table-column>  
121 - <el-table-column label="操作" align="center" class-name="small-padding fixed-width">  
122 - <template slot-scope="scope">  
123 - <el-button  
124 - size="mini"  
125 - type="text"  
126 - icon="el-icon-view"  
127 - @click="handleView(scope.row,scope.index)"  
128 - v-hasPermi="['monitor:operlog:query']"  
129 - >详细</el-button>  
130 - </template>  
131 - </el-table-column>  
132 - </el-table>  
133 -  
134 - <pagination  
135 - v-show="total>0"  
136 - :total="total"  
137 - :page.sync="queryParams.pageNum"  
138 - :limit.sync="queryParams.pageSize"  
139 - @pagination="getList"  
140 - />  
141 -  
142 - <!-- 操作日志详细 -->  
143 - <el-dialog title="操作日志详细" :visible.sync="open" width="700px" append-to-body>  
144 - <el-form ref="form" :model="form" label-width="100px" size="mini">  
145 - <el-row>  
146 - <el-col :span="12">  
147 - <el-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>  
148 - <el-form-item  
149 - label="登录信息:"  
150 - >{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>  
151 - </el-col>  
152 - <el-col :span="12">  
153 - <el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>  
154 - <el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>  
155 - </el-col>  
156 - <el-col :span="24">  
157 - <el-form-item label="操作方法:">{{ form.method }}</el-form-item>  
158 - </el-col>  
159 - <el-col :span="24">  
160 - <el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>  
161 - </el-col>  
162 - <el-col :span="24">  
163 - <el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>  
164 - </el-col>  
165 - <el-col :span="12">  
166 - <el-form-item label="操作状态:">  
167 - <div v-if="form.status === 0">正常</div>  
168 - <div v-else-if="form.status === 1">失败</div>  
169 - </el-form-item>  
170 - </el-col>  
171 - <el-col :span="12">  
172 - <el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>  
173 - </el-col>  
174 - <el-col :span="24">  
175 - <el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>  
176 - </el-col>  
177 - </el-row>  
178 - </el-form>  
179 - <div slot="footer" class="dialog-footer">  
180 - <el-button @click="open = false">关 闭</el-button>  
181 - </div>  
182 - </el-dialog>  
183 - </div>  
184 -</template>  
185 -  
186 -<script>  
187 -import { list, delOperlog, cleanOperlog, exportOperlog } from "@/api/monitor/operlog";  
188 -  
189 -export default {  
190 - name: "Operlog",  
191 - data() {  
192 - return {  
193 - // 遮罩层  
194 - loading: true,  
195 - // 选中数组  
196 - ids: [],  
197 - // 非多个禁用  
198 - multiple: true,  
199 - // 显示搜索条件  
200 - showSearch: true,  
201 - // 总条数  
202 - total: 0,  
203 - // 表格数据  
204 - list: [],  
205 - // 是否显示弹出层  
206 - open: false,  
207 - // 类型数据字典  
208 - typeOptions: [],  
209 - // 类型数据字典  
210 - statusOptions: [],  
211 - // 日期范围  
212 - dateRange: [],  
213 - // 表单参数  
214 - form: {},  
215 - // 查询参数  
216 - queryParams: {  
217 - pageNum: 1,  
218 - pageSize: 10,  
219 - title: undefined,  
220 - operName: undefined,  
221 - businessType: undefined,  
222 - status: undefined  
223 - }  
224 - };  
225 - },  
226 - created() {  
227 - this.getList();  
228 - this.getDicts("sys_oper_type").then(response => {  
229 - this.typeOptions = response.data;  
230 - });  
231 - this.getDicts("sys_common_status").then(response => {  
232 - this.statusOptions = response.data;  
233 - });  
234 - },  
235 - methods: {  
236 - /** 查询登录日志 */  
237 - getList() {  
238 - this.loading = true;  
239 - list(this.addDateRange(this.queryParams, this.dateRange)).then( response => {  
240 - this.list = response.rows;  
241 - this.total = response.total;  
242 - this.loading = false;  
243 - }  
244 - );  
245 - },  
246 - // 操作日志状态字典翻译  
247 - statusFormat(row, column) {  
248 - return this.selectDictLabel(this.statusOptions, row.status);  
249 - },  
250 - // 操作日志类型字典翻译  
251 - typeFormat(row, column) {  
252 - return this.selectDictLabel(this.typeOptions, row.businessType);  
253 - },  
254 - /** 搜索按钮操作 */  
255 - handleQuery() {  
256 - this.queryParams.pageNum = 1;  
257 - this.getList();  
258 - },  
259 - /** 重置按钮操作 */  
260 - resetQuery() {  
261 - this.dateRange = [];  
262 - this.resetForm("queryForm");  
263 - this.handleQuery();  
264 - },  
265 - // 多选框选中数据  
266 - handleSelectionChange(selection) {  
267 - this.ids = selection.map(item => item.operId)  
268 - this.multiple = !selection.length  
269 - },  
270 - /** 详细按钮操作 */  
271 - handleView(row) {  
272 - this.open = true;  
273 - this.form = row;  
274 - },  
275 - /** 删除按钮操作 */  
276 - handleDelete(row) {  
277 - const operIds = row.operId || this.ids;  
278 - this.$confirm('是否确认删除日志编号为"' + operIds + '"的数据项?', "警告", {  
279 - confirmButtonText: "确定",  
280 - cancelButtonText: "取消",  
281 - type: "warning"  
282 - }).then(function() {  
283 - return delOperlog(operIds);  
284 - }).then(() => {  
285 - this.getList();  
286 - this.msgSuccess("删除成功");  
287 - })  
288 - },  
289 - /** 清空按钮操作 */  
290 - handleClean() {  
291 - this.$confirm('是否确认清空所有操作日志数据项?', "警告", {  
292 - confirmButtonText: "确定",  
293 - cancelButtonText: "取消",  
294 - type: "warning"  
295 - }).then(function() {  
296 - return cleanOperlog();  
297 - }).then(() => {  
298 - this.getList();  
299 - this.msgSuccess("清空成功");  
300 - })  
301 - },  
302 - /** 导出按钮操作 */  
303 - handleExport() {  
304 - const queryParams = this.queryParams;  
305 - this.$confirm('是否确认导出所有操作日志数据项?', "警告", {  
306 - confirmButtonText: "确定",  
307 - cancelButtonText: "取消",  
308 - type: "warning"  
309 - }).then(function() {  
310 - return exportOperlog(queryParams);  
311 - }).then(response => {  
312 - this.download(response.msg);  
313 - })  
314 - }  
315 - }  
316 -};  
317 -</script>  
318 - 1 +<template>
  2 + <div class="app-container">
  3 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  4 + <el-form-item label="系统模块" prop="title">
  5 + <el-input
  6 + v-model="queryParams.title"
  7 + placeholder="请输入系统模块"
  8 + clearable
  9 + style="width: 240px;"
  10 + size="small"
  11 + @keyup.enter.native="handleQuery"
  12 + />
  13 + </el-form-item>
  14 + <el-form-item label="操作人员" prop="operName">
  15 + <el-input
  16 + v-model="queryParams.operName"
  17 + placeholder="请输入操作人员"
  18 + clearable
  19 + style="width: 240px;"
  20 + size="small"
  21 + @keyup.enter.native="handleQuery"
  22 + />
  23 + </el-form-item>
  24 + <el-form-item label="类型" prop="type">
  25 + <el-select
  26 + v-model="queryParams.type"
  27 + placeholder="操作类型"
  28 + clearable
  29 + size="small"
  30 + style="width: 240px"
  31 + >
  32 + <el-option
  33 + v-for="dict in this.getDictDatas(DICT_TYPE.SYS_OPERATE_TYPE)"
  34 + :key="parseInt(dict.value)"
  35 + :label="dict.label"
  36 + :value="parseInt(dict.value)"
  37 + />
  38 + </el-select>
  39 + </el-form-item>
  40 + <el-form-item label="状态" prop="status">
  41 + <el-select
  42 + v-model="queryParams.success"
  43 + placeholder="操作状态"
  44 + clearable
  45 + size="small"
  46 + style="width: 240px"
  47 + >
  48 + <el-option
  49 + :key="true"
  50 + label="成功"
  51 + :value="true"
  52 + />
  53 + <el-option
  54 + :key="false"
  55 + label="失败"
  56 + :value="false"
  57 + />
  58 + </el-select>
  59 + </el-form-item>
  60 + <el-form-item label="操作时间">
  61 + <el-date-picker
  62 + v-model="dateRange"
  63 + size="small"
  64 + style="width: 240px"
  65 + value-format="yyyy-MM-dd"
  66 + type="daterange"
  67 + range-separator="-"
  68 + start-placeholder="开始日期"
  69 + end-placeholder="结束日期"
  70 + ></el-date-picker>
  71 + </el-form-item>
  72 + <el-form-item>
  73 + <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  74 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  75 + </el-form-item>
  76 + </el-form>
  77 +
  78 + <el-row :gutter="10" class="mb8">
  79 + <el-col :span="1.5">
  80 + <el-button
  81 + type="warning"
  82 + icon="el-icon-download"
  83 + size="mini"
  84 + @click="handleExport"
  85 + v-hasPermi="['system:config:export']"
  86 + >导出</el-button>
  87 + </el-col>
  88 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  89 + </el-row>
  90 +
  91 + <el-table v-loading="loading" :data="list">
  92 + <el-table-column label="日志编号" align="center" prop="id" />
  93 + <el-table-column label="操作模块" align="center" prop="module" />
  94 + <el-table-column label="操作名" align="center" prop="name" width="180" />
  95 + <el-table-column label="操作类型" align="center" prop="type">
  96 + <template slot-scope="scope">
  97 + <span>{{ getDictDataLabel(DICT_TYPE.SYS_OPERATE_TYPE, scope.row.type) }}</span>
  98 + </template>
  99 + </el-table-column>
  100 + <el-table-column label="操作人" align="center" prop="userNickname" />
  101 + <el-table-column label="操作结果" align="center" prop="status">
  102 + <template slot-scope="scope">
  103 + <span>{{ scope.row.resultCode === 0 ? '成功' : '失败' }}</span>
  104 + </template>
  105 + </el-table-column>
  106 + <el-table-column label="操作日期" align="center" prop="startTime" width="180">
  107 + <template slot-scope="scope">
  108 + <span>{{ parseTime(scope.row.startTime) }}</span>
  109 + </template>
  110 + </el-table-column>
  111 + <el-table-column label="执行时长" align="center" prop="startTime">
  112 + <template slot-scope="scope">
  113 + <span>{{ scope.row.duration }} ms</span>
  114 + </template>
  115 + </el-table-column>
  116 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  117 + <template slot-scope="scope">
  118 + <el-button
  119 + size="mini"
  120 + type="text"
  121 + icon="el-icon-view"
  122 + @click="handleView(scope.row,scope.index)"
  123 + v-hasPermi="['system:operate-log:query']"
  124 + >详细</el-button>
  125 + </template>
  126 + </el-table-column>
  127 + </el-table>
  128 +
  129 + <pagination
  130 + v-show="total>0"
  131 + :total="total"
  132 + :page.sync="queryParams.pageNo"
  133 + :limit.sync="queryParams.pageSize"
  134 + @pagination="getList"
  135 + />
  136 +
  137 + <!-- 操作日志详细 -->
  138 + <el-dialog title="操作日志详细" :visible.sync="open" width="700px" append-to-body>
  139 + <el-form ref="form" :model="form" label-width="100px" size="mini">
  140 + <el-row>
  141 + <el-col :span="12">
  142 + <el-form-item label="操作模块:">{{ form.title }} / {{ typeFormat(form) }}</el-form-item>
  143 + <el-form-item
  144 + label="登录信息:"
  145 + >{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item>
  146 + </el-col>
  147 + <el-col :span="12">
  148 + <el-form-item label="请求地址:">{{ form.operUrl }}</el-form-item>
  149 + <el-form-item label="请求方式:">{{ form.requestMethod }}</el-form-item>
  150 + </el-col>
  151 + <el-col :span="24">
  152 + <el-form-item label="操作方法:">{{ form.method }}</el-form-item>
  153 + </el-col>
  154 + <el-col :span="24">
  155 + <el-form-item label="请求参数:">{{ form.operParam }}</el-form-item>
  156 + </el-col>
  157 + <el-col :span="24">
  158 + <el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item>
  159 + </el-col>
  160 + <el-col :span="12">
  161 + <el-form-item label="操作状态:">
  162 + <div v-if="form.status === 0">正常</div>
  163 + <div v-else-if="form.status === 1">失败</div>
  164 + </el-form-item>
  165 + </el-col>
  166 + <el-col :span="12">
  167 + <el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item>
  168 + </el-col>
  169 + <el-col :span="24">
  170 + <el-form-item label="异常信息:" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item>
  171 + </el-col>
  172 + </el-row>
  173 + </el-form>
  174 + <div slot="footer" class="dialog-footer">
  175 + <el-button @click="open = false">关 闭</el-button>
  176 + </div>
  177 + </el-dialog>
  178 + </div>
  179 +</template>
  180 +
  181 +<script>
  182 +import { listOperateLog, exportOperateLog } from "@/api/system/operatelog";
  183 +
  184 +export default {
  185 + name: "Operlog",
  186 + data() {
  187 + return {
  188 + // 遮罩层
  189 + loading: true,
  190 + // 显示搜索条件
  191 + showSearch: true,
  192 + // 总条数
  193 + total: 0,
  194 + // 表格数据
  195 + list: [],
  196 + // 是否显示弹出层
  197 + open: false,
  198 + // 类型数据字典
  199 + typeOptions: [],
  200 + // 类型数据字典
  201 + statusOptions: [],
  202 + // 日期范围
  203 + dateRange: [],
  204 + // 表单参数
  205 + form: {},
  206 + // 查询参数
  207 + queryParams: {
  208 + pageNo: 1,
  209 + pageSize: 10,
  210 + title: undefined,
  211 + operName: undefined,
  212 + businessType: undefined,
  213 + status: undefined
  214 + },
  215 +
  216 + };
  217 + },
  218 + created() {
  219 + this.getList();
  220 + },
  221 + methods: {
  222 + /** 查询登录日志 */
  223 + getList() {
  224 + this.loading = true;
  225 + listOperateLog(this.addDateRange(this.queryParams, [
  226 + this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
  227 + this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
  228 + ])).then( response => {
  229 + this.list = response.data.list;
  230 + this.total = response.data.total;
  231 + this.loading = false;
  232 + }
  233 + );
  234 + },
  235 + // 操作日志状态字典翻译
  236 + statusFormat(row, column) {
  237 + return this.selectDictLabel(this.statusOptions, row.status);
  238 + },
  239 + // 操作日志类型字典翻译
  240 + typeFormat(row, column) {
  241 + return this.selectDictLabel(this.typeOptions, row.businessType);
  242 + },
  243 + /** 搜索按钮操作 */
  244 + handleQuery() {
  245 + this.queryParams.pageNo = 1;
  246 + this.getList();
  247 + },
  248 + /** 重置按钮操作 */
  249 + resetQuery() {
  250 + this.dateRange = [];
  251 + this.resetForm("queryForm");
  252 + this.handleQuery();
  253 + },
  254 + /** 详细按钮操作 */
  255 + handleView(row) {
  256 + this.open = true;
  257 + this.form = row;
  258 + },
  259 + /** 导出按钮操作 */
  260 + handleExport() {
  261 + const queryParams = this.queryParams;
  262 + this.$confirm('是否确认导出所有操作日志数据项?', "警告", {
  263 + confirmButtonText: "确定",
  264 + cancelButtonText: "取消",
  265 + type: "warning"
  266 + }).then(function() {
  267 + return exportOperateLog(queryParams);
  268 + }).then(response => {
  269 + this.download(response.msg);
  270 + })
  271 + }
  272 + }
  273 +};
  274 +</script>
  275 +
sql/ruoyi-vue-pro-data.sql 0 → 100644
  1 +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');
  2 +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');
  3 +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');
  4 +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');
  5 +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');
  6 +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');
  7 +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');
  8 +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');
  9 +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');
  10 +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');
  11 +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');
  12 +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');
  13 +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');
  14 +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');
  15 +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');
  16 +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');
  17 +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');
  18 +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');
  19 +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');
  20 +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');
  21 +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');
  22 +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');
  23 +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');
  24 +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');
  25 +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');
  26 +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');
  27 +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');
  28 +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');
  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 (38, 5, '仅本人数据权限', '5', 'sys_data_scope', 0, '仅本人数据权限', 'admin', '2021-01-05 17:03:48', '', '2021-01-06 19:38:38', b'0');
src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java
@@ -31,4 +31,8 @@ public final class PageResult&lt;T&gt; implements Serializable { @@ -31,4 +31,8 @@ public final class PageResult&lt;T&gt; implements Serializable {
31 this.total = total; 31 this.total = total;
32 } 32 }
33 33
  34 + public static <T> PageResult<T> empty() {
  35 + return new PageResult<>(0L);
  36 + }
  37 +
34 } 38 }
src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java
@@ -4,6 +4,6 @@ import org.springframework.context.annotation.Configuration; @@ -4,6 +4,6 @@ import org.springframework.context.annotation.Configuration;
4 import org.springframework.scheduling.annotation.EnableAsync; 4 import org.springframework.scheduling.annotation.EnableAsync;
5 5
6 @Configuration 6 @Configuration
7 -@EnableAsync(proxyTargetClass = true) 7 +@EnableAsync
8 public class AsyncConfiguration { 8 public class AsyncConfiguration {
9 } 9 }
src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java
1 package cn.iocoder.dashboard.framework.logger.operatelog.core.annotations; 1 package cn.iocoder.dashboard.framework.logger.operatelog.core.annotations;
2 2
3 -import cn.iocoder.dashboard.modules.system.enums.logger.SysOperateLogTypeEnum; 3 +import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
4 import io.swagger.annotations.Api; 4 import io.swagger.annotations.Api;
5 import io.swagger.annotations.ApiOperation; 5 import io.swagger.annotations.ApiOperation;
6 6
@@ -32,7 +32,7 @@ public @interface OperateLog { @@ -32,7 +32,7 @@ public @interface OperateLog {
32 * 32 *
33 * 实际并不是数组,因为枚举不能设置 null 作为默认值 33 * 实际并不是数组,因为枚举不能设置 null 作为默认值
34 */ 34 */
35 - SysOperateLogTypeEnum[] type() default {}; 35 + OperateLogTypeEnum[] type() default {};
36 36
37 // ========== 开关字段 ========== 37 // ========== 开关字段 ==========
38 38
src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java
@@ -6,11 +6,11 @@ import cn.hutool.core.util.StrUtil; @@ -6,11 +6,11 @@ import cn.hutool.core.util.StrUtil;
6 import cn.hutool.extra.servlet.ServletUtil; 6 import cn.hutool.extra.servlet.ServletUtil;
7 import cn.iocoder.dashboard.common.pojo.CommonResult; 7 import cn.iocoder.dashboard.common.pojo.CommonResult;
8 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; 8 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
  9 +import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
9 import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService; 10 import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService;
10 import cn.iocoder.dashboard.framework.security.core.util.SecurityUtils; 11 import cn.iocoder.dashboard.framework.security.core.util.SecurityUtils;
11 import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils; 12 import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
12 import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO; 13 import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO;
13 -import cn.iocoder.dashboard.modules.system.enums.logger.SysOperateLogTypeEnum;  
14 import cn.iocoder.dashboard.util.servlet.ServletUtils; 14 import cn.iocoder.dashboard.util.servlet.ServletUtils;
15 import com.alibaba.fastjson.JSON; 15 import com.alibaba.fastjson.JSON;
16 import com.google.common.collect.Maps; 16 import com.google.common.collect.Maps;
@@ -180,7 +180,7 @@ public class OperateLogAspect { @@ -180,7 +180,7 @@ public class OperateLogAspect {
180 } 180 }
181 if (operateLogVO.getType() == null) { 181 if (operateLogVO.getType() == null) {
182 RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); 182 RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint));
183 - SysOperateLogTypeEnum operateLogType = convertOperateLogType(requestMethod); 183 + OperateLogTypeEnum operateLogType = convertOperateLogType(requestMethod);
184 operateLogVO.setType(operateLogType != null ? operateLogType.getType() : null); 184 operateLogVO.setType(operateLogType != null ? operateLogType.getType() : null);
185 } 185 }
186 // content 和 exts 属性 186 // content 和 exts 属性
@@ -275,21 +275,21 @@ public class OperateLogAspect { @@ -275,21 +275,21 @@ public class OperateLogAspect {
275 return requestMethods[0]; 275 return requestMethods[0];
276 } 276 }
277 277
278 - private static SysOperateLogTypeEnum convertOperateLogType(RequestMethod requestMethod) { 278 + private static OperateLogTypeEnum convertOperateLogType(RequestMethod requestMethod) {
279 if (requestMethod == null) { 279 if (requestMethod == null) {
280 return null; 280 return null;
281 } 281 }
282 switch (requestMethod) { 282 switch (requestMethod) {
283 case GET: 283 case GET:
284 - return SysOperateLogTypeEnum.GET; 284 + return OperateLogTypeEnum.GET;
285 case POST: 285 case POST:
286 - return SysOperateLogTypeEnum.CREATE; 286 + return OperateLogTypeEnum.CREATE;
287 case PUT: 287 case PUT:
288 - return SysOperateLogTypeEnum.UPDATE; 288 + return OperateLogTypeEnum.UPDATE;
289 case DELETE: 289 case DELETE:
290 - return SysOperateLogTypeEnum.DELETE; 290 + return OperateLogTypeEnum.DELETE;
291 default: 291 default:
292 - return SysOperateLogTypeEnum.OTHER; 292 + return OperateLogTypeEnum.OTHER;
293 } 293 }
294 } 294 }
295 295
src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysOperateLogTypeEnum.java renamed to src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateLogTypeEnum.java
1 -package cn.iocoder.dashboard.modules.system.enums.logger; 1 +package cn.iocoder.dashboard.framework.logger.operatelog.core.enums;
2 2
3 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; 3 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
4 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
@@ -11,7 +11,7 @@ import lombok.Getter; @@ -11,7 +11,7 @@ import lombok.Getter;
11 */ 11 */
12 @Getter 12 @Getter
13 @AllArgsConstructor 13 @AllArgsConstructor
14 -public enum SysOperateLogTypeEnum { 14 +public enum OperateLogTypeEnum {
15 15
16 /** 16 /**
17 * 查询 17 * 查询
src/main/java/cn/iocoder/dashboard/framework/mybatis/core/mapper/BaseMapperX.java 0 → 100644
  1 +package cn.iocoder.dashboard.framework.mybatis.core.mapper;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.PageParam;
  4 +import cn.iocoder.dashboard.common.pojo.PageResult;
  5 +import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
  6 +import com.baomidou.mybatisplus.core.conditions.Wrapper;
  7 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  8 +import com.baomidou.mybatisplus.core.metadata.IPage;
  9 +import org.apache.ibatis.annotations.Param;
  10 +
  11 +/**
  12 + * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
  13 + */
  14 +public interface BaseMapperX<T> extends BaseMapper<T> {
  15 +
  16 + default PageResult<T> selectPage(PageParam pageParam, @Param("ew") Wrapper<T> queryWrapper) {
  17 + // MyBatis Plus 查询
  18 + IPage<T> mpPage = MyBatisUtils.buildPage(pageParam);
  19 + selectPage(mpPage, queryWrapper);
  20 + // 转换返回
  21 + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
  22 + }
  23 +
  24 +}
src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java
@@ -54,7 +54,6 @@ public class SysAuthController { @@ -54,7 +54,6 @@ public class SysAuthController {
54 54
55 @ApiOperation("获取登陆用户的权限信息") 55 @ApiOperation("获取登陆用户的权限信息")
56 @GetMapping("/get-permission-info") 56 @GetMapping("/get-permission-info")
57 - @OperateLog  
58 public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() { 57 public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() {
59 // 获得用户信息 58 // 获得用户信息
60 SysUserDO user = userService.getUser(getLoginUserId()); 59 SysUserDO user = userService.getUser(getLoginUserId());
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http
1 ### 请求 /captcha/get-image 接口 => 成功 1 ### 请求 /captcha/get-image 接口 => 成功
2 -GET {{baseUrl}}/captcha/get-image 2 +GET {{baseUrl}}/system/captcha/get-image
src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java
@@ -23,7 +23,7 @@ public class SysCaptchaController { @@ -23,7 +23,7 @@ public class SysCaptchaController {
23 23
24 @ApiOperation("生成图片验证码") 24 @ApiOperation("生成图片验证码")
25 @GetMapping("/get-image") 25 @GetMapping("/get-image")
26 - private CommonResult<SysCaptchaImageRespVO> getCaptchaImage() { 26 + public CommonResult<SysCaptchaImageRespVO> getCaptchaImage() {
27 return success(captchaService.getCaptchaImage()); 27 return success(captchaService.getCaptchaImage());
28 } 28 }
29 29
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.http 0 → 100644
  1 +### 请求 /system/operate-log/demo 接口 => 成功
  2 +GET {{baseUrl}}/system/operate-log/demo
  3 +Authorization: Bearer {{token}}
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.logger;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.CommonResult;
  4 +import cn.iocoder.dashboard.common.pojo.PageResult;
  5 +import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
  6 +import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
  7 +import cn.iocoder.dashboard.framework.logger.operatelog.core.util.OperateLogUtils;
  8 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
  9 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogRespVO;
  10 +import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert;
  11 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
  12 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
  13 +import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService;
  14 +import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
  15 +import cn.iocoder.dashboard.util.collection.CollectionUtils;
  16 +import cn.iocoder.dashboard.util.collection.MapUtils;
  17 +import io.swagger.annotations.Api;
  18 +import io.swagger.annotations.ApiOperation;
  19 +import org.springframework.validation.annotation.Validated;
  20 +import org.springframework.web.bind.annotation.GetMapping;
  21 +import org.springframework.web.bind.annotation.RequestMapping;
  22 +import org.springframework.web.bind.annotation.RestController;
  23 +
  24 +import javax.annotation.Resource;
  25 +import java.util.ArrayList;
  26 +import java.util.Collection;
  27 +import java.util.List;
  28 +import java.util.Map;
  29 +
  30 +import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
  31 +
  32 +@Api(tags = "操作日志 API")
  33 +@RestController
  34 +@RequestMapping("/system/operate-log")
  35 +public class SysOperateLogController {
  36 +
  37 + @Resource
  38 + private SysOperateLogService operateLogService;
  39 +
  40 + @Resource
  41 + private SysUserService userService;
  42 +
  43 + @ApiOperation("示例")
  44 + @OperateLog(type = OperateLogTypeEnum.OTHER)
  45 + @GetMapping("/demo")
  46 + public CommonResult<Boolean> demo() {
  47 + // 这里可以调用业务逻辑
  48 +
  49 + // 补全操作日志的明细
  50 + OperateLogUtils.setContent("将编号 1 的数据,xxx 字段修改成了 yyyy");
  51 + OperateLogUtils.addExt("orderId", 1);
  52 +
  53 + // 响应
  54 + return success(true);
  55 + }
  56 +
  57 + @ApiOperation("查看操作日志分页列表")
  58 + @GetMapping("/page")
  59 +// @PreAuthorize("@ss.hasPermi('system:operate-log:query')")
  60 + public CommonResult<PageResult<SysOperateLogRespVO>> pageOperateLog(@Validated SysOperateLogPageReqVO reqVO) {
  61 + PageResult<SysOperateLogDO> pageResult = operateLogService.pageOperateLog(reqVO);
  62 +
  63 + // 获得拼接需要的数据
  64 + Collection<Long> userIds = CollectionUtils.convertList(pageResult.getList(), SysOperateLogDO::getUserId);
  65 + Map<Long, SysUserDO> userMap = userService.getUserMap(userIds);
  66 + // 拼接数据
  67 + List<SysOperateLogRespVO> list = new ArrayList<>(pageResult.getList().size());
  68 + pageResult.getList().forEach(operateLog -> {
  69 + SysOperateLogRespVO respVO = SysOperateLogConvert.INSTANCE.convert(operateLog);
  70 + list.add(respVO);
  71 + // 拼接用户信息
  72 + MapUtils.findAndThen(userMap, operateLog.getUserId(), user -> respVO.setUserNickname(user.getNickname()));
  73 + });
  74 + return success(new PageResult<>(list, pageResult.getTotal()));
  75 + }
  76 +
  77 +// @Log(title = "操作日志", businessType = BusinessType.EXPORT)
  78 +// @PreAuthorize("@ss.hasPermi('system:operate-log:export')")
  79 +// @GetMapping("/export")
  80 +// public AjaxResult export(SysOperLog operLog) {
  81 +// List<SysOperLog> list = operLogService.selectOperLogList(operLog);
  82 +// ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
  83 +// return util.exportExcel(list, "操作日志");
  84 +// }
  85 +
  86 +}
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/package-info.java deleted
1 -package cn.iocoder.dashboard.modules.system.controller.logger;  
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java
@@ -6,6 +6,7 @@ import lombok.Data; @@ -6,6 +6,7 @@ import lombok.Data;
6 import javax.validation.constraints.NotEmpty; 6 import javax.validation.constraints.NotEmpty;
7 import javax.validation.constraints.NotNull; 7 import javax.validation.constraints.NotNull;
8 import java.util.Date; 8 import java.util.Date;
  9 +import java.util.Map;
9 10
10 /** 11 /**
11 * 操作日志 Base VO,提供给添加、修改、详细的子 VO 使用 12 * 操作日志 Base VO,提供给添加、修改、详细的子 VO 使用
@@ -30,10 +31,16 @@ public class SysOperateLogBaseVO { @@ -30,10 +31,16 @@ public class SysOperateLogBaseVO {
30 @NotEmpty(message = "操作名") 31 @NotEmpty(message = "操作名")
31 private String name; 32 private String name;
32 33
33 - @ApiModelProperty(value = "操作分类", required = true, example = "操作分类", notes = "参见 SysOperateLogTypeEnum 枚举类") 34 + @ApiModelProperty(value = "操作分类", required = true, example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类")
34 @NotNull(message = "操作分类不能为空") 35 @NotNull(message = "操作分类不能为空")
35 private Integer type; 36 private Integer type;
36 37
  38 + @ApiModelProperty(value = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。")
  39 + private String content;
  40 +
  41 + @ApiModelProperty(value = "拓展字段", example = "{'orderId': 1}")
  42 + private Map<String, Object> exts;
  43 +
37 @ApiModelProperty(value = "请求方法名", required = true, example = "GET") 44 @ApiModelProperty(value = "请求方法名", required = true, example = "GET")
38 @NotEmpty(message = "请求方法名不能为空") 45 @NotEmpty(message = "请求方法名不能为空")
39 private String requestMethod; 46 private String requestMethod;
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogPageReqVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.logger.vo;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.util.Date;
  11 +
  12 +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@ApiModel("操作日志分页列表 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +public class SysOperateLogPageReqVO extends PageParam {
  18 +
  19 + @ApiModelProperty(value = "操作模块", example = "订单", notes = "模拟匹配")
  20 + private String module;
  21 +
  22 + @ApiModelProperty(value = "用户昵称", example = "芋道", notes = "模拟匹配")
  23 + private String userNickname;
  24 +
  25 + @ApiModelProperty(value = "操作分类", example = "1", notes = "参见 SysOperateLogTypeEnum 枚举类")
  26 + private Integer type;
  27 +
  28 + @ApiModelProperty(value = "操作状态", example = "true")
  29 + private Boolean success;
  30 +
  31 + @ApiModelProperty(value = "开始时间", example = "2020-10-24")
  32 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  33 + private Date beginTime;
  34 +
  35 + @ApiModelProperty(value = "结束时间", example = "2020-10-24")
  36 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  37 + private Date endTime;
  38 +
  39 +}
src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogRespVO.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.system.controller.logger.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +@ApiModel("操作日志 Response VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class SysOperateLogRespVO extends SysOperateLogBaseVO {
  14 +
  15 + @ApiModelProperty(value = "日志编号", required = true, example = "1024")
  16 + private Long id;
  17 +
  18 + @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
  19 + private String userNickname;
  20 +
  21 +}
src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java
1 package cn.iocoder.dashboard.modules.system.convert.logger; 1 package cn.iocoder.dashboard.modules.system.convert.logger;
2 2
  3 +import cn.iocoder.dashboard.common.pojo.PageResult;
3 import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO; 4 import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO;
  5 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogRespVO;
4 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO; 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
5 import org.mapstruct.Mapper; 7 import org.mapstruct.Mapper;
6 import org.mapstruct.factory.Mappers; 8 import org.mapstruct.factory.Mappers;
@@ -12,4 +14,8 @@ public interface SysOperateLogConvert { @@ -12,4 +14,8 @@ public interface SysOperateLogConvert {
12 14
13 SysOperateLogDO convert(SysOperateLogCreateReqVO bean); 15 SysOperateLogDO convert(SysOperateLogCreateReqVO bean);
14 16
  17 + PageResult<SysOperateLogRespVO> convertPage(PageResult<SysOperateLogDO> page);
  18 +
  19 + SysOperateLogRespVO convert(SysOperateLogDO bean);
  20 +
15 } 21 }
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysOperateLogMapper.java
1 package cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger; 1 package cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger;
2 2
  3 +import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
  4 +import cn.iocoder.dashboard.common.pojo.PageResult;
  5 +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
  6 +import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
  7 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
3 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO; 8 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
4 -import com.baomidou.mybatisplus.core.mapper.BaseMapper;  
5 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
6 10
  11 +import java.util.Collection;
  12 +
7 @Mapper 13 @Mapper
8 -public interface SysOperateLogMapper extends BaseMapper<SysOperateLogDO> { 14 +public interface SysOperateLogMapper extends BaseMapperX<SysOperateLogDO> {
  15 +
  16 + default PageResult<SysOperateLogDO> selectPage(SysOperateLogPageReqVO reqVO, Collection<Long> userIds) {
  17 + QueryWrapperX<SysOperateLogDO> query = new QueryWrapperX<SysOperateLogDO>()
  18 + .likeIfPresent("module", reqVO.getModule())
  19 + .inIfPresent("user_id", userIds)
  20 + .eqIfPresent("operate_type", reqVO.getType())
  21 + .betweenIfPresent("start_time", reqVO.getBeginTime(), reqVO.getEndTime());
  22 + if (Boolean.TRUE.equals(reqVO.getSuccess())) {
  23 + query.eq("result_code", GlobalErrorCodeConstants.SUCCESS.getCode());
  24 + } else if (Boolean.FALSE.equals(reqVO.getSuccess())) {
  25 + query.gt("result_code", GlobalErrorCodeConstants.SUCCESS.getCode());
  26 + }
  27 + return selectPage(reqVO, query);
  28 + }
  29 +
9 } 30 }
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java
@@ -45,5 +45,9 @@ public interface SysUserMapper extends BaseMapper&lt;SysUserDO&gt; { @@ -45,5 +45,9 @@ public interface SysUserMapper extends BaseMapper&lt;SysUserDO&gt; {
45 .inIfPresent("dept_id", deptIds)); 45 .inIfPresent("dept_id", deptIds));
46 } 46 }
47 47
  48 + default List<SysUserDO> selectListByNickname(String nickname) {
  49 + return selectList(new QueryWrapperX<SysUserDO>().like("nickname", nickname));
  50 + }
  51 +
48 } 52 }
49 53
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java
@@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger; @@ -3,7 +3,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger;
3 import cn.iocoder.dashboard.common.pojo.CommonResult; 3 import cn.iocoder.dashboard.common.pojo.CommonResult;
4 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
5 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; 5 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
6 -import cn.iocoder.dashboard.modules.system.enums.logger.SysOperateLogTypeEnum; 6 +import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateLogTypeEnum;
7 import com.baomidou.mybatisplus.annotation.TableField; 7 import com.baomidou.mybatisplus.annotation.TableField;
8 import com.baomidou.mybatisplus.annotation.TableId; 8 import com.baomidou.mybatisplus.annotation.TableId;
9 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
@@ -62,22 +62,18 @@ public class SysOperateLogDO extends BaseDO { @@ -62,22 +62,18 @@ public class SysOperateLogDO extends BaseDO {
62 /** 62 /**
63 * 操作分类 63 * 操作分类
64 * 64 *
65 - * 枚举 {@link SysOperateLogTypeEnum} 65 + * 枚举 {@link OperateLogTypeEnum}
66 */ 66 */
67 @TableField("operate_type") 67 @TableField("operate_type")
68 private Integer type; 68 private Integer type;
69 /** 69 /**
70 * 操作内容,记录整个操作的明细 70 * 操作内容,记录整个操作的明细
71 * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 71 * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
72 - *  
73 - * TODO 预留字段  
74 */ 72 */
75 private String content; 73 private String content;
76 /** 74 /**
77 * 拓展字段,有些复杂的业务,需要记录一些字段 75 * 拓展字段,有些复杂的业务,需要记录一些字段
78 * 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号 76 * 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号
79 - *  
80 - * TODO 预留字段  
81 */ 77 */
82 @TableField(typeHandler = FastjsonTypeHandler.class) 78 @TableField(typeHandler = FastjsonTypeHandler.class)
83 private Map<String, Object> exts; 79 private Map<String, Object> exts;
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java
1 package cn.iocoder.dashboard.modules.system.service.logger; 1 package cn.iocoder.dashboard.modules.system.service.logger;
2 2
  3 +import cn.iocoder.dashboard.common.pojo.PageResult;
3 import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService; 4 import cn.iocoder.dashboard.framework.logger.operatelog.core.service.OperateLogFrameworkService;
  5 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
  6 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
4 7
5 /** 8 /**
6 * 操作日志 Service 接口 9 * 操作日志 Service 接口
7 */ 10 */
8 public interface SysOperateLogService extends OperateLogFrameworkService { 11 public interface SysOperateLogService extends OperateLogFrameworkService {
  12 +
  13 + /**
  14 + * 获得操作日志分页列表
  15 + *
  16 + * @param reqVO 分页条件
  17 + * @return 操作日志分页列表
  18 + */
  19 + PageResult<SysOperateLogDO> pageOperateLog(SysOperateLogPageReqVO reqVO);
  20 +
9 } 21 }
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java
1 package cn.iocoder.dashboard.modules.system.service.logger.impl; 1 package cn.iocoder.dashboard.modules.system.service.logger.impl;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.dashboard.common.pojo.PageResult;
3 import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO; 6 import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogCreateReqVO;
  7 +import cn.iocoder.dashboard.modules.system.controller.logger.vo.SysOperateLogPageReqVO;
4 import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert; 8 import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert;
5 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysOperateLogMapper; 9 import cn.iocoder.dashboard.modules.system.dal.mysql.dao.logger.SysOperateLogMapper;
6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO; 10 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO;
  11 +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
7 import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService; 12 import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService;
  13 +import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
8 import cn.iocoder.dashboard.util.string.StrUtils; 14 import cn.iocoder.dashboard.util.string.StrUtils;
9 import lombok.extern.slf4j.Slf4j; 15 import lombok.extern.slf4j.Slf4j;
10 import org.springframework.scheduling.annotation.Async; 16 import org.springframework.scheduling.annotation.Async;
11 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
12 18
13 import javax.annotation.Resource; 19 import javax.annotation.Resource;
  20 +import java.util.Collection;
14 21
15 -import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.*; 22 +import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH;
  23 +import static cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.logger.SysOperateLogDO.RESULT_MAX_LENGTH;
  24 +import static cn.iocoder.dashboard.util.collection.CollectionUtils.convertSet;
16 25
17 @Service 26 @Service
18 @Slf4j 27 @Slf4j
@@ -21,6 +30,9 @@ public class SysOperateLogServiceImpl implements SysOperateLogService { @@ -21,6 +30,9 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
21 @Resource 30 @Resource
22 private SysOperateLogMapper operateLogMapper; 31 private SysOperateLogMapper operateLogMapper;
23 32
  33 + @Resource
  34 + private SysUserService userService;
  35 +
24 @Override 36 @Override
25 @Async 37 @Async
26 public void createOperateLogAsync(SysOperateLogCreateReqVO reqVO) { 38 public void createOperateLogAsync(SysOperateLogCreateReqVO reqVO) {
@@ -35,4 +47,18 @@ public class SysOperateLogServiceImpl implements SysOperateLogService { @@ -35,4 +47,18 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
35 } 47 }
36 } 48 }
37 49
  50 + @Override
  51 + public PageResult<SysOperateLogDO> pageOperateLog(SysOperateLogPageReqVO reqVO) {
  52 + // 处理基于用户昵称的查询
  53 + Collection<Long> userIds = null;
  54 + if (StrUtil.isNotEmpty(reqVO.getUserNickname())) {
  55 + userIds = convertSet(userService.listUsersByNickname(reqVO.getUserNickname()), SysUserDO::getId);
  56 + if (CollUtil.isEmpty(userIds)) {
  57 + return PageResult.empty();
  58 + }
  59 + }
  60 + // 查询分页
  61 + return operateLogMapper.selectPage(reqVO, userIds);
  62 + }
  63 +
38 } 64 }
src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java
1 package cn.iocoder.dashboard.modules.system.service.user; 1 package cn.iocoder.dashboard.modules.system.service.user;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.dashboard.common.pojo.PageResult; 4 import cn.iocoder.dashboard.common.pojo.PageResult;
4 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; 5 import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*;
5 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; 6 import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
  7 +import cn.iocoder.dashboard.util.collection.CollectionUtils;
6 8
  9 +import java.util.Collection;
  10 +import java.util.HashMap;
7 import java.util.List; 11 import java.util.List;
  12 +import java.util.Map;
8 13
9 /** 14 /**
10 * 用户 Service 接口 15 * 用户 Service 接口
@@ -46,6 +51,35 @@ public interface SysUserService { @@ -46,6 +51,35 @@ public interface SysUserService {
46 List<SysUserDO> listUsers(SysUserExportReqVO reqVO); 51 List<SysUserDO> listUsers(SysUserExportReqVO reqVO);
47 52
48 /** 53 /**
  54 + * 获得用户列表
  55 + *
  56 + * @param ids 用户编号数组
  57 + * @return 用户列表
  58 + */
  59 + List<SysUserDO> listUsers(Collection<Long> ids);
  60 +
  61 + /**
  62 + * 获得用户 Map
  63 + *
  64 + * @param ids 用户编号数组
  65 + * @return 用户 Map
  66 + */
  67 + default Map<Long, SysUserDO> getUserMap(Collection<Long> ids) {
  68 + if (CollUtil.isEmpty(ids)) {
  69 + return new HashMap<>();
  70 + }
  71 + return CollectionUtils.convertMap(listUsers(ids), SysUserDO::getId);
  72 + }
  73 +
  74 + /**
  75 + * 获得用户列表,基于昵称模糊匹配
  76 + *
  77 + * @param nickname 昵称
  78 + * @return 用户列表
  79 + */
  80 + List<SysUserDO> listUsersByNickname(String nickname);
  81 +
  82 + /**
49 * 创建用户 83 * 创建用户
50 * 84 *
51 * @param reqVO 用户信息 85 * @param reqVO 用户信息
src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java
@@ -83,6 +83,16 @@ public class SysUserServiceImpl implements SysUserService { @@ -83,6 +83,16 @@ public class SysUserServiceImpl implements SysUserService {
83 return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId())); 83 return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId()));
84 } 84 }
85 85
  86 + @Override
  87 + public List<SysUserDO> listUsers(Collection<Long> ids) {
  88 + return userMapper.selectBatchIds(ids);
  89 + }
  90 +
  91 + @Override
  92 + public List<SysUserDO> listUsersByNickname(String nickname) {
  93 + return userMapper.selectListByNickname(nickname);
  94 + }
  95 +
86 /** 96 /**
87 * 获得部门条件:查询指定部门的子部门编号们,包括自身 97 * 获得部门条件:查询指定部门的子部门编号们,包括自身
88 * 98 *