Commit daf4651a4f08dce7af17c424ab2a6da3af02cae5

Authored by puhui999
1 parent 289f0409

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

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;
11 11 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
12 12 import cn.iocoder.yudao.module.system.api.dept.DeptApi;
13 13 import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  14 +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
  15 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
14 16 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
15 17 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
16 18 import io.swagger.v3.oas.annotations.Operation;
... ... @@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
36 38 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
37 39 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
38 40 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  41 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER;
39 42  
40 43 @Tag(name = "管理后台 - CRM 客户")
41 44 @RestController
... ... @@ -50,6 +53,8 @@ public class CrmCustomerController {
50 53 private DeptApi deptApi;
51 54 @Resource
52 55 private AdminUserApi adminUserApi;
  56 + @Resource
  57 + private OperateLogApi operateLogApi;
53 58  
54 59 @PostMapping("/create")
55 60 @Operation(summary = "创建客户")
... ... @@ -130,6 +135,21 @@ public class CrmCustomerController {
130 135 return success(true);
131 136 }
132 137  
  138 + @GetMapping("/operate-log")
  139 + @Operation(summary = "获得客户操作日志")
  140 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  141 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  142 + public CommonResult<List<OperateLogV2RespDTO>> getOperateLog(@RequestParam("id") Long id) {
  143 + // 1. 获取客户
  144 + CrmCustomerDO customer = customerService.getCustomer(id);
  145 + if (customer == null) {
  146 + return success(null);
  147 + }
  148 +
  149 + // 2. 获取操作日志
  150 + return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id));
  151 + }
  152 +
133 153 // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了;
134 154 @PutMapping("/lock")
135 155 @Operation(summary = "锁定/解锁客户")
... ...
yudao-module-system/yudao-module-system-api/pom.xml
... ... @@ -29,6 +29,16 @@
29 29 <artifactId>bizlog-sdk</artifactId>
30 30 </dependency>
31 31  
  32 + <!--工具类相关-->
  33 + <dependency>
  34 + <groupId>com.fasterxml.jackson.core</groupId>
  35 + <artifactId>jackson-databind</artifactId>
  36 + </dependency>
  37 + <dependency>
  38 + <groupId>com.fasterxml.jackson.core</groupId>
  39 + <artifactId>jackson-core</artifactId>
  40 + </dependency>
  41 +
32 42 <!-- 参数校验 -->
33 43 <dependency>
34 44 <groupId>org.springframework.boot</groupId>
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java
1 1 package cn.iocoder.yudao.module.system.api.logger;
2 2  
3 3 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
4   -
  4 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
5 5 import jakarta.validation.Valid;
6 6  
  7 +import java.util.List;
  8 +
7 9 /**
8 10 * 操作日志 API 接口
9 11 *
... ... @@ -18,4 +20,13 @@ public interface OperateLogApi {
18 20 */
19 21 void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO);
20 22  
  23 + /**
  24 + * 获取指定模块的指定数据的操作日志
  25 + *
  26 + * @param module 操作模块
  27 + * @param bizId 操作模块编号
  28 + * @return 操作日志
  29 + */
  30 + List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId);
  31 +
21 32 }
... ...
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.api.logger.dto;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import lombok.Data;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
  11 +
  12 +/**
  13 + * 系统操作日志 Resp DTO
  14 + *
  15 + * @author HUIHUI
  16 + */
  17 +@Data
  18 +public class OperateLogV2RespDTO {
  19 +
  20 + /**
  21 + * 链路追踪编号
  22 + *
  23 + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
  24 + */
  25 + private String traceId;
  26 + /**
  27 + * 用户编号
  28 + *
  29 + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性
  30 + */
  31 + private Long userId;
  32 + /**
  33 + * 用户类型
  34 + *
  35 + * 关联 {@link UserTypeEnum}
  36 + */
  37 + private Integer userType;
  38 + /**
  39 + * 操作模块
  40 + */
  41 + private String module;
  42 + /**
  43 + * 操作名
  44 + */
  45 + private String name;
  46 + /**
  47 + * 操作模块业务编号
  48 + */
  49 + private Long bizId;
  50 + /**
  51 + * 操作内容,记录整个操作的明细
  52 + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
  53 + */
  54 + private String content;
  55 + /**
  56 + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
  57 + * 例如说,记录订单编号,{ orderId: "1"}
  58 + */
  59 + private String extra;
  60 +
  61 + /**
  62 + * 请求方法名
  63 + */
  64 + private String requestMethod;
  65 + /**
  66 + * 请求地址
  67 + */
  68 + private String requestUrl;
  69 + /**
  70 + * 用户 IP
  71 + */
  72 + private String userIp;
  73 + /**
  74 + * 浏览器 UA
  75 + */
  76 + private String userAgent;
  77 +
  78 + /**
  79 + * 创建时间
  80 + */
  81 + // TODO puhui999: 木得效果怎么肥事
  82 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
  83 + private LocalDateTime createTime;
  84 + /**
  85 + * 创建者,关联 AdminUserDO#getId
  86 + */
  87 + private String creator;
  88 + /**
  89 + * 创建者名称
  90 + */
  91 + private String creatorName;
  92 +
  93 +}
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
1 1 package cn.iocoder.yudao.module.system.api.logger;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
3 5 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
  6 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
  7 +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
  8 +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
