Browse Source

系统操作日志:集成 mzt-biz-log 5,增加日志保存和查询接口

puhui999 1 year ago
parent
commit
daf4651a4f
11 changed files with 228 additions and 18 deletions
  1. 20 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
  2. 10 0
      yudao-module-system/yudao-module-system-api/pom.xml
  3. 12 1
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java
  4. 93 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java
  5. 34 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
  6. 5 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java
  7. 8 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java
  8. 5 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java
  9. 21 6
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java
  10. 15 6
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java
  11. 5 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java

+ 20 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java

@@ -11,6 +11,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
+import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.Operation;
@@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER;
 
 @Tag(name = "管理后台 - CRM 客户")
 @RestController
@@ -50,6 +53,8 @@ public class CrmCustomerController {
     private DeptApi deptApi;
     @Resource
     private AdminUserApi adminUserApi;
+    @Resource
+    private OperateLogApi operateLogApi;
 
     @PostMapping("/create")
     @Operation(summary = "创建客户")
@@ -130,6 +135,21 @@ public class CrmCustomerController {
         return success(true);
     }
 
+    @GetMapping("/operate-log")
+    @Operation(summary = "获得客户操作日志")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('crm:customer:query')")
+    public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) {
+        // 1. 获取客户
+        CrmCustomerDO customer = customerService.getCustomer(id);
+        if (customer == null) {
+            return success(null);
+        }
+
+        // 2. 获取操作日志
+        return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id));
+    }
+
     // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了;
     @PutMapping("/lock")
     @Operation(summary = "锁定/解锁客户")

+ 10 - 0
yudao-module-system/yudao-module-system-api/pom.xml

@@ -29,6 +29,16 @@
             <artifactId>bizlog-sdk</artifactId>
         </dependency>
 
+        <!--工具类相关-->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+
         <!-- 参数校验 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>

+ 12 - 1
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java

@@ -1,9 +1,11 @@
 package cn.iocoder.yudao.module.system.api.logger;
 
 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
-
+import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
 import jakarta.validation.Valid;
 
+import java.util.List;
+
 /**
  * 操作日志 API 接口
  *
@@ -18,4 +20,13 @@ public interface OperateLogApi {
      */
     void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
 
+    /**
+     * 获取指定模块的指定数据的操作日志
+     *
+     * @param module 操作模块
+     * @param bizId  操作模块编号
+     * @return 操作日志
+     */
+    List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId);
+
 }

+ 93 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.system.api.logger.dto;
+
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
+
+/**
+ * 系统操作日志 Resp DTO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class OperateLogV2RespDTO {
+
+    /**
+     * 链路追踪编号
+     *
+     * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
+     */
+    private String traceId;
+    /**
+     * 用户编号
+     *
+     * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
+     */
+    private Long userId;
+    /**
+     * 用户类型
+     *
+     * 关联 {@link  UserTypeEnum}
+     */
+    private Integer userType;
+    /**
+     * 操作模块
+     */
+    private String module;
+    /**
+     * 操作名
+     */
+    private String name;
+    /**
+     * 操作模块业务编号
+     */
+    private Long bizId;
+    /**
+     * 操作内容,记录整个操作的明细
+     * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
+     */
+    private String content;
+    /**
+     * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
+     * 例如说,记录订单编号,{ orderId: "1"}
+     */
+    private String extra;
+
+    /**
+     * 请求方法名
+     */
+    private String requestMethod;
+    /**
+     * 请求地址
+     */
+    private String requestUrl;
+    /**
+     * 用户 IP
+     */
+    private String userIp;
+    /**
+     * 浏览器 UA
+     */
+    private String userAgent;
+
+    /**
+     * 创建时间
+     */
+    // TODO puhui999: 木得效果怎么肥事
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
+    private LocalDateTime createTime;
+    /**
+     * 创建者,关联 AdminUserDO#getId
+     */
+    private String creator;
+    /**
+     * 创建者名称
+     */
+    private String creatorName;
+
+}

+ 34 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java

@@ -1,11 +1,23 @@
 package cn.iocoder.yudao.module.system.api.logger;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
+import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
+import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
+import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
+import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
-import jakarta.annotation.Resource;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
 
 /**
  * 操作日志 API 实现类
@@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi {
 
     @Resource
     private OperateLogService operateLogService;
+    @Resource
+    private AdminUserService adminUserService;
 
     @Override
     public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
         operateLogService.createOperateLog(createReqDTO);
     }
 
+    @Override
+    public List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId) {
+        List<OperateLogV2DO> logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId);
+        if (CollUtil.isEmpty(logList)) {
+            return Collections.emptyList();
+        }
+
+        // 获取用户
+        List<AdminUserDO> userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator())));
+        Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId);
+        return convertList(logList, item -> {
+            OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class);
+            findAndThen(userMap, Long.parseLong(item.getCreator()), user -> {
+                bean.setCreatorName(user.getNickname());
+            });
+            return bean;
+        });
+    }
+
 }

+ 5 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java

@@ -59,7 +59,11 @@ public class OperateLogV2DO extends BaseDO {
      * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
      */
     private String content;
