Browse Source

多模块重构 11:修复代码生成的 BaseDO 模板不正确

YunaiV 3 years ago
parent
commit
f2f36bd617
18 changed files with 866 additions and 76 deletions
  1. 94 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/TestDemoController.java
  2. 34 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoBaseVO.java
  3. 14 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoCreateReqVO.java
  4. 38 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExcelVO.java
  5. 38 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExportReqVO.java
  6. 40 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoPageReqVO.java
  7. 19 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoRespVO.java
  8. 18 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoUpdateReqVO.java
  9. 34 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/test/TestDemoConvert.java
  10. 70 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/test/TestDemoDO.java
  11. 42 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/test/TestDemoMapper.java
  12. 6 6
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenEngine.java
  13. 70 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoService.java
  14. 82 0
      yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImpl.java
  15. 187 0
      yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImplTest.java
  16. 39 0
      yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/test/BaseDbUnitTest.java
  17. 0 1
      yudao-ui-admin/src/api/tool/testDemo.js
  18. 41 69
      yudao-ui-admin/src/views/tool/testDemo/index.vue

+ 94 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/TestDemoController.java

@@ -0,0 +1,94 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test;
+
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.annotations.*;
+
+import javax.validation.constraints.*;
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*;
+import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
+import cn.iocoder.yudao.module.tool.convert.test.TestDemoConvert;
+import cn.iocoder.yudao.module.tool.service.test.TestDemoService;
+
+@Api(tags = "管理后台 - 字典类型")
+@RestController
+@RequestMapping("/tool/test-demo")
+@Validated
+public class TestDemoController {
+
+    @Resource
+    private TestDemoService testDemoService;
+
+    @PostMapping("/create")
+    @ApiOperation("创建字典类型")
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:create')")    public CommonResult<Long> createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) {
+        return success(testDemoService.createTestDemo(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("更新字典类型")
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:update')")    public CommonResult<Boolean> updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) {
+        testDemoService.updateTestDemo(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除字典类型")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:delete')")    public CommonResult<Boolean> deleteTestDemo(@RequestParam("id") Long id) {
+        testDemoService.deleteTestDemo(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得字典类型")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:query')")
+    public CommonResult<TestDemoRespVO> getTestDemo(@RequestParam("id") Long id) {
+        TestDemoDO testDemo = testDemoService.getTestDemo(id);
+        return success(TestDemoConvert.INSTANCE.convert(testDemo));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获得字典类型列表")
+    @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:query')")    public CommonResult<List<TestDemoRespVO>> getTestDemoList(@RequestParam("ids") Collection<Long> ids) {
+        List<TestDemoDO> list = testDemoService.getTestDemoList(ids);
+        return success(TestDemoConvert.INSTANCE.convertList(list));
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("获得字典类型分页")
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:query')")    public CommonResult<PageResult<TestDemoRespVO>> getTestDemoPage(@Valid TestDemoPageReqVO pageVO) {
+        PageResult<TestDemoDO> pageResult = testDemoService.getTestDemoPage(pageVO);
+        return success(TestDemoConvert.INSTANCE.convertPage(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @ApiOperation("导出字典类型 Excel")
+    @PreAuthorize("@ss.hasPermission('tool:test-demo:export')")    @OperateLog(type = EXPORT)
+    public void exportTestDemoExcel(@Valid TestDemoExportReqVO exportReqVO,
+              HttpServletResponse response) throws IOException {
+        List<TestDemoDO> list = testDemoService.getTestDemoList(exportReqVO);
+        // 导出 Excel
+        List<TestDemoExcelVO> datas = TestDemoConvert.INSTANCE.convertList02(list);
+        ExcelUtils.write(response, "字典类型.xls", "数据", TestDemoExcelVO.class, datas);
+    }
+
+}

+ 34 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoBaseVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+/**
+* 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用
+* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
+*/
+@Data
+public class TestDemoBaseVO {
+
+    @ApiModelProperty(value = "名字", required = true)
+    @NotNull(message = "名字不能为空")
+    private String name;
+
+    @ApiModelProperty(value = "状态", required = true)
+    @NotNull(message = "状态不能为空")
+    private Integer status;
+
+    @ApiModelProperty(value = "类型", required = true)
+    @NotNull(message = "类型不能为空")
+    private Integer type;
+
+    @ApiModelProperty(value = "分类", required = true)
+    @NotNull(message = "分类不能为空")
+    private Integer category;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+}

+ 14 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoCreateReqVO.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("管理后台 - 字典类型创建 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class TestDemoCreateReqVO extends TestDemoBaseVO {
+
+}

+ 38 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExcelVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+/**
+ * 字典类型 Excel VO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class TestDemoExcelVO {
+
+    @ExcelProperty("编号")
+    private Long id;
+
+    @ExcelProperty("名字")
+    private String name;
+
+    @ExcelProperty("状态")
+    private Integer status;
+
+    @ExcelProperty("类型")
+    private Integer type;
+
+    @ExcelProperty("分类")
+    private Integer category;
+
+    @ExcelProperty("备注")
+    private String remark;
+
+    @ExcelProperty("创建时间")
+    private Date createTime;
+
+}

+ 38 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoExportReqVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel(value = "管理后台 - 字典类型 Excel 导出 Request VO", description = "参数和 TestDemoPageReqVO 是一致的")
+@Data
+public class TestDemoExportReqVO {
+
+    @ApiModelProperty(value = "名字")
+    private String name;
+
+    @ApiModelProperty(value = "状态")
+    private Integer status;
+
+    @ApiModelProperty(value = "类型")
+    private Integer type;
+
+    @ApiModelProperty(value = "分类")
+    private Integer category;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 40 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoPageReqVO.java

@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("管理后台 - 字典类型分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class TestDemoPageReqVO extends PageParam {
+
+    @ApiModelProperty(value = "名字")
+    private String name;
+
+    @ApiModelProperty(value = "状态")
+    private Integer status;
+
+    @ApiModelProperty(value = "类型")
+    private Integer type;
+
+    @ApiModelProperty(value = "分类")
+    private Integer category;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "开始创建时间")
+    private Date beginCreateTime;
+
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ApiModelProperty(value = "结束创建时间")
+    private Date endCreateTime;
+
+}

+ 19 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoRespVO.java

@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+
+@ApiModel("管理后台 - 字典类型 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class TestDemoRespVO extends TestDemoBaseVO {
+
+    @ApiModelProperty(value = "编号", required = true)
+    private Long id;
+
+    @ApiModelProperty(value = "创建时间", required = true)
+    private Date createTime;
+
+}

+ 18 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/controller/admin/test/vo/TestDemoUpdateReqVO.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.tool.controller.admin.test.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.annotations.*;
+import javax.validation.constraints.*;
+
+@ApiModel("管理后台 - 字典类型更新 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class TestDemoUpdateReqVO extends TestDemoBaseVO {
+
+    @ApiModelProperty(value = "编号", required = true)
+    @NotNull(message = "编号不能为空")
+    private Long id;
+
+}

+ 34 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/convert/test/TestDemoConvert.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.tool.convert.test;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*;
+import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
+
+/**
+ * 字典类型 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface TestDemoConvert {
+
+    TestDemoConvert INSTANCE = Mappers.getMapper(TestDemoConvert.class);
+
+    TestDemoDO convert(TestDemoCreateReqVO bean);
+
+    TestDemoDO convert(TestDemoUpdateReqVO bean);
+
+    TestDemoRespVO convert(TestDemoDO bean);
+
+    List<TestDemoRespVO> convertList(List<TestDemoDO> list);
+
+    PageResult<TestDemoRespVO> convertPage(PageResult<TestDemoDO> page);
+
+    List<TestDemoExcelVO> convertList02(List<TestDemoDO> list);
+
+}

+ 70 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/dataobject/test/TestDemoDO.java

@@ -0,0 +1,70 @@
+package cn.iocoder.yudao.module.tool.dal.dataobject.test;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.util.Date;
+
+/**
+ * 字典类型 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("tool_test_demo")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TestDemoDO extends BaseDO {
+
+    /**
+     * 编号
+     */
+    @TableId
+    private Long id;
+    /**
+     * 名字
+     */
+    private String name;
+    /**
+     * 状态
+     */
+    private Integer status;
+    /**
+     * 类型
+     */
+    private Integer type;
+    /**
+     * 分类
+     */
+    private Integer category;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 创建者
+     */
+    private String creator;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 更新者
+     */
+    private String updater;
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+    /**
+     * 是否删除
+     */
+    private Boolean deleted;
+
+}

+ 42 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/dal/mysql/test/TestDemoMapper.java

@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.tool.dal.mysql.test;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*;
+
+/**
+ * 字典类型 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface TestDemoMapper extends BaseMapperX<TestDemoDO> {
+
+    default PageResult<TestDemoDO> selectPage(TestDemoPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<TestDemoDO>()
+                .likeIfPresent(TestDemoDO::getName, reqVO.getName())
+                .eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(TestDemoDO::getType, reqVO.getType())
+                .eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory())
+                .eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc(TestDemoDO::getId));
+    }
+
+    default List<TestDemoDO> selectList(TestDemoExportReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<TestDemoDO>()
+                .likeIfPresent(TestDemoDO::getName, reqVO.getName())
+                .eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(TestDemoDO::getType, reqVO.getType())
+                .eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory())
+                .eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
+                .orderByDesc(TestDemoDO::getId));
+    }
+
+}

+ 6 - 6
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenEngine.java

@@ -79,9 +79,9 @@ public class CodegenEngine {
                     javaModuleImplMainFilePath("service/${table.businessName}/${table.className}Service"))
             // Java module-impl Test
             .put(javaTemplatePath("test/serviceTest"),
-                    javaModuleImplTestFilePath("service/${table.businessName}/${table.className}ServiceTest"))
+                    javaModuleImplTestFilePath("service/${table.businessName}/${table.className}ServiceImplTest"))
             // Java module-api Main
-            .put(javaTemplatePath("enums/errorcode"), javaModuleApiMainFilePath("enums/ErrorCodeConstants"))
+            .put(javaTemplatePath("enums/errorcode"), javaModuleApiMainFilePath("enums/ErrorCodeConstants_手动操作"))
             // Vue
             .put(vueTemplatePath("views/index.vue"),
                     vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue"))
@@ -158,11 +158,11 @@ public class CodegenEngine {
 
         // 如果多租户,则进行覆盖 DB 独有字段
         if (CollectionUtils.findFirst(columns, column -> column.getColumnName().equals(CodegenBuilder.TENANT_ID_FIELD)) != null) {
-            globalBindingMap.put("BaseDOClassName", TenantBaseDO.class.getName());
-            globalBindingMap.put("BaseDOClassName_simple", TenantBaseDO.class.getSimpleName());
+            bindingMap.put("BaseDOClassName", TenantBaseDO.class.getName());
+            bindingMap.put("BaseDOClassName_simple", TenantBaseDO.class.getSimpleName());
         } else {
-            globalBindingMap.put("BaseDOClassName", BaseDO.class.getName());
-            globalBindingMap.put("BaseDOClassName_simple", BaseDO.class.getSimpleName());
+            bindingMap.put("BaseDOClassName", BaseDO.class.getName());
+            bindingMap.put("BaseDOClassName_simple", BaseDO.class.getSimpleName());
         }
 
         // 执行生成

+ 70 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoService.java

@@ -0,0 +1,70 @@
+package cn.iocoder.yudao.module.tool.service.test;
+
+import java.util.*;
+import javax.validation.*;
+import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*;
+import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+/**
+ * 字典类型 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface TestDemoService {
+
+    /**
+     * 创建字典类型
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createTestDemo(@Valid TestDemoCreateReqVO createReqVO);
+
+    /**
+     * 更新字典类型
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateTestDemo(@Valid TestDemoUpdateReqVO updateReqVO);
+
+    /**
+     * 删除字典类型
+     *
+     * @param id 编号
+     */
+    void deleteTestDemo(Long id);
+
+    /**
+     * 获得字典类型
+     *
+     * @param id 编号
+     * @return 字典类型
+     */
+    TestDemoDO getTestDemo(Long id);
+
+    /**
+     * 获得字典类型列表
+     *
+     * @param ids 编号
+     * @return 字典类型列表
+     */
+    List<TestDemoDO> getTestDemoList(Collection<Long> ids);
+
+    /**
+     * 获得字典类型分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 字典类型分页
+     */
+    PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO);
+
+    /**
+     * 获得字典类型列表, 用于 Excel 导出
+     *
+     * @param exportReqVO 查询条件
+     * @return 字典类型列表
+     */
+    List<TestDemoDO> getTestDemoList(TestDemoExportReqVO exportReqVO);
+
+}

+ 82 - 0
yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImpl.java

@@ -0,0 +1,82 @@
+package cn.iocoder.yudao.module.tool.service.test;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*;
+import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import cn.iocoder.yudao.module.tool.convert.test.TestDemoConvert;
+import cn.iocoder.yudao.module.tool.dal.mysql.test.TestDemoMapper;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants.*;
+
+/**
+ * 字典类型 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class TestDemoServiceImpl implements TestDemoService {
+
+    @Resource
+    private TestDemoMapper testDemoMapper;
+
+    @Override
+    public Long createTestDemo(TestDemoCreateReqVO createReqVO) {
+        // 插入
+        TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO);
+        testDemoMapper.insert(testDemo);
+        // 返回
+        return testDemo.getId();
+    }
+
+    @Override
+    public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) {
+        // 校验存在
+        this.validateTestDemoExists(updateReqVO.getId());
+        // 更新
+        TestDemoDO updateObj = TestDemoConvert.INSTANCE.convert(updateReqVO);
+        testDemoMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteTestDemo(Long id) {
+        // 校验存在
+        this.validateTestDemoExists(id);
+        // 删除
+        testDemoMapper.deleteById(id);
+    }
+
+    private void validateTestDemoExists(Long id) {
+        if (testDemoMapper.selectById(id) == null) {
+            throw exception(TEST_DEMO_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public TestDemoDO getTestDemo(Long id) {
+        return testDemoMapper.selectById(id);
+    }
+
+    @Override
+    public List<TestDemoDO> getTestDemoList(Collection<Long> ids) {
+        return testDemoMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public PageResult<TestDemoDO> getTestDemoPage(TestDemoPageReqVO pageReqVO) {
+        return testDemoMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<TestDemoDO> getTestDemoList(TestDemoExportReqVO exportReqVO) {
+        return testDemoMapper.selectList(exportReqVO);
+    }
+
+}

+ 187 - 0
yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImplTest.java

@@ -0,0 +1,187 @@
+package cn.iocoder.yudao.module.tool.service.test;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+
+import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest;
+import cn.iocoder.yudao.module.tool.controller.admin.test.vo.*;
+import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
+import cn.iocoder.yudao.module.tool.dal.mysql.test.TestDemoMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import javax.annotation.Resource;
+import org.springframework.context.annotation.Import;
+import java.util.*;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+* {@link TestDemoServiceImpl} 的单元测试类
+*
+* @author 芋道源码
+*/
+@Import(TestDemoServiceImpl.class)
+public class TestDemoServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private TestDemoServiceImpl testDemoService;
+
+    @Resource
+    private TestDemoMapper testDemoMapper;
+
+    @Test
+    public void testCreateTestDemo_success() {
+        // 准备参数
+        TestDemoCreateReqVO reqVO = randomPojo(TestDemoCreateReqVO.class);
+
+        // 调用
+        Long testDemoId = testDemoService.createTestDemo(reqVO);
+        // 断言
+        assertNotNull(testDemoId);
+        // 校验记录的属性是否正确
+        TestDemoDO testDemo = testDemoMapper.selectById(testDemoId);
+        assertPojoEquals(reqVO, testDemo);
+    }
+
+    @Test
+    public void testUpdateTestDemo_success() {
+        // mock 数据
+        TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class);
+        testDemoMapper.insert(dbTestDemo);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        TestDemoUpdateReqVO reqVO = randomPojo(TestDemoUpdateReqVO.class, o -> {
+            o.setId(dbTestDemo.getId()); // 设置更新的 ID
+        });
+
+        // 调用
+        testDemoService.updateTestDemo(reqVO);
+        // 校验是否更新正确
+        TestDemoDO testDemo = testDemoMapper.selectById(reqVO.getId()); // 获取最新的
+        assertPojoEquals(reqVO, testDemo);
+    }
+
+    @Test
+    public void testUpdateTestDemo_notExists() {
+        // 准备参数
+        TestDemoUpdateReqVO reqVO = randomPojo(TestDemoUpdateReqVO.class);
+
+        // 调用, 并断言异常
+        assertServiceException(() -> testDemoService.updateTestDemo(reqVO), TEST_DEMO_NOT_EXISTS);
+    }
+
+    @Test
+    public void testDeleteTestDemo_success() {
+        // mock 数据
+        TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class);
+        testDemoMapper.insert(dbTestDemo);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        Long id = dbTestDemo.getId();
+
+        // 调用
+        testDemoService.deleteTestDemo(id);
+       // 校验数据不存在了
+       assertNull(testDemoMapper.selectById(id));
+    }
+
+    @Test
+    public void testDeleteTestDemo_notExists() {
+        // 准备参数
+        Long id = randomLongId();
+
+        // 调用, 并断言异常
+        assertServiceException(() -> testDemoService.deleteTestDemo(id), TEST_DEMO_NOT_EXISTS);
+    }
+
+    @Test // TODO 请修改 null 为需要的值
+    public void testGetTestDemoPage() {
+       // mock 数据
+       TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class, o -> { // 等会查询到
+           o.setName(null);
+           o.setStatus(null);
+           o.setType(null);
+           o.setCategory(null);
+           o.setRemark(null);
+           o.setCreateTime(null);
+       });
+       testDemoMapper.insert(dbTestDemo);
+       // 测试 name 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setName(null)));
+       // 测试 status 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setStatus(null)));
+       // 测试 type 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setType(null)));
+       // 测试 category 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCategory(null)));
+       // 测试 remark 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark(null)));
+       // 测试 createTime 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(null)));
+       // 准备参数
+       TestDemoPageReqVO reqVO = new TestDemoPageReqVO();
+       reqVO.setName(null);
+       reqVO.setStatus(null);
+       reqVO.setType(null);
+       reqVO.setCategory(null);
+       reqVO.setRemark(null);
+       reqVO.setBeginCreateTime(null);
+       reqVO.setEndCreateTime(null);
+
+       // 调用
+       PageResult<TestDemoDO> pageResult = testDemoService.getTestDemoPage(reqVO);
+       // 断言
+       assertEquals(1, pageResult.getTotal());
+       assertEquals(1, pageResult.getList().size());
+       assertPojoEquals(dbTestDemo, pageResult.getList().get(0));
+    }
+
+    @Test // TODO 请修改 null 为需要的值
+    public void testGetTestDemoList() {
+       // mock 数据
+       TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class, o -> { // 等会查询到
+           o.setName(null);
+           o.setStatus(null);
+           o.setType(null);
+           o.setCategory(null);
+           o.setRemark(null);
+           o.setCreateTime(null);
+       });
+       testDemoMapper.insert(dbTestDemo);
+       // 测试 name 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setName(null)));
+       // 测试 status 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setStatus(null)));
+       // 测试 type 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setType(null)));
+       // 测试 category 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCategory(null)));
+       // 测试 remark 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark(null)));
+       // 测试 createTime 不匹配
+       testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(null)));
+       // 准备参数
+       TestDemoExportReqVO reqVO = new TestDemoExportReqVO();
+       reqVO.setName(null);
+       reqVO.setStatus(null);
+       reqVO.setType(null);
+       reqVO.setCategory(null);
+       reqVO.setRemark(null);
+       reqVO.setBeginCreateTime(null);
+       reqVO.setEndCreateTime(null);
+
+       // 调用
+       List<TestDemoDO> list = testDemoService.getTestDemoList(reqVO);
+       // 断言
+       assertEquals(1, list.size());
+       assertPojoEquals(dbTestDemo, list.get(0));
+    }
+
+}

