Commit 5de6a8bd2314faaba3b94bb4a96c307c4fedc1f5
1 parent
82a25474
📖 code review:操作日志的实现
Showing
20 changed files
with
40 additions
and
27 deletions
yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml
| ... | ... | @@ -46,9 +46,10 @@ |
| 46 | 46 | <groupId>com.google.guava</groupId> |
| 47 | 47 | <artifactId>guava</artifactId> |
| 48 | 48 | </dependency> |
| 49 | - <!-- Springboot-注解-通用操作日志组件 --> | |
| 50 | - <!-- 此组件解决的问题是: 「谁」在「什么时间」对「什么」做了「什么事」 --> | |
| 49 | + | |
| 51 | 50 | <dependency> |
| 51 | + <!-- Spring Boot 通用操作日志组件,基于注解实现 --> | |
| 52 | + <!-- 此组件解决的问题是:「谁」在「什么时间」对「什么」做了「什么事」 --> | |
| 52 | 53 | <groupId>io.github.mouzt</groupId> |
| 53 | 54 | <artifactId>bizlog-sdk</artifactId> |
| 54 | 55 | </dependency> | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java
| ... | ... | @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 5 | 5 | @AutoConfiguration |
| 6 | 6 | public class YudaoOperateLogAutoConfiguration { |
| 7 | 7 | |
| 8 | + // TODO @puhui999:这个是不是留着哈?因为老版本还是会留着一段时间的 | |
| 8 | 9 | //@Bean |
| 9 | 10 | //public OperateLogAspect operateLogAspect() { |
| 10 | 11 | // return new OperateLogAspect(); | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java
| ... | ... | @@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 9 | 9 | import org.springframework.context.annotation.Bean; |
| 10 | 10 | import org.springframework.context.annotation.Primary; |
| 11 | 11 | |
| 12 | +// TODO @puhui999:思考了下,为了减少 starter 数量,在 security 组件里,增加一个 core/operatelog 包,然后 YudaoOperateLogV2Configuration 搞一个过去; | |
| 12 | 13 | /** |
| 13 | 14 | * mzt-biz-log 配置类 |
| 14 | 15 | * | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java
| ... | ... | @@ -44,6 +44,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC |
| 44 | 44 | import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; |
| 45 | 45 | import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; |
| 46 | 46 | |
| 47 | +// TODO @puhui999:这个类,是不是可以删除哈;简化简化 | |
| 47 | 48 | /** |
| 48 | 49 | * 拦截使用 @Operation 注解, 获取操作类型、开始时间、持续时间、方法相关信息、执行结果等信息 |
| 49 | 50 | * 对 mzt-biz-log 日志信息进行增强 | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java deleted
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java
| ... | ... | @@ -23,16 +23,17 @@ public class ILogRecordServiceImpl implements ILogRecordService { |
| 23 | 23 | public void record(LogRecord logRecord) { |
| 24 | 24 | OperateLogV2Aspect.setContent(logRecord); // 操作日志 |
| 25 | 25 | OperateLogV2Aspect.addExtra(LogRecordContext.getVariables()); // 扩展信息 |
| 26 | + // TODO @puhui999:这里是不是调用 operateLogApi 进行记录哈 | |
| 26 | 27 | } |
| 27 | 28 | |
| 28 | 29 | @Override |
| 29 | 30 | public List<LogRecord> queryLog(String bizNo, String type) { |
| 30 | - return Collections.emptyList(); | |
| 31 | + throw new UnsupportedOperationException("不支持该操作,请使用 OperateLogApi 查询!"); | |
| 31 | 32 | } |
| 32 | 33 | |
| 33 | 34 | @Override |
| 34 | 35 | public List<LogRecord> queryLogByBizNo(String bizNo, String type, String subType) { |
| 35 | - return Collections.emptyList(); | |
| 36 | + throw new UnsupportedOperationException("不支持该操作,请使用 OperateLogApi 查询!"); | |
| 36 | 37 | } |
| 37 | 38 | |
| 38 | 39 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java
| ... | ... | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | 5 | import lombok.Data; |
| 6 | 6 | |
| 7 | +// TODO @puhui999:这个最好每个模块自己弄哈,放这里有点怪可能 | |
| 7 | 8 | @Schema(description = "管理后台 - 操作日志分页 Request VO") |
| 8 | 9 | @Data |
| 9 | 10 | public class OperateLogV2PageReqVO extends PageParam { | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java
| ... | ... | @@ -8,6 +8,7 @@ import org.springframework.stereotype.Component; |
| 8 | 8 | |
| 9 | 9 | import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; |
| 10 | 10 | |
| 11 | +// TODO @puhui999:还是放在 core 包下哈; | |
| 11 | 12 | /** |
| 12 | 13 | * 自定义函数-通过行业编号获取行业信息 |
| 13 | 14 | * |
| ... | ... | @@ -29,6 +30,7 @@ public class CrmIndustryParseFunction implements IParseFunction { |
| 29 | 30 | |
| 30 | 31 | @Override |
| 31 | 32 | public String apply(Object value) { |
| 33 | +// if (ObjUtil.isEmpty(value)) TODO @puhui999 可以直接替代哈; | |
| 32 | 34 | if (value == null) { |
| 33 | 35 | return ""; |
| 34 | 36 | } |
| ... | ... | @@ -37,10 +39,12 @@ public class CrmIndustryParseFunction implements IParseFunction { |
| 37 | 39 | } |
| 38 | 40 | |
| 39 | 41 | // 获取行业信息 |
| 42 | + // TODO @puhui999:这里可以不用 try catch 哇? | |
| 40 | 43 | try { |
| 41 | 44 | return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); |
| 42 | 45 | } catch (Exception ignored) { |
| 43 | 46 | } |
| 44 | 47 | return ""; |
| 45 | 48 | } |
| 49 | + | |
| 46 | 50 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java
| ... | ... | @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.api.permission.PermissionApi; |
| 12 | 12 | */ |
| 13 | 13 | public class CrmPermissionUtils { |
| 14 | 14 | |
| 15 | + // TODO @puhui999:isCrmAdmin。换成这个名字;因为 validate 一般是参数校验,不符合抛出异常;一般是 isXXXValid 才会返回 true false | |
| 15 | 16 | /** |
| 16 | 17 | * 校验用户是否是 CRM 管理员 |
| 17 | 18 | * |
| ... | ... | @@ -21,6 +22,7 @@ public class CrmPermissionUtils { |
| 21 | 22 | return SingletonManager.getPermissionApi().hasAnyRoles(getUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); |
| 22 | 23 | } |
| 23 | 24 | |
| 25 | + // TODO @puhui999:这个不需要哈,直接用原本的 SecuriyUtils 去拿更方便一些; | |
| 24 | 26 | /** |
| 25 | 27 | * 获得用户编号 |
| 26 | 28 | * | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
| ... | ... | @@ -68,6 +68,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 68 | 68 | return customer.getId(); |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | + // TODO @puhui999:测试下,能不能打出用户数据的变更。啊哈,可以打完微信发我下; | |
| 71 | 72 | @Override |
| 72 | 73 | @Transactional(rollbackFor = Exception.class) |
| 73 | 74 | @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}") | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
| ... | ... | @@ -90,6 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { |
| 90 | 90 | CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( |
| 91 | 91 | transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); |
| 92 | 92 | String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); |
| 93 | + // TODO @puhui999:是不是并且? 不是拥有者,并且不是超管 | |
| 93 | 94 | if (oldPermission == null || !isOwner(oldPermission.getLevel()) || !CrmPermissionUtils.validateAdminUser()) { |
| 94 | 95 | throw exception(CRM_PERMISSION_DENIED, bizTypeName); |
| 95 | 96 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java
| ... | ... | @@ -98,6 +98,7 @@ public class CrmQueryWrapperUtils { |
| 98 | 98 | private static class SingletonManager { |
| 99 | 99 | |
| 100 | 100 | private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); |
| 101 | + | |
| 101 | 102 | private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); |
| 102 | 103 | |
| 103 | 104 | public static AdminUserApi getAdminUserApi() { | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
| ... | ... | @@ -75,10 +75,9 @@ public class AppActivityController { |
| 75 | 75 | if (CollUtil.isEmpty(spuIds)) { |
| 76 | 76 | return new ArrayList<>(); |
| 77 | 77 | } |
| 78 | - | |
| 79 | - LocalDateTime now = LocalDateTime.now(); | |
| 80 | 78 | // 获取开启的且开始的且没有结束的活动 |
| 81 | 79 | List<AppActivityRespVO> activityList = new ArrayList<>(); |
| 80 | + LocalDateTime now = LocalDateTime.now(); | |
| 82 | 81 | // 1. 拼团活动 |
| 83 | 82 | getCombinationActivities(spuIds, now, activityList); |
| 84 | 83 | // 2. 秒杀活动 |
| ... | ... | @@ -99,6 +98,7 @@ public class AppActivityController { |
| 99 | 98 | return; |
| 100 | 99 | } |
| 101 | 100 | |
| 101 | + // TODO @puhui999:AppActivityRespVO 搞个构造方法,写起来更方便一些;这样后续万一加个属性,也可以处理下哈; | |
| 102 | 102 | combinationActivities.forEach(item -> { |
| 103 | 103 | activityList.add(new AppActivityRespVO().setId(item.getId()) |
| 104 | 104 | .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) |
| ... | ... | @@ -144,11 +144,9 @@ public class AppActivityController { |
| 144 | 144 | List<DiscountProductDO> products = discountActivityService.getDiscountProductsByActivityId( |
| 145 | 145 | convertSet(discountActivities, DiscountActivityDO::getId)); |
| 146 | 146 | Map<Long, Long> productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); |
| 147 | - discountActivities.forEach(item -> { | |
| 148 | - activityList.add(new AppActivityRespVO().setId(item.getId()) | |
| 149 | - .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) | |
| 150 | - .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); | |
| 151 | - }); | |
| 147 | + discountActivities.forEach(item -> activityList.add(new AppActivityRespVO().setId(item.getId()) | |
| 148 | + .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) | |
| 149 | + .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()))); | |
| 152 | 150 | } |
| 153 | 151 | |
| 154 | 152 | private void getRewardActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
| ... | ... | @@ -98,6 +98,7 @@ public interface DiscountActivityService { |
| 98 | 98 | * @param dateTime 当前日期时间 |
| 99 | 99 | * @return 折扣活动列表 |
| 100 | 100 | */ |
| 101 | - List<DiscountActivityDO> getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime); | |
| 101 | + List<DiscountActivityDO> getDiscountActivityBySpuIdsAndStatusAndDateTimeLt( | |
| 102 | + Collection<Long> spuIds, Integer status, LocalDateTime dateTime); | |
| 102 | 103 | |
| 103 | 104 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
| ... | ... | @@ -59,13 +59,12 @@ public class OperateLogApiImpl implements OperateLogApi { |
| 59 | 59 | return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | + // TODO @puhui999:这种 convert 还是放到 convert 类里, | |
| 62 | 63 | private static List<OperateLogV2RespDTO> setUserInfo(List<OperateLogV2DO> logList, List<AdminUserDO> userList) { |
| 63 | 64 | Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId); |
| 64 | 65 | return convertList(logList, item -> { |
| 65 | 66 | OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); |
| 66 | - findAndThen(userMap, item.getUserId(), user -> { | |
| 67 | - respDTO.setUserName(user.getNickname()); | |
| 68 | - }); | |
| 67 | + findAndThen(userMap, item.getUserId(), user -> respDTO.setUserName(user.getNickname())); | |
| 69 | 68 | return respDTO; |
| 70 | 69 | }); |
| 71 | 70 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java
| ... | ... | @@ -70,6 +70,7 @@ public class OperateLogV2DO extends BaseDO { |
| 70 | 70 | * 操作模块业务编号 |
| 71 | 71 | */ |
| 72 | 72 | private Long bizId; |
| 73 | + // TODO @puhui999:content 改成 action,extra 换成 String。注释就直接用 mzt,和它完全对应好了。 | |
| 73 | 74 | /** |
| 74 | 75 | * 操作内容,记录整个操作的明细 |
| 75 | 76 | * |
| ... | ... | @@ -83,6 +84,7 @@ public class OperateLogV2DO extends BaseDO { |
| 83 | 84 | */ |
| 84 | 85 | @TableField(typeHandler = JacksonTypeHandler.class) |
| 85 | 86 | private Map<String, Object> extra; |
| 87 | + | |
| 86 | 88 | /** |
| 87 | 89 | * 请求方法名 |
| 88 | 90 | */ |
| ... | ... | @@ -100,6 +102,7 @@ public class OperateLogV2DO extends BaseDO { |
| 100 | 102 | */ |
| 101 | 103 | private String userAgent; |
| 102 | 104 | |
| 105 | + // TODO @puhui999:微信已经讨论,下面的字段都不要哈; | |
| 103 | 106 | /** |
| 104 | 107 | * Java 方法名 |
| 105 | 108 | */ | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java
| ... | ... | @@ -6,6 +6,7 @@ import com.mzt.logapi.service.IParseFunction; |
| 6 | 6 | import lombok.extern.slf4j.Slf4j; |
| 7 | 7 | import org.springframework.stereotype.Component; |
| 8 | 8 | |
| 9 | +// TODO @puhui999:还是放在 core 包下哈; | |
| 9 | 10 | /** |
| 10 | 11 | * 自定义函数-通过区域编号获取区域信息 |
| 11 | 12 | * |
| ... | ... | @@ -36,4 +37,5 @@ public class AreaParseFunction implements IParseFunction { |
| 36 | 37 | |
| 37 | 38 | return AreaUtils.format(Integer.parseInt(value.toString())); |
| 38 | 39 | } |
| 40 | + | |
| 39 | 41 | } | ... | ... |
yudao-server/src/main/resources/application.yaml
| ... | ... | @@ -79,17 +79,11 @@ mybatis-plus: |
| 79 | 79 | password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 |
| 80 | 80 | |
| 81 | 81 | mybatis-plus-join: |
| 82 | - #是否打印 mybatis plus join banner 默认true | |
| 83 | - banner: false | |
| 84 | - #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除 | |
| 85 | - sub-table-logic: true | |
| 86 | - #拦截器MappedStatement缓存(默认true) | |
| 87 | - ms-cache: true | |
| 88 | - #表别名(默认 t) | |
| 89 | - table-alias: t | |
| 90 | - #副表逻辑删除条件的位置,支持where、on | |
| 91 | - #默认ON (1.4.7.2及之前版本默认为where) | |
| 92 | - logic-del-type: on | |
| 82 | + banner: false # 是否打印 mybatis plus join banner,默认true | |
| 83 | + sub-table-logic: true # 全局启用副表逻辑删除,默认true。关闭后关联查询不会加副表逻辑删除 | |
| 84 | + ms-cache: true # 拦截器MappedStatement缓存,默认 true | |
| 85 | + table-alias: t # 表别名(默认 t) | |
| 86 | + logic-del-type: on # 副表逻辑删除条件的位置,支持 WHERE、ON,默认 ON | |
| 93 | 87 | |
| 94 | 88 | # Spring Data Redis 配置 |
| 95 | 89 | spring: | ... | ... |