4 9 import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
  10 +import cn.iocoder.yudao.module.system.service.user.AdminUserService;
  11 +import jakarta.annotation.Resource;
5 12 import org.springframework.stereotype.Service;
6 13 import org.springframework.validation.annotation.Validated;
7 14  
8   -import jakarta.annotation.Resource;
  15 +import java.util.Collections;
  16 +import java.util.List;
  17 +import java.util.Map;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  20 +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
9 21  
10 22 /**
11 23 * 操作日志 API 实现类
... ... @@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi {
18 30  
19 31 @Resource
20 32 private OperateLogService operateLogService;
  33 + @Resource
  34 + private AdminUserService adminUserService;
21 35  
22 36 @Override
23 37 public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
24 38 operateLogService.createOperateLog(createReqDTO);
25 39 }
26 40  
  41 + @Override
  42 + public List<OperateLogV2RespDTO> getOperateLogByModuleAndBizId(String module, Long bizId) {
  43 + List<OperateLogV2DO> logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId);
  44 + if (CollUtil.isEmpty(logList)) {
  45 + return Collections.emptyList();
  46 + }
  47 +
  48 + // 获取用户
  49 + List<AdminUserDO> userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator())));
  50 + Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId);
  51 + return convertList(logList, item -> {
  52 + OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class);
  53 + findAndThen(userMap, Long.parseLong(item.getCreator()), user -> {
  54 + bean.setCreatorName(user.getNickname());
  55 + });
  56 + return bean;
  57 + });
  58 + }
  59 +
27 60 }
... ...
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 {
59 59 * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
60 60 */
61 61 private String content;
62   -
  62 + /**
  63 + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
  64 + * 例如说,记录订单编号,{ orderId: "1"}
  65 + */
  66 + private String extra;
63 67 /**
64 68 * 请求方法名
65 69 */
... ...
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;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
10 10 import java.util.Collection;
  11 +import java.util.List;
11 12  
12 13 @Mapper
13 14 public interface OperateLogV2Mapper extends BaseMapperX<OperateLogV2DO> {
... ... @@ -20,4 +21,11 @@ public interface OperateLogV2Mapper extends BaseMapperX&lt;OperateLogV2DO&gt; {
20 21 return selectPage(reqVO, query);
21 22 }
22 23  
  24 + default List<OperateLogV2DO> selectListByModuleAndBizId(String module, Long bizId) {
  25 + return selectList(new LambdaQueryWrapperX<OperateLogV2DO>()
  26 + .eq(OperateLogV2DO::getModule, module)
  27 + .eq(OperateLogV2DO::getBizId, bizId)
  28 + .orderByDesc(OperateLogV2DO::getCreateTime));
  29 + }
  30 +
23 31 }
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
4 4 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
5 5 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
6   -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
  6 +import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
