From 1768d27e1154c1d5486f0c6e4cd3107ddbeda4ac Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 17 Jan 2021 20:55:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=B0=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=9A=84=E9=A1=B5=E9=9D=A2=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../monitor/SysOperlogController.java | 18 +- ruoyi-common/pom.xml | 35 -- .../java/com/ruoyi/common/annotation/Log.java | 41 -- .../ruoyi/framework/aspectj/LogAspect.java | 160 ----- .../framework/config/ApplicationConfig.java | 29 - ruoyi-ui/src/api/monitor/operlog.js | 35 -- ruoyi-ui/src/api/system/operatelog.js | 19 + ruoyi-ui/src/main.js | 4 + ruoyi-ui/src/utils/dict.js | 1 + .../operlog => system/operatelog}/index.vue | 593 ++++++++---------- sql/ruoyi-vue-pro-data.sql | 29 + .../dashboard/common/pojo/PageResult.java | 4 + .../async/config/AsyncConfiguration.java | 2 +- .../core/annotations/OperateLog.java | 4 +- .../operatelog/core/aop/OperateLogAspect.java | 16 +- .../core/enums/OperateLogTypeEnum.java} | 4 +- .../mybatis/core/mapper/BaseMapperX.java | 24 + .../controller/auth/SysAuthController.java | 1 - .../common/SysCaptchaController.http | 2 +- .../common/SysCaptchaController.java | 2 +- .../logger/SysOperateLogController.http | 3 + .../logger/SysOperateLogController.java | 86 +++ .../controller/logger/package-info.java | 1 - .../logger/vo/SysOperateLogBaseVO.java | 9 +- .../logger/vo/SysOperateLogPageReqVO.java | 39 ++ .../logger/vo/SysOperateLogRespVO.java | 21 + .../convert/logger/SysOperateLogConvert.java | 6 + .../mysql/dao/logger/SysOperateLogMapper.java | 25 +- .../dal/mysql/dao/user/SysUserMapper.java | 4 + .../dataobject/logger/SysOperateLogDO.java | 8 +- .../service/logger/SysOperateLogService.java | 12 + .../logger/impl/SysOperateLogServiceImpl.java | 28 +- .../system/service/user/SysUserService.java | 34 + .../service/user/SysUserServiceImpl.java | 10 + 35 files changed, 648 insertions(+), 663 deletions(-) delete mode 100644 ruoyi-common/pom.xml delete mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java delete mode 100644 ruoyi-ui/src/api/monitor/operlog.js create mode 100644 ruoyi-ui/src/api/system/operatelog.js rename ruoyi-ui/src/views/{monitor/operlog => system/operatelog}/index.vue (63%) create mode 100644 sql/ruoyi-vue-pro-data.sql rename src/main/java/cn/iocoder/dashboard/{modules/system/enums/logger/SysOperateLogTypeEnum.java => framework/logger/operatelog/core/enums/OperateLogTypeEnum.java} (89%) create mode 100644 src/main/java/cn/iocoder/dashboard/framework/mybatis/core/mapper/BaseMapperX.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.http create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/package-info.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogPageReqVO.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogRespVO.java diff --git a/pom.xml b/pom.xml index 20ede4f7e..cc04724b0 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ ${java.version} 3.8.0 - 2.4.1 + 2.4.2 diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java index 276442289..99f9f7648 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java @@ -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 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 list = operLogService.selectOperLogList(operLog); - ExcelUtil util = new ExcelUtil(SysOperLog.class); - return util.exportExcel(list, "操作日志"); - } } diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml deleted file mode 100644 index ab7f11b1b..000000000 --- a/ruoyi-common/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - ruoyi - com.ruoyi - 3.3.0 - - 4.0.0 - - ruoyi-common - - - common通用工具 - - - - - - - org.yaml - snakeyaml - - - - - eu.bitwalker - UserAgentUtils - - - - - - diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java deleted file mode 100644 index 3458c882d..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java +++ /dev/null @@ -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; -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java deleted file mode 100644 index 2c58eb9be..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java +++ /dev/null @@ -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; - } -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java deleted file mode 100644 index eab1ee0e6..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java +++ /dev/null @@ -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()); - } -} diff --git a/ruoyi-ui/src/api/monitor/operlog.js b/ruoyi-ui/src/api/monitor/operlog.js deleted file mode 100644 index c519355ef..000000000 --- a/ruoyi-ui/src/api/monitor/operlog.js +++ /dev/null @@ -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 - }) -} \ No newline at end of file diff --git a/ruoyi-ui/src/api/system/operatelog.js b/ruoyi-ui/src/api/system/operatelog.js new file mode 100644 index 000000000..c089975d4 --- /dev/null +++ b/ruoyi-ui/src/api/system/operatelog.js @@ -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 + }) +} diff --git a/ruoyi-ui/src/main.js b/ruoyi-ui/src/main.js index c7fafc017..f337ab78a 100644 --- a/ruoyi-ui/src/main.js +++ b/ruoyi-ui/src/main.js @@ -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 diff --git a/ruoyi-ui/src/utils/dict.js b/ruoyi-ui/src/utils/dict.js index 07df5fd8c..00f74aefe 100644 --- a/ruoyi-ui/src/utils/dict.js +++ b/ruoyi-ui/src/utils/dict.js @@ -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' } /** diff --git a/ruoyi-ui/src/views/monitor/operlog/index.vue b/ruoyi-ui/src/views/system/operatelog/index.vue similarity index 63% rename from ruoyi-ui/src/views/monitor/operlog/index.vue rename to ruoyi-ui/src/views/system/operatelog/index.vue index 3a44cfcd3..f038dc51f 100644 --- a/ruoyi-ui/src/views/monitor/operlog/index.vue +++ b/ruoyi-ui/src/views/system/operatelog/index.vue @@ -1,318 +1,275 @@ - - - - + + + + diff --git a/sql/ruoyi-vue-pro-data.sql b/sql/ruoyi-vue-pro-data.sql new file mode 100644 index 000000000..a1ee1b82a --- /dev/null +++ b/sql/ruoyi-vue-pro-data.sql @@ -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'); diff --git a/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java b/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java index fa7d109d9..092677d0c 100644 --- a/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java +++ b/src/main/java/cn/iocoder/dashboard/common/pojo/PageResult.java @@ -31,4 +31,8 @@ public final class PageResult implements Serializable { this.total = total; } + public static PageResult empty() { + return new PageResult<>(0L); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java index b2c126c28..58096d5da 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java +++ b/src/main/java/cn/iocoder/dashboard/framework/async/config/AsyncConfiguration.java @@ -4,6 +4,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; @Configuration -@EnableAsync(proxyTargetClass = true) +@EnableAsync public class AsyncConfiguration { } diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java index ce61c77a0..494f04158 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/annotations/OperateLog.java @@ -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 {}; // ========== 开关字段 ========== diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java index beb654210..a5afe95e1 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/aop/OperateLogAspect.java @@ -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; } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysOperateLogTypeEnum.java b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateLogTypeEnum.java similarity index 89% rename from src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysOperateLogTypeEnum.java rename to src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateLogTypeEnum.java index ab1f8546d..5e3552455 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysOperateLogTypeEnum.java +++ b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/enums/OperateLogTypeEnum.java @@ -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 { /** * 查询 diff --git a/src/main/java/cn/iocoder/dashboard/framework/mybatis/core/mapper/BaseMapperX.java b/src/main/java/cn/iocoder/dashboard/framework/mybatis/core/mapper/BaseMapperX.java new file mode 100644 index 000000000..e2f2559d8 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/mybatis/core/mapper/BaseMapperX.java @@ -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 extends BaseMapper { + + default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) { + // MyBatis Plus 查询 + IPage mpPage = MyBatisUtils.buildPage(pageParam); + selectPage(mpPage, queryWrapper); + // 转换返回 + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java index 3db8ed8ef..3669652e8 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/auth/SysAuthController.java @@ -54,7 +54,6 @@ public class SysAuthController { @ApiOperation("获取登陆用户的权限信息") @GetMapping("/get-permission-info") - @OperateLog public CommonResult getPermissionInfo() { // 获得用户信息 SysUserDO user = userService.getUser(getLoginUserId()); diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http b/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http index 90859ca70..0b1cf854b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.http @@ -1,2 +1,2 @@ ### 请求 /captcha/get-image 接口 => 成功 -GET {{baseUrl}}/captcha/get-image +GET {{baseUrl}}/system/captcha/get-image diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java index 3faa96db3..f29e835ad 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/common/SysCaptchaController.java @@ -23,7 +23,7 @@ public class SysCaptchaController { @ApiOperation("生成图片验证码") @GetMapping("/get-image") - private CommonResult getCaptchaImage() { + public CommonResult getCaptchaImage() { return success(captchaService.getCaptchaImage()); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.http b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.http new file mode 100644 index 000000000..3b8871996 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.http @@ -0,0 +1,3 @@ +### 请求 /system/operate-log/demo 接口 => 成功 +GET {{baseUrl}}/system/operate-log/demo +Authorization: Bearer {{token}} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java new file mode 100644 index 000000000..2b569e193 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/SysOperateLogController.java @@ -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 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> pageOperateLog(@Validated SysOperateLogPageReqVO reqVO) { + PageResult pageResult = operateLogService.pageOperateLog(reqVO); + + // 获得拼接需要的数据 + Collection userIds = CollectionUtils.convertList(pageResult.getList(), SysOperateLogDO::getUserId); + Map userMap = userService.getUserMap(userIds); + // 拼接数据 + List 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 list = operLogService.selectOperLogList(operLog); +// ExcelUtil util = new ExcelUtil(SysOperLog.class); +// return util.exportExcel(list, "操作日志"); +// } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/package-info.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/package-info.java deleted file mode 100644 index d682a7365..000000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.dashboard.modules.system.controller.logger; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java index 31d734461..35bc57f28 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogBaseVO.java @@ -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 exts; + @ApiModelProperty(value = "请求方法名", required = true, example = "GET") @NotEmpty(message = "请求方法名不能为空") private String requestMethod; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogPageReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogPageReqVO.java new file mode 100644 index 000000000..7602063f9 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogPageReqVO.java @@ -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; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogRespVO.java new file mode 100644 index 000000000..34b78b6cc --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/logger/vo/SysOperateLogRespVO.java @@ -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; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java index 734c82c31..2f46788e4 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/logger/SysOperateLogConvert.java @@ -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 convertPage(PageResult page); + + SysOperateLogRespVO convert(SysOperateLogDO bean); + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysOperateLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysOperateLogMapper.java index b15bd6d0c..99667ec78 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysOperateLogMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/logger/SysOperateLogMapper.java @@ -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 { +public interface SysOperateLogMapper extends BaseMapperX { + + default PageResult selectPage(SysOperateLogPageReqVO reqVO, Collection userIds) { + QueryWrapperX query = new QueryWrapperX() + .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); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java index 225195f12..5103fc00e 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java @@ -45,5 +45,9 @@ public interface SysUserMapper extends BaseMapper { .inIfPresent("dept_id", deptIds)); } + default List selectListByNickname(String nickname) { + return selectList(new QueryWrapperX().like("nickname", nickname)); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java index be835d006..709b486ab 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/logger/SysOperateLogDO.java +++ b/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; 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 exts; diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java index 8cf65d209..89d87720a 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogService.java @@ -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 pageOperateLog(SysOperateLogPageReqVO reqVO); + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java index 4c7905da2..0e8953c70 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java @@ -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 pageOperateLog(SysOperateLogPageReqVO reqVO) { + // 处理基于用户昵称的查询 + Collection 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); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java index 771ffeb9f..288c14dee 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java @@ -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 listUsers(SysUserExportReqVO reqVO); + /** + * 获得用户列表 + * + * @param ids 用户编号数组 + * @return 用户列表 + */ + List listUsers(Collection ids); + + /** + * 获得用户 Map + * + * @param ids 用户编号数组 + * @return 用户 Map + */ + default Map getUserMap(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return new HashMap<>(); + } + return CollectionUtils.convertMap(listUsers(ids), SysUserDO::getId); + } + + /** + * 获得用户列表,基于昵称模糊匹配 + * + * @param nickname 昵称 + * @return 用户列表 + */ + List listUsersByNickname(String nickname); + /** * 创建用户 * diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java index 11b541177..b71e634cf 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java @@ -83,6 +83,16 @@ public class SysUserServiceImpl implements SysUserService { return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId())); } + @Override + public List listUsers(Collection ids) { + return userMapper.selectBatchIds(ids); + } + + @Override + public List listUsersByNickname(String nickname) { + return userMapper.selectListByNickname(nickname); + } + /** * 获得部门条件:查询指定部门的子部门编号们,包括自身 *