-
+    /**
+     * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
+     * 例如说,记录订单编号,{ orderId: "1"}
+     */
+    private String extra;
     /**
      * 请求方法名
      */

+ 8 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java

@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.Collection;
+import java.util.List;
 
 @Mapper
 public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> {
@@ -20,4 +21,11 @@ public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> {
         return selectPage(reqVO, query);
     }
 
+    default List<OperateLogV2DO> selectListByModuleAndBizId(String module, Long bizId) {
+        return selectList(new LambdaQueryWrapperX<OperateLogV2DO>()
+                .eq(OperateLogV2DO::getModule, module)
+                .eq(OperateLogV2DO::getBizId, bizId)
+                .orderByDesc(OperateLogV2DO::getCreateTime));
+    }
+
 }

+ 5 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.framework.bizlog.service;
 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
-import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
+import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
 import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO;
 import com.mzt.logapi.beans.LogRecord;
 import com.mzt.logapi.service.ILogRecordService;
@@ -18,7 +18,7 @@ import java.util.List;
 /**
  * 操作日志 ILogRecordService 实现类
  *
- * 基于 {@link OperateLogApi} 实现,记录操作日志
+ * 基于 {@link OperateLogService} 实现,记录操作日志
  *
  * @author HUIHUI
  */
@@ -27,7 +27,7 @@ import java.util.List;
 public class ILogRecordServiceImpl implements ILogRecordService {
 
     @Resource
-    private OperateLogApi operateLogApi;
+    private OperateLogService operateLogService;
 
     @Override
     public void record(LogRecord logRecord) {
@@ -41,6 +41,7 @@ public class ILogRecordServiceImpl implements ILogRecordService {
         // 补全请求信息
         fillRequestFields(reqBO);
         // 异步记录日志
+        operateLogService.createOperateLogV2(reqBO);
         log.info("操作日志 ===> {}", reqBO);
     }
 
@@ -54,6 +55,7 @@ public class ILogRecordServiceImpl implements ILogRecordService {
         reqBO.setName(logRecord.getSubType());// 操作名称如 转移客户
         reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号
         reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
+        reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"}
     }
 
     private static void fillRequestFields(OperateLogV2CreateReqBO reqBO) {

+ 21 - 6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java

@@ -4,6 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
+import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO;
+
+import java.util.List;
 
 /**
  * 操作日志 Service 接口
@@ -19,19 +23,30 @@ public interface OperateLogService {
      */
     void createOperateLog(OperateLogCreateReqDTO createReqDTO);
 
+    /**
+     * 获得操作日志分页列表
+     *
+     * @param pageReqVO 分页条件
+     * @return 操作日志分页列表
+     */
+    PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO);
+
+    //======================= LOG V2 =======================
+
     /**
      * 记录操作日志 V2
      *
-     * @param createReqDTO 操作日志请求
+     * @param createReqBO 创建请求
      */
-    void createOperateLogV2(OperateLogCreateReqDTO createReqDTO);
+    void createOperateLogV2(OperateLogV2CreateReqBO createReqBO);
 
     /**
-     * 获得操作日志分页列表
+     * 获取指定模块的指定数据的操作日志
      *
-     * @param pageReqVO 分页条件
-     * @return 操作日志分页列表
+     * @param module 操作模块
+     * @param bizId  操作模块编号
+     * @return 操作日志
      */
-    PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO);
+    List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId);
 
 }

+ 15 - 6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java

@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper;
+import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
@@ -19,6 +20,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import java.util.Collection;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH;
@@ -50,12 +52,6 @@ public class OperateLogServiceImpl implements OperateLogService {
         operateLogMapper.insert(log);
     }
 
-    @Override
-    public void createOperateLogV2(OperateLogCreateReqDTO createReqDTO) {
-        OperateLogV2DO log = BeanUtils.toBean(createReqDTO, OperateLogV2DO.class);
-        operateLogV2Mapper.insert(log);
-    }
-
     @Override
     public PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO) {
         // 处理基于用户昵称的查询
@@ -70,4 +66,17 @@ public class OperateLogServiceImpl implements OperateLogService {
         return operateLogMapper.selectPage(pageReqVO, userIds);
     }
 
+    //======================= LOG V2 =======================
+
+    @Override
+    public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) {
+        OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class);
+        operateLogV2Mapper.insert(log);
+    }
+
+    @Override
+    public List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId) {
+        return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId);
+    }
+
 }

+ 5 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java

@@ -53,6 +53,11 @@ public class OperateLogV2CreateReqBO {
      */
     @NotEmpty(message = "操作内容不能为空")
     private String content;
+    /**
+     * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
+     * 例如说,记录订单编号,{ orderId: "1"}
+     */
+    private String extra;
 
     /**
      * 请求方法名