!930 全局:增加 VO 数据翻译的支持

Merge pull request !930 from 芋道源码/feature/easy-trans
This commit is contained in:
芋道源码 2024-04-02 12:05:01 +00:00 committed by Gitee
commit 9fac998a14
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
18 changed files with 160 additions and 134 deletions

View File

@ -27,6 +27,7 @@
<mybatis-plus-generator.version>3.5.5</mybatis-plus-generator.version> <mybatis-plus-generator.version>3.5.5</mybatis-plus-generator.version>
<dynamic-datasource.version>4.3.0</dynamic-datasource.version> <dynamic-datasource.version>4.3.0</dynamic-datasource.version>
<mybatis-plus-join.version>1.4.10</mybatis-plus-join.version> <mybatis-plus-join.version>1.4.10</mybatis-plus-join.version>
<easy-trans.version>2.2.11</easy-trans.version>
<redisson.version>3.26.0</redisson.version> <redisson.version>3.26.0</redisson.version>
<dm8.jdbc.version>8.1.3.62</dm8.jdbc.version> <dm8.jdbc.version>8.1.3.62</dm8.jdbc.version>
<!-- 消息队列 --> <!-- 消息队列 -->
@ -197,6 +198,32 @@
<version>${mybatis-plus-join.version}</version> <version>${mybatis-plus-join.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
<artifactId>easy-trans-spring-boot-starter</artifactId>
<version>${easy-trans.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fhs-opensource</groupId>
<artifactId>easy-trans-mybatis-plus-extend</artifactId>
<version>${easy-trans.version}</version>
</dependency>
<dependency>
<groupId>com.fhs-opensource</groupId>
<artifactId>easy-trans-anno</artifactId>
<version>${easy-trans.version}</version>
</dependency>
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-redis</artifactId> <artifactId>yudao-spring-boot-starter-redis</artifactId>

View File

@ -137,6 +137,11 @@
<artifactId>transmittable-thread-local</artifactId> <artifactId>transmittable-thread-local</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
<artifactId>easy-trans-anno</artifactId> <!-- 默认引入的原因,方便 xxx-module-api 包使用 -->
</dependency>
<!-- Test 测试相关 --> <!-- Test 测试相关 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -77,6 +77,15 @@
<groupId>com.github.yulichang</groupId> <groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 --> <artifactId>mybatis-plus-join-boot-starter</artifactId> <!-- MyBatis 联表查询 -->
</dependency> </dependency>
<dependency>
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
<artifactId>easy-trans-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.fhs-opensource</groupId>
<artifactId>easy-trans-mybatis-plus-extend</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fhs.core.trans.vo.TransPojo;
import lombok.Data; import lombok.Data;
import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.JdbcType;
@ -12,10 +14,14 @@ import java.time.LocalDateTime;
/** /**
* 基础实体对象 * 基础实体对象
* *
* 为什么实现 {@link TransPojo} 接口
* 因为使用 Easy-Trans TransType.SIMPLE 模式集成 MyBatis Plus 查询
*
* @author 芋道源码 * @author 芋道源码
*/ */
@Data @Data
public abstract class BaseDO implements Serializable { @JsonIgnoreProperties(value = "transMap") // 由于 Easy-Trans 会添加 transMap 属性避免 Jackson Spring Cache 反序列化报错
public abstract class BaseDO implements Serializable, TransPojo {
/** /**
* 创建时间 * 创建时间

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.framework.translate.config;
import cn.iocoder.yudao.framework.translate.core.TranslateUtils;
import com.fhs.trans.service.impl.TransService;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
@AutoConfiguration
public class YudaoTranslateAutoConfiguration {
@Bean
@SuppressWarnings({"InstantiationOfUtilityClass", "SpringJavaInjectionPointsAutowiringInspection"})
public TranslateUtils translateUtils(TransService transService) {
TranslateUtils.init(transService);
return new TranslateUtils();
}
}

View File

@ -0,0 +1,37 @@
package cn.iocoder.yudao.framework.translate.core;
import cn.hutool.core.collection.CollUtil;
import com.fhs.core.trans.vo.VO;
import com.fhs.trans.service.impl.TransService;
import java.util.List;
/**
* VO 数据翻译 Utils
*
* @author 芋道源码
*/
public class TranslateUtils {
private static TransService transService;
public static void init(TransService transService) {
TranslateUtils.transService = transService;
}
/**
* 数据翻译
*
* 使用场景无法使用 @TransMethodResult 注解的场景只能通过手动触发翻译
*
* @param data 数据
* @return 翻译结果
*/
public static <T extends VO> List<T> translate(List<T> data) {
if (CollUtil.isNotEmpty((data))) {
transService.transBatch(data);
}
return data;
}
}

View File

@ -0,0 +1,4 @@
/**
* 使用 Easy-Trans 提升使用 VO 数据翻译的开发效率
*/
package cn.iocoder.yudao.framework.translate;

View File

@ -1,2 +1,3 @@
cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration
cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration
cn.iocoder.yudao.framework.translate.config.YudaoTranslateAutoConfiguration

View File

@ -1,23 +1,19 @@
package cn.iocoder.yudao.module.crm.controller.admin.product; package cn.iocoder.yudao.module.crm.controller.admin.product;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.translate.core.TranslateUtils;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum; import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum;
import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService;
import cn.iocoder.yudao.module.crm.service.product.CrmProductService; import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 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; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -29,15 +25,11 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static java.util.Collections.singletonList;
@Tag(name = "管理后台 - CRM 产品") @Tag(name = "管理后台 - CRM 产品")
@RestController @RestController
@ -47,9 +39,6 @@ public class CrmProductController {
@Resource @Resource
private CrmProductService productService; private CrmProductService productService;
@Resource
private CrmProductCategoryService productCategoryService;
@Resource @Resource
private AdminUserApi adminUserApi; private AdminUserApi adminUserApi;
@ -83,14 +72,7 @@ public class CrmProductController {
@PreAuthorize("@ss.hasPermission('crm:product:query')") @PreAuthorize("@ss.hasPermission('crm:product:query')")
public CommonResult<CrmProductRespVO> getProduct(@RequestParam("id") Long id) { public CommonResult<CrmProductRespVO> getProduct(@RequestParam("id") Long id) {
CrmProductDO product = productService.getProduct(id); CrmProductDO product = productService.getProduct(id);
return success(buildProductDetail(product)); return success(BeanUtils.toBean(product, CrmProductRespVO.class));
}
private CrmProductRespVO buildProductDetail(CrmProductDO product) {
if (product == null) {
return null;
}
return buildProductDetailList(singletonList(product)).get(0);
} }
@GetMapping("/simple-list") @GetMapping("/simple-list")
@ -106,7 +88,7 @@ public class CrmProductController {
@PreAuthorize("@ss.hasPermission('crm:product:query')") @PreAuthorize("@ss.hasPermission('crm:product:query')")
public CommonResult<PageResult<CrmProductRespVO>> getProductPage(@Valid CrmProductPageReqVO pageVO) { public CommonResult<PageResult<CrmProductRespVO>> getProductPage(@Valid CrmProductPageReqVO pageVO) {
PageResult<CrmProductDO> pageResult = productService.getProductPage(pageVO); PageResult<CrmProductDO> pageResult = productService.getProductPage(pageVO);
return success(new PageResult<>(buildProductDetailList(pageResult.getList()), pageResult.getTotal())); return success(BeanUtils.toBean(pageResult, CrmProductRespVO.class));
} }
@GetMapping("/export-excel") @GetMapping("/export-excel")
@ -119,27 +101,7 @@ public class CrmProductController {
List<CrmProductDO> list = productService.getProductPage(exportReqVO).getList(); List<CrmProductDO> list = productService.getProductPage(exportReqVO).getList();
// 导出 Excel // 导出 Excel
ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class, ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class,
buildProductDetailList(list)); TranslateUtils.translate(BeanUtils.toBean(list, CrmProductRespVO.class)));
}
private List<CrmProductRespVO> buildProductDetailList(List<CrmProductDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 1.1 获得用户信息
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSetByFlatMap(list, user -> Stream.of(Long.valueOf(user.getCreator()), user.getOwnerUserId())));
// 1.2 获得分类信息
Map<Long, CrmProductCategoryDO> categoryMap = productCategoryService.getProductCategoryMap(
convertSet(list, CrmProductDO::getCategoryId));
// 2. 拼接数据
return BeanUtils.toBean(list, CrmProductRespVO.class, productVO -> {
// 2.1 设置用户信息
MapUtils.findAndThen(userMap, productVO.getOwnerUserId(), user -> productVO.setOwnerUserName(user.getNickname()));
MapUtils.findAndThen(userMap, Long.valueOf(productVO.getCreator()), user -> productVO.setCreatorName(user.getNickname()));
// 2.2 设置分类名称
MapUtils.findAndThen(categoryMap, productVO.getCategoryId(), category -> productVO.setCategoryName(category.getName()));
});
} }
} }

View File

@ -2,9 +2,13 @@ package cn.iocoder.yudao.module.crm.controller.admin.product.vo.product;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@ -14,7 +18,7 @@ import java.time.LocalDateTime;
@Schema(description = "管理后台 - CRM 产品 Response VO") @Schema(description = "管理后台 - CRM 产品 Response VO")
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class CrmProductRespVO { public class CrmProductRespVO implements VO {
@Schema(description = "产品编号", example = "20529") @Schema(description = "产品编号", example = "20529")
@ExcelProperty("产品编号") @ExcelProperty("产品编号")
@ -43,6 +47,7 @@ public class CrmProductRespVO {
private Integer status; private Integer status;
@Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@Trans(type = TransType.SIMPLE, target = CrmProductCategoryDO.class, fields = "name", ref = "categoryName")
private Long categoryId; private Long categoryId;
@Schema(description = "产品分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "衣服") @Schema(description = "产品分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "衣服")
@ExcelProperty("产品分类") @ExcelProperty("产品分类")
@ -53,12 +58,16 @@ public class CrmProductRespVO {
private String description; private String description;
@Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31926") @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31926")
@Trans(type = TransType.RPC, targetClassName = "cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO",
fields = "nickname", ref = "ownerUserName")
private Long ownerUserId; private Long ownerUserId;
@Schema(description = "负责人的用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @Schema(description = "负责人的用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
@ExcelProperty("负责人") @ExcelProperty("负责人")
private String ownerUserName; private String ownerUserName;
@Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@Trans(type = TransType.RPC, targetClassName = "cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO",
fields = "nickname", ref = "creatorName")
private String creator; private String creator;
@Schema(description = "创建人名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @Schema(description = "创建人名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
@ExcelProperty("创建人") @ExcelProperty("创建人")

View File

@ -1,5 +1,8 @@
package cn.iocoder.yudao.module.system.api.logger.dto; package cn.iocoder.yudao.module.system.api.logger.dto;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -10,8 +13,12 @@ import java.time.LocalDateTime;
* @author HUIHUI * @author HUIHUI
*/ */
@Data @Data
public class OperateLogV2RespDTO { public class OperateLogV2RespDTO implements VO {
/**
* 日志编号
*/
private Long id;
/** /**
* 链路追踪编号 * 链路追踪编号
*/ */
@ -19,6 +26,8 @@ public class OperateLogV2RespDTO {
/** /**
* 用户编号 * 用户编号
*/ */
@Trans(type = TransType.RPC, targetClassName = "cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO",
fields = "nickname", ref = "userName")
private Long userId; private Long userId;
/** /**
* 用户名称 * 用户名称

View File

@ -2,24 +2,19 @@ package cn.iocoder.yudao.module.system.api.logger;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.OperateLogCreateReqDTO;
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO;
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; 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.logger.OperateLogService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.fhs.core.trans.anno.TransMethodResult;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
/** /**
* 操作日志 API 实现类 * 操作日志 API 实现类
* *
@ -31,8 +26,6 @@ public class OperateLogApiImpl implements OperateLogApi {
@Resource @Resource
private OperateLogService operateLogService; private OperateLogService operateLogService;
@Resource
private AdminUserService adminUserService;
@Override @Override
public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { public void createOperateLog(OperateLogCreateReqDTO createReqDTO) {
@ -46,16 +39,13 @@ public class OperateLogApiImpl implements OperateLogApi {
} }
@Override @Override
@TransMethodResult
public PageResult<OperateLogV2RespDTO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { public PageResult<OperateLogV2RespDTO> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) {
PageResult<OperateLogV2DO> operateLogPage = operateLogService.getOperateLogPage(pageReqVO); PageResult<OperateLogV2DO> operateLogPage = operateLogService.getOperateLogPage(pageReqVO);
if (CollUtil.isEmpty(operateLogPage.getList())) { if (CollUtil.isEmpty(operateLogPage.getList())) {
return PageResult.empty(); return PageResult.empty();
} }
return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class);
// 获取用户
List<AdminUserDO> userList = adminUserService.getUserList(
convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId));
return OperateLogConvert.INSTANCE.convertPage(operateLogPage, userList);
} }
} }

View File

@ -1,4 +1,4 @@
### 请求 /system/operate-log/demo 接口 => 成功 ### 请求 /system/operate-log/page 接口 => 成功
GET {{baseUrl}}/system/operate-log/demo GET {{baseUrl}}/system/operate-log/page
Authorization: Bearer {{token}} Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}} tenant-id: {{adminTenentId}}

View File

@ -3,32 +3,29 @@ package cn.iocoder.yudao.module.system.controller.admin.logger;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.translate.core.TranslateUtils;
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO;
import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
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.logger.OperateLogService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 操作日志") @Tag(name = "管理后台 - 操作日志")
@ -39,19 +36,13 @@ public class OperateLogController {
@Resource @Resource
private OperateLogService operateLogService; private OperateLogService operateLogService;
@Resource
private AdminUserService userService;
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "查看操作日志分页列表") @Operation(summary = "查看操作日志分页列表")
@PreAuthorize("@ss.hasPermission('system:operate-log:query')") @PreAuthorize("@ss.hasPermission('system:operate-log:query')")
public CommonResult<PageResult<OperateLogRespVO>> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) { public CommonResult<PageResult<OperateLogRespVO>> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) {
PageResult<OperateLogDO> pageResult = operateLogService.getOperateLogPage(pageReqVO); PageResult<OperateLogDO> pageResult = operateLogService.getOperateLogPage(pageReqVO);
// 获得拼接需要的数据 return success(BeanUtils.toBean(pageResult, OperateLogRespVO.class));
Map<Long, AdminUserDO> userMap = userService.getUserMap(
convertList(pageResult.getList(), OperateLogDO::getUserId));
return success(new PageResult<>(OperateLogConvert.INSTANCE.convertList(pageResult.getList(), userMap),
pageResult.getTotal()));
} }
@Operation(summary = "导出操作日志") @Operation(summary = "导出操作日志")
@ -61,11 +52,8 @@ public class OperateLogController {
public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException { public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<OperateLogDO> list = operateLogService.getOperateLogPage(exportReqVO).getList(); List<OperateLogDO> list = operateLogService.getOperateLogPage(exportReqVO).getList();
// 输出
Map<Long, AdminUserDO> userMap = userService.getUserMap(
convertList(list, OperateLogDO::getUserId));
ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class, ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class,
OperateLogConvert.INSTANCE.convertList(list, userMap)); TranslateUtils.translate(BeanUtils.toBean(list, OperateLogRespVO.class)));
} }
} }

View File

@ -2,20 +2,24 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data; import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Map; import java.util.Map;
@Schema(description = "管理后台 - 操作日志 Response VO") @Schema(description = "管理后台 - 操作日志 Response VO")
@Data @Data
@ExcelIgnoreUnannotated @ExcelIgnoreUnannotated
public class OperateLogRespVO { public class OperateLogRespVO implements VO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("日志编号") @ExcelProperty("日志编号")
@ -25,6 +29,7 @@ public class OperateLogRespVO {
private String traceId; private String traceId;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userNickname")
private Long userId; private Long userId;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")

View File

@ -1,49 +0,0 @@
package cn.iocoder.yudao.module.system.convert.logger;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO;
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.dal.dataobject.user.AdminUserDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
@Mapper
public interface OperateLogConvert {
OperateLogConvert INSTANCE = Mappers.getMapper(OperateLogConvert.class);
default List<OperateLogRespVO> convertList(List<OperateLogDO> list, Map<Long, AdminUserDO> userMap) {
return CollectionUtils.convertList(list, log -> {
OperateLogRespVO logVO = BeanUtils.toBean(log, OperateLogRespVO.class);
MapUtils.findAndThen(userMap, log.getUserId(), user -> logVO.setUserNickname(user.getNickname()));
return logVO;
});
}
default PageResult<OperateLogV2RespDTO> convertPage(PageResult<OperateLogV2DO> operateLogPage, List<AdminUserDO> userList) {
return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList));
}
OperateLogV2RespDTO convert(OperateLogV2DO operateLogV2DO);
default List<OperateLogV2RespDTO> setUserInfo(List<OperateLogV2DO> logList, List<AdminUserDO> userList) {
Map<Long, AdminUserDO> userMap = convertMap(userList, AdminUserDO::getId);
return CollectionUtils.convertList(logList, item -> {
OperateLogV2RespDTO respDTO = convert(item);
findAndThen(userMap, item.getUserId(), user -> respDTO.setUserName(user.getNickname()));
return respDTO;
});
}
}

View File

@ -91,6 +91,12 @@ spring:
redis: redis:
repositories: repositories:
enabled: false # 项目未使用到 Spring Data Redis 的 Repository所以直接禁用保证启动速度 enabled: false # 项目未使用到 Spring Data Redis 的 Repository所以直接禁用保证启动速度
# VO 转换(数据翻译)相关
easy-trans:
is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口
is-enable-cloud: false # 禁用 TransType.RPC 微服务模式
--- #################### 验证码相关配置 #################### --- #################### 验证码相关配置 ####################
aj: aj: