diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index 7f07c1e97..46de69603 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -29,6 +29,7 @@
3.5.5
4.3.0
1.4.10
+ 2.2.11
3.26.0
8.1.3.62
@@ -224,6 +225,32 @@
${mybatis-plus-join.version}
+
+ com.fhs-opensource
+ easy-trans-spring-boot-starter
+ ${easy-trans.version}
+
+
+ org.springframework
+ spring-context
+
+
+ org.springframework.cloud
+ spring-cloud-commons
+
+
+
+
+ com.fhs-opensource
+ easy-trans-mybatis-plus-extend
+ ${easy-trans.version}
+
+
+ com.fhs-opensource
+ easy-trans-anno
+ ${easy-trans.version}
+
+
cn.iocoder.cloud
yudao-spring-boot-starter-redis
diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml
index 6e743cc2a..5bc169107 100644
--- a/yudao-framework/yudao-common/pom.xml
+++ b/yudao-framework/yudao-common/pom.xml
@@ -137,6 +137,11 @@
transmittable-thread-local
+
+ com.fhs-opensource
+ easy-trans-anno
+
+
org.springframework.boot
diff --git a/yudao-framework/yudao-common/src/main/java/com/fhs/trans/service/AutoTransable.java b/yudao-framework/yudao-common/src/main/java/com/fhs/trans/service/AutoTransable.java
new file mode 100644
index 000000000..b166863d8
--- /dev/null
+++ b/yudao-framework/yudao-common/src/main/java/com/fhs/trans/service/AutoTransable.java
@@ -0,0 +1,59 @@
+package com.fhs.trans.service;
+
+import com.fhs.core.trans.vo.VO;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 只有实现了这个接口的才能自动翻译
+ *
+ * 为什么要赋值粘贴到 yudao-common 包下?
+ * 因为 AutoTransable 属于 easy-trans-service 下,无法方便的在 yudao-module-xxx-api 模块下使用
+ *
+ * @author jackwang
+ * @since 2020-05-19 10:26:15
+ */
+public interface AutoTransable {
+
+ /**
+ * 根据 ids 查询数据列表
+ *
+ * 改方法已过期啦,请使用 selectByIds
+ *
+ * @param ids 编号数组
+ * @return 数据列表
+ */
+ @Deprecated
+ default List findByIds(List extends Object> ids){
+ return new ArrayList<>();
+ }
+
+ /**
+ * 根据 ids 查询
+ *
+ * @param ids 编号数组
+ * @return 数据列表
+ */
+ default List selectByIds(List extends Object> ids){
+ return this.findByIds(ids);
+ }
+
+ /**
+ * 获取 db 中所有的数据
+ *
+ * @return db 中所有的数据
+ */
+ default List select(){
+ return new ArrayList<>();
+ }
+
+ /**
+ * 根据 id 获取 vo
+ *
+ * @param primaryValue id
+ * @return vo
+ */
+ V selectById(Object primaryValue);
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
index ba6820d23..d02b68d73 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
@@ -77,6 +77,15 @@
com.github.yulichang
mybatis-plus-join-boot-starter
+
+
+ com.fhs-opensource
+ easy-trans-spring-boot-starter
+
+
+ com.fhs-opensource
+ easy-trans-mybatis-plus-extend
+
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java
index 19abaa6fe..fc5f0a301 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/dataobject/BaseDO.java
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.mybatis.core.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fhs.core.trans.vo.TransPojo;
import lombok.Data;
import org.apache.ibatis.type.JdbcType;
@@ -12,10 +14,14 @@ import java.time.LocalDateTime;
/**
* 基础实体对象
*
+ * 为什么实现 {@link TransPojo} 接口?
+ * 因为使用 Easy-Trans TransType.SIMPLE 模式,集成 MyBatis Plus 查询
+ *
* @author 芋道源码
*/
@Data
-public abstract class BaseDO implements Serializable {
+@JsonIgnoreProperties(value = "transMap") // 由于 Easy-Trans 会添加 transMap 属性,避免 Jackson 在 Spring Cache 反序列化报错
+public abstract class BaseDO implements Serializable, TransPojo {
/**
* 创建时间
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/config/YudaoTranslateAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/config/YudaoTranslateAutoConfiguration.java
new file mode 100644
index 000000000..bcc46b80d
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/config/YudaoTranslateAutoConfiguration.java
@@ -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();
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/core/TranslateUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/core/TranslateUtils.java
new file mode 100644
index 000000000..2974b0c32
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/core/TranslateUtils.java
@@ -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 List translate(List data) {
+ if (CollUtil.isNotEmpty((data))) {
+ transService.transBatch(data);
+ }
+ return data;
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/package-info.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/package-info.java
new file mode 100644
index 000000000..f14914a08
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/translate/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 使用 Easy-Trans 提升使用 VO 数据翻译的开发效率
+ */
+package cn.iocoder.yudao.framework.translate;
diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index c4aee8a93..4a4eb95b7 100644
--- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,2 +1,3 @@
cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration
cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration
+cn.iocoder.yudao.framework.translate.config.YudaoTranslateAutoConfiguration
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java
index 1d04e7759..b8c1ed208 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java
@@ -1,23 +1,19 @@
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.PageParam;
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.excel.core.util.ExcelUtils;
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.CrmProductRespVO;
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.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.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.Parameter;
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 java.io.IOException;
-import java.util.Collections;
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.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 java.util.Collections.singletonList;
@Tag(name = "管理后台 - CRM 产品")
@RestController
@@ -47,9 +39,6 @@ public class CrmProductController {
@Resource
private CrmProductService productService;
- @Resource
- private CrmProductCategoryService productCategoryService;
-
@Resource
private AdminUserApi adminUserApi;
@@ -83,14 +72,7 @@ public class CrmProductController {
@PreAuthorize("@ss.hasPermission('crm:product:query')")
public CommonResult getProduct(@RequestParam("id") Long id) {
CrmProductDO product = productService.getProduct(id);
- return success(buildProductDetail(product));
- }
-
- private CrmProductRespVO buildProductDetail(CrmProductDO product) {
- if (product == null) {
- return null;
- }
- return buildProductDetailList(singletonList(product)).get(0);
+ return success(BeanUtils.toBean(product, CrmProductRespVO.class));
}
@GetMapping("/simple-list")
@@ -106,7 +88,7 @@ public class CrmProductController {
@PreAuthorize("@ss.hasPermission('crm:product:query')")
public CommonResult> getProductPage(@Valid CrmProductPageReqVO pageVO) {
PageResult pageResult = productService.getProductPage(pageVO);
- return success(new PageResult<>(buildProductDetailList(pageResult.getList()), pageResult.getTotal()));
+ return success(BeanUtils.toBean(pageResult, CrmProductRespVO.class));
}
@GetMapping("/export-excel")
@@ -119,27 +101,7 @@ public class CrmProductController {
List list = productService.getProductPage(exportReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "产品.xls", "数据", CrmProductRespVO.class,
- buildProductDetailList(list));
- }
-
- private List buildProductDetailList(List list) {
- if (CollUtil.isEmpty(list)) {
- return Collections.emptyList();
- }
- // 1.1 获得用户信息
- Map userMap = adminUserApi.getUserMap(
- convertSetByFlatMap(list, user -> Stream.of(Long.valueOf(user.getCreator()), user.getOwnerUserId())));
- // 1.2 获得分类信息
- Map 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()));
- });
+ TranslateUtils.translate(BeanUtils.toBean(list, CrmProductRespVO.class)));
}
}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java
index 1f659aa77..08625b8ca 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java
@@ -2,9 +2,14 @@ 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.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.system.api.user.AdminUserApi;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
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 lombok.Data;
@@ -14,7 +19,7 @@ import java.time.LocalDateTime;
@Schema(description = "管理后台 - CRM 产品 Response VO")
@Data
@ExcelIgnoreUnannotated
-public class CrmProductRespVO {
+public class CrmProductRespVO implements VO {
@Schema(description = "产品编号", example = "20529")
@ExcelProperty("产品编号")
@@ -43,6 +48,7 @@ public class CrmProductRespVO {
private Integer status;
@Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+ @Trans(type = TransType.SIMPLE, target = CrmProductCategoryDO.class, fields = "name", ref = "categoryName")
private Long categoryId;
@Schema(description = "产品分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "衣服")
@ExcelProperty("产品分类")
@@ -53,12 +59,16 @@ public class CrmProductRespVO {
private String description;
@Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31926")
+ @Trans(type = TransType.AUTO_TRANS, key = AdminUserApi.PREFIX,
+ fields = "nickname", ref = "ownerUserName")
private Long ownerUserId;
@Schema(description = "负责人的用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
@ExcelProperty("负责人")
private String ownerUserName;
@Schema(description = "创建人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @Trans(type = TransType.AUTO_TRANS, key = AdminUserApi.PREFIX,
+ fields = "nickname", ref = "creatorName")
private String creator;
@Schema(description = "创建人名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
@ExcelProperty("创建人")
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/application.yaml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/application.yaml
index 7860f1328..dfe866cd4 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/application.yaml
+++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/application.yaml
@@ -70,6 +70,11 @@ spring:
repositories:
enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度
+# VO 转换(数据翻译)相关
+easy-trans:
+ is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口
+ is-enable-cloud: false # 禁用 TransType.RPC 微服务模式
+
--- #################### MQ 消息队列相关配置 ####################
--- #################### 定时任务相关配置 ####################
diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java
index 502356810..c2460fedc 100644
--- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java
@@ -1,5 +1,8 @@
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 io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,11 +10,16 @@ import java.time.LocalDateTime;
@Schema(name = "RPC 服务 - 系统操作日志 Response DTO")
@Data
-public class OperateLogV2RespDTO {
+public class OperateLogV2RespDTO implements VO {
+
+ @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long id;
@Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "89aca178-a370-411c-ae02-3f0d672be4ab")
private String traceId;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
+ @Trans(type = TransType.RPC, targetClassName = "cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO",
+ fields = "nickname", ref = "userName")
private Long userId;
@Schema(description = "用户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String userName;
diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
index 13342ec7e..4be228d3d 100644
--- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
@@ -1,9 +1,13 @@
package cn.iocoder.yudao.module.system.api.user;
+import cn.hutool.core.convert.Convert;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.enums.ApiConstants;
+import com.fhs.core.trans.anno.AutoTrans;
+import com.fhs.trans.service.AutoTransable;
+import feign.FeignIgnore;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
@@ -13,9 +17,12 @@ import org.springframework.web.bind.annotation.RequestParam;
import java.util.*;
+import static cn.iocoder.yudao.module.system.api.user.AdminUserApi.PREFIX;
+
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
@Tag(name = "RPC 服务 - 管理员用户")
-public interface AdminUserApi {
+@AutoTrans(namespace = PREFIX, fields = {"nickname"})
+public interface AdminUserApi extends AutoTransable {
String PREFIX = ApiConstants.PREFIX + "/user";
@@ -71,4 +78,16 @@ public interface AdminUserApi {
@Parameter(name = "ids", description = "用户编号数组", example = "3,5", required = true)
CommonResult validateUserList(@RequestParam("ids") Collection ids);
+ @Override
+ @FeignIgnore
+ default List selectByIds(List> ids) {
+ return getUserList(Convert.toList(Long.class, ids)).getCheckedData();
+ }
+
+ @Override
+ @FeignIgnore
+ default AdminUserRespDTO selectById(Object id) {
+ return getUser(Convert.toLong(id)).getCheckedData();
+ }
+
}
diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java
index a2e5e4a1a..e5af684e3 100644
--- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/dto/AdminUserRespDTO.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.api.user.dto;
+import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,7 +8,7 @@ import java.util.Set;
@Schema(description = "RPC 服务 - Admin 用户 Response DTO")
@Data
-public class AdminUserRespDTO {
+public class AdminUserRespDTO implements VO {
@Schema(description = "用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
index d36ee51f7..f6aeb7744 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java
@@ -1,26 +1,19 @@
package cn.iocoder.yudao.module.system.api.logger;
-import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
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.OperateLogV2CreateReqDTO;
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.convert.logger.OperateLogConvert;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
-import jakarta.annotation.Resource;
-
-import java.util.List;
-
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
@@ -28,8 +21,6 @@ public class OperateLogApiImpl implements OperateLogApi {
@Resource
private OperateLogService operateLogService;
- @Resource
- private AdminUserService adminUserService;
@Override
public CommonResult createOperateLog(OperateLogCreateReqDTO createReqDTO) {
@@ -46,14 +37,7 @@ public class OperateLogApiImpl implements OperateLogApi {
@Override
public CommonResult> getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) {
PageResult operateLogPage = operateLogService.getOperateLogPage(pageReqVO);
- if (CollUtil.isEmpty(operateLogPage.getList())) {
- return success(PageResult.empty());
- }
-
- // 获取用户
- List userList = adminUserService.getUserList(
- convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId));
- return success(OperateLogConvert.INSTANCE.convertPage(operateLogPage, userList));
+ return success(BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class));
}
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http
index f667482da..068436aa2 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.http
@@ -1,4 +1,4 @@
-### 请求 /system/operate-log/demo 接口 => 成功
-GET {{baseUrl}}/system/operate-log/demo
+### 请求 /system/operate-log/page 接口 => 成功
+GET {{systemBaseUrl}}/system/operate-log/page
Authorization: Bearer {{token}}
tenant-id: {{adminTenentId}}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java
index 744f8b02a..2933eef29 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java
@@ -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.PageParam;
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.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.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.user.AdminUserDO;
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.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.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 jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.Valid;
import java.io.IOException;
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.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 操作日志")
@@ -39,19 +36,13 @@ public class OperateLogController {
@Resource
private OperateLogService operateLogService;
- @Resource
- private AdminUserService userService;
@GetMapping("/page")
@Operation(summary = "查看操作日志分页列表")
@PreAuthorize("@ss.hasPermission('system:operate-log:query')")
public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) {
PageResult pageResult = operateLogService.getOperateLogPage(pageReqVO);
- // 获得拼接需要的数据
- Map userMap = userService.getUserMap(
- convertList(pageResult.getList(), OperateLogDO::getUserId));
- return success(new PageResult<>(OperateLogConvert.INSTANCE.convertList(pageResult.getList(), userMap),
- pageResult.getTotal()));
+ return success(BeanUtils.toBean(pageResult, OperateLogRespVO.class));
}
@Operation(summary = "导出操作日志")
@@ -61,11 +52,8 @@ public class OperateLogController {
public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List list = operateLogService.getOperateLogPage(exportReqVO).getList();
- // 输出
- Map userMap = userService.getUserMap(
- convertList(list, OperateLogDO::getUserId));
ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class,
- OperateLogConvert.INSTANCE.convertList(list, userMap));
+ TranslateUtils.translate(BeanUtils.toBean(list, OperateLogRespVO.class)));
}
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java
index f8962bb51..575dc417b 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java
@@ -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.convert.DictConvert;
+import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
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 jakarta.validation.constraints.NotEmpty;
import lombok.Data;
-import jakarta.validation.constraints.NotEmpty;
import java.time.LocalDateTime;
import java.util.Map;
@Schema(description = "管理后台 - 操作日志 Response VO")
@Data
@ExcelIgnoreUnannotated
-public class OperateLogRespVO {
+public class OperateLogRespVO implements VO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("日志编号")
@@ -25,6 +29,7 @@ public class OperateLogRespVO {
private String traceId;
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ @Trans(type = TransType.SIMPLE, target = AdminUserDO.class, fields = "nickname", ref = "userNickname")
private Long userId;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java
deleted file mode 100644
index 9500a35f5..000000000
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java
+++ /dev/null
@@ -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 convertList(List list, Map 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 convertPage(PageResult operateLogPage, List userList) {
- return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList));
- }
-
- OperateLogV2RespDTO convert(OperateLogV2DO operateLogV2DO);
-
- default List setUserInfo(List logList, List userList) {
- Map 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;
- });
- }
-
-}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml
index 9a8da02a9..0e8545b90 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml
+++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml
@@ -70,6 +70,11 @@ spring:
repositories:
enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度
+# VO 转换(数据翻译)相关
+easy-trans:
+ is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口
+ is-enable-cloud: false # 禁用 TransType.RPC 微服务模式
+
--- #################### RPC 远程调用相关配置 ####################
--- #################### 消息队列相关 ####################