+ 39 - 0
yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/test/BaseDbUnitTest.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.tool.test;
+
+import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
+import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.jdbc.Sql;
+
+/**
+ * 依赖内存 DB 的单元测试
+ *
+ * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法
+ *
+ * @author 芋道源码
+ */
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class)
+@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件
+@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB
+public class BaseDbUnitTest {
+
+    @Import({
+            // DB 配置类
+            YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类
+            DataSourceAutoConfiguration.class, // Spring DB 自动配置类
+            DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类
+            DruidDataSourceAutoConfigure.class, // Druid 自动配置类
+            // MyBatis 配置类
+            YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类
+            MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类
+    })
+    public static class Application {
+    }
+
+}

+ 0 - 1
yudao-ui-admin/src/api/tool/testDemo.js

@@ -18,7 +18,6 @@ export function updateTestDemo(data) {
   })
 }
 
-
 // 删除字典类型
 export function deleteTestDemo(id) {
   return request({

+ 41 - 69
yudao-ui-admin/src/views/tool/testDemo/index.vue

@@ -8,21 +8,16 @@
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
-          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
-                     :key="dict.value" :label="dict.label" :value="dict.value"/>
+          <el-option label="请选择字典生成" value="" />
         </el-select>
       </el-form-item>
       <el-form-item label="类型" prop="type">
         <el-select v-model="queryParams.type" placeholder="请选择类型" clearable size="small">
-          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYSTEM_OPERATE_TYPE)"
-                     :key="dict.value" :label="dict.label" :value="dict.value"/>
+          <el-option label="请选择字典生成" value="" />
         </el-select>
       </el-form-item>
       <el-form-item label="分类" prop="category">
-        <el-select v-model="queryParams.category" placeholder="请选择分类" clearable size="small">
-          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE)"
-                     :key="dict.value" :label="dict.label" :value="dict.value"/>
-        </el-select>
+        <el-input v-model="queryParams.category" placeholder="请输入分类" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="备注" prop="remark">
         <el-input v-model="queryParams.remark" placeholder="请输入备注" clearable size="small" @keyup.enter.native="handleQuery"/>
@@ -31,11 +26,6 @@
         <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
                         type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
       </el-form-item>
-      <el-form-item label="是否删除" prop="deleted">
-        <el-select v-model="queryParams.deleted" placeholder="请选择是否删除" clearable size="small">
-          <el-option label="请选择字典生成" value="" />
-        </el-select>
-      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -59,25 +49,13 @@
     <el-table v-loading="loading" :data="list">
       <el-table-column label="编号" align="center" prop="id" />
       <el-table-column label="名字" align="center" prop="name" />
-      <el-table-column label="状态" align="center" prop="status">
-        <template slot-scope="scope">
-          <span>{{ getDictDataLabel(DICT_TYPE.COMMON_STATUS, scope.row.status) }}</span>
-        </template>
-      </el-table-column>>
-      <el-table-column label="类型" align="center" prop="type">
-        <template slot-scope="scope">
-          <span>{{ getDictDataLabel(DICT_TYPE.SYSTEM_OPERATE_TYPE, scope.row.type) }}</span>
-        </template>
-      </el-table-column>>
-      <el-table-column label="分类" align="center" prop="category">
-        <template slot-scope="scope">
-          <span>{{ getDictDataLabel(DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE, scope.row.category) }}</span>
-        </template>
-      </el-table-column>>
+      <el-table-column label="状态" align="center" prop="status" />
+      <el-table-column label="类型" align="center" prop="type" />
+      <el-table-column label="分类" align="center" prop="category" />
       <el-table-column label="备注" align="center" prop="remark" />
       <el-table-column label="创建时间" align="center" prop="createTime" width="180">
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
+          <span>{{ parseTime(scope.row.createTime) }}</span>
         </template>
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -99,23 +77,18 @@
         <el-form-item label="名字" prop="name">
           <el-input v-model="form.name" placeholder="请输入名字" />
         </el-form-item>
-        <el-form-item label="状态">
+        <el-form-item label="状态" prop="status">
           <el-radio-group v-model="form.status">
-            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
-                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
+            <el-radio label="1">请选择字典生成</el-radio>
           </el-radio-group>
         </el-form-item>
         <el-form-item label="类型" prop="type">
           <el-select v-model="form.type" placeholder="请选择类型">
-            <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYSTEM_OPERATE_TYPE)"
-                       :key="dict.value" :label="dict.label" :value="parseInt(dict.value)" />
+            <el-option label="请选择字典生成" value="" />
           </el-select>
         </el-form-item>