7 7 import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO;
8 8 import com.mzt.logapi.beans.LogRecord;
9 9 import com.mzt.logapi.service.ILogRecordService;
... ... @@ -18,7 +18,7 @@ import java.util.List;
18 18 /**
19 19 * 操作日志 ILogRecordService 实现类
20 20 *
21   - * 基于 {@link OperateLogApi} 实现,记录操作日志
  21 + * 基于 {@link OperateLogService} 实现,记录操作日志
22 22 *
23 23 * @author HUIHUI
24 24 */
... ... @@ -27,7 +27,7 @@ import java.util.List;
27 27 public class ILogRecordServiceImpl implements ILogRecordService {
28 28  
29 29 @Resource
30   - private OperateLogApi operateLogApi;
  30 + private OperateLogService operateLogService;
31 31  
32 32 @Override
33 33 public void record(LogRecord logRecord) {
... ... @@ -41,6 +41,7 @@ public class ILogRecordServiceImpl implements ILogRecordService {
41 41 // 补全请求信息
42 42 fillRequestFields(reqBO);
43 43 // 异步记录日志
  44 + operateLogService.createOperateLogV2(reqBO);
44 45 log.info("操作日志 ===> {}", reqBO);
45 46 }
46 47  
... ... @@ -54,6 +55,7 @@ public class ILogRecordServiceImpl implements ILogRecordService {
54 55 reqBO.setName(logRecord.getSubType());// 操作名称如 转移客户
55 56 reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号
56 57 reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。
  58 + reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"}
57 59 }
58 60  
59 61 private static void fillRequestFields(OperateLogV2CreateReqBO reqBO) {
... ...
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;
4 4 import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO;
5 5 import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
6 6 import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
  7 +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO;
  8 +import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO;
  9 +
  10 +import java.util.List;
7 11  
8 12 /**
9 13 * 操作日志 Service 接口
... ... @@ -20,18 +24,29 @@ public interface OperateLogService {
20 24 void createOperateLog(OperateLogCreateReqDTO createReqDTO);
21 25  
22 26 /**
  27 + * 获得操作日志分页列表
  28 + *
  29 + * @param pageReqVO 分页条件
  30 + * @return 操作日志分页列表
  31 + */
  32 + PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO);
  33 +
  34 + //======================= LOG V2 =======================
  35 +
  36 + /**
23 37 * 记录操作日志 V2
24 38 *
25   - * @param createReqDTO 操作日志请求
  39 + * @param createReqBO 创建请求
26 40 */
27   - void createOperateLogV2(OperateLogCreateReqDTO createReqDTO);
  41 + void createOperateLogV2(OperateLogV2CreateReqBO createReqBO);
28 42  
29 43 /**
30   - * 获得操作日志分页列表
  44 + * 获取指定模块的指定数据的操作日志
31 45 *
32   - * @param pageReqVO 分页条件
33   - * @return 操作日志分页列表
  46 + * @param module 操作模块
  47 + * @param bizId 操作模块编号
  48 + * @return 操作日志
34 49 */
35   - PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO);
  50 + List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId);
36 51  
37 52 }
... ...
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;
12 12 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
13 13 import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper;
14 14 import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper;
  15 +import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO;
15 16 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
16 17 import jakarta.annotation.Resource;
17 18 import lombok.extern.slf4j.Slf4j;
... ... @@ -19,6 +20,7 @@ import org.springframework.stereotype.Service;
19 20 import org.springframework.validation.annotation.Validated;
20 21  
21 22 import java.util.Collection;
  23 +import java.util.List;
22 24  
23 25 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
24 26 import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH;
... ... @@ -51,12 +53,6 @@ public class OperateLogServiceImpl implements OperateLogService {
51 53 }
52 54  
53 55 @Override
54   - public void createOperateLogV2(OperateLogCreateReqDTO createReqDTO) {
55   - OperateLogV2DO log = BeanUtils.toBean(createReqDTO, OperateLogV2DO.class);
56   - operateLogV2Mapper.insert(log);
57   - }
58   -
59   - @Override
60 56 public PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO) {
61 57 // 处理基于用户昵称的查询
62 58 Collection<Long> userIds = null;
... ... @@ -70,4 +66,17 @@ public class OperateLogServiceImpl implements OperateLogService {
70 66 return operateLogMapper.selectPage(pageReqVO, userIds);
71 67 }
72 68  
  69 + //======================= LOG V2 =======================
  70 +
  71 + @Override
  72 + public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) {
  73 + OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class);
  74 + operateLogV2Mapper.insert(log);
  75 + }
  76 +
  77 + @Override
  78 + public List<OperateLogV2DO> getOperateLogByModuleAndBizId(String module, Long bizId) {
  79 + return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId);
  80 + }
  81 +
73 82 }
... ...
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 {
53 53 */
54 54 @NotEmpty(message = "操作内容不能为空")
55 55 private String content;
  56 + /**
  57 + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 )
  58 + * 例如说,记录订单编号,{ orderId: "1"}
  59 + */
  60 + private String extra;
56 61  
57 62 /**
58 63 * 请求方法名
... ...