-        <el-form-item label="分类">
-          <el-radio-group v-model="form.category">
-            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_REDIS_TIMEOUT_TYPE)"
-                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
-          </el-radio-group>
+        <el-form-item label="分类" prop="category">
+          <el-input v-model="form.category" placeholder="请输入分类" />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" placeholder="请输入备注" />
@@ -144,7 +117,7 @@ export default {
       showSearch: true,
       // 总条数
       total: 0,
-      // 测试示例列表
+      // 字典类型列表
       list: [],
       // 弹出层标题
       title: "",
@@ -160,7 +133,6 @@ export default {
         type: null,
         category: null,
         remark: null,
-        deleted: null,
       },
       // 表单参数
       form: {},
@@ -180,6 +152,7 @@ export default {
     /** 查询列表 */
     getList() {
       this.loading = true;
+      // 处理查询参数
       let params = {...this.queryParams};
       this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
       // 执行查询
@@ -189,12 +162,12 @@ export default {
         this.loading = false;
       });
     },
-    // 取消按钮
+    /** 取消按钮 */
     cancel() {
       this.open = false;
       this.reset();
     },
-    // 表单重置
+    /** 表单重置 */
     reset() {
       this.form = {
         id: undefined,
@@ -203,11 +176,6 @@ export default {
         type: undefined,
         category: undefined,
         remark: undefined,
-        createBy: undefined,
-        createTime: undefined,
-        updateBy: undefined,
-        updateTime: undefined,
-        deleted: undefined,
       };
       this.resetForm("form");
     },
@@ -226,7 +194,7 @@ export default {
     handleAdd() {
       this.reset();
       this.open = true;
-      this.title = "添加测试示例";
+      this.title = "添加字典类型";
     },
     /** 修改按钮操作 */
     handleUpdate(row) {
@@ -235,7 +203,7 @@ export default {
       getTestDemo(id).then(response => {
         this.form = response.data;
         this.open = true;
-        this.title = "修改测试示例";
+        this.title = "修改字典类型";
       });
     },
     /** 提交按钮 */
@@ -264,30 +232,34 @@ export default {
     /** 删除按钮操作 */
     handleDelete(row) {
       const id = row.id;
-      this.$confirm('是否确认删除测试示例编号为"' + id + '"的数据项?', "警告", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }).then(function() {
-        return deleteTestDemo(id);
-      }).then(() => {
-        this.getList();
-        this.msgSuccess("删除成功");
-      })
+      this.$confirm('是否确认删除字典类型编号为"' + id + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return deleteTestDemo(id);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        })
     },
     /** 导出按钮操作 */
     handleExport() {
+      // 处理查询参数
       let params = {...this.queryParams};
+      params.pageNo = undefined;
+      params.pageSize = undefined;
       this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
-      this.$confirm('是否确认导出所有测试示例数据项?', "警告", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }).then(function() {
-        return exportTestDemoExcel(params);
-      }).then(response => {
-        this.downloadExcel(response, '测试示例.xls');
-      })
+      // 执行导出
+      this.$confirm('是否确认导出所有字典类型数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportTestDemoExcel(params);
+        }).then(response => {
+          this.downloadExcel(response, '字典类型.xls');
+        })
     }
   }
 };