Commit ba34e3c98752acceb8ef18ec8d98a3740be81540
1 parent
08f64da8
优化代码生成器的展示
Showing
6 changed files
with
104 additions
and
35 deletions
ruoyi-ui/src/views/tool/codegen/index.vue
| ... | ... | @@ -77,12 +77,22 @@ |
| 77 | 77 | <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/> |
| 78 | 78 | |
| 79 | 79 | <!-- 预览界面 --> |
| 80 | - <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body> | |
| 81 | - <el-tabs tab-position="left" v-model="preview.activeName"> | |
| 82 | - <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" :name="item.filePath" :key="item.filePath"> | |
| 83 | - <pre><code class="hljs" v-html="highlightedCode(item)"></code></pre> | |
| 84 | - </el-tab-pane> | |
| 85 | - </el-tabs> | |
| 80 | + <el-dialog :title="preview.title" :visible.sync="preview.open" width="90%" top="5vh" append-to-body> | |
| 81 | + | |
| 82 | + <el-row> | |
| 83 | + <el-col :span="7"> | |
| 84 | + <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all | |
| 85 | + @node-click="handleNodeClick"/> | |
| 86 | + </el-col> | |
| 87 | + <el-col :span="17"> | |
| 88 | + <el-tabs v-model="preview.activeName"> | |
| 89 | + <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" | |
| 90 | + :name="item.filePath" :key="item.filePath"> | |
| 91 | + <pre><code class="hljs" v-html="highlightedCode(item)"></code></pre> | |
| 92 | + </el-tab-pane> | |
| 93 | + </el-tabs> | |
| 94 | + </el-col> | |
| 95 | + </el-row> | |
| 86 | 96 | </el-dialog> |
| 87 | 97 | |
| 88 | 98 | <!-- 基于 DB 导入 --> |
| ... | ... | @@ -154,8 +164,9 @@ export default { |
| 154 | 164 | preview: { |
| 155 | 165 | open: false, |
| 156 | 166 | title: "代码预览", |
| 167 | + fileTree: [], | |
| 157 | 168 | data: {}, |
| 158 | - activeName: "domain.java" | |
| 169 | + activeName: "", | |
| 159 | 170 | }, |
| 160 | 171 | // 基于 SQL 导入 |
| 161 | 172 | importSQL: { |
| ... | ... | @@ -243,6 +254,11 @@ export default { |
| 243 | 254 | handlePreview(row) { |
| 244 | 255 | previewCodegen(row.id).then(response => { |
| 245 | 256 | this.preview.data = response.data; |
| 257 | + let files = this.handleFiles(response.data); | |
| 258 | + console.log(files) | |
| 259 | + this.preview.fileTree = this.handleTree(files, "id", "parentId", "children", | |
| 260 | + "/"); // "/" 为根节点 | |
| 261 | + console.log(this.preview.fileTree) | |
| 246 | 262 | this.preview.activeName = response.data[0].filePath; |
| 247 | 263 | this.preview.open = true; |
| 248 | 264 | }); |
| ... | ... | @@ -255,6 +271,36 @@ export default { |
| 255 | 271 | const result = hljs.highlight(language, item.code || "", true); |
| 256 | 272 | return result.value || ' '; |
| 257 | 273 | }, |
| 274 | + /** 生成 files 目录 **/ | |
| 275 | + handleFiles(datas) { | |
| 276 | + let exists = {}; // key:file 的 id;value:true | |
| 277 | + let files = []; | |
| 278 | + // 遍历每个元素 | |
| 279 | + for (const data of datas) { | |
| 280 | + let paths = data.filePath.split('/'); | |
| 281 | + let fullPath = ''; // 从头开始的路径,用于生成 id | |
| 282 | + for (let i = 0; i < paths.length; i++) { | |
| 283 | + // 已经添加大奥 files 中,则跳过 | |
| 284 | + let oldFullPath = fullPath; | |
| 285 | + fullPath = fullPath.length === 0 ? paths[i] : fullPath + '/' + paths[i]; | |
| 286 | + if (exists[fullPath]) { | |
| 287 | + continue; | |
| 288 | + } | |
| 289 | + // 添加到 files 中 | |
| 290 | + exists[fullPath] = true; | |
| 291 | + files.push({ | |
| 292 | + id: fullPath, | |
| 293 | + label: paths[i], | |
| 294 | + parentId: oldFullPath || '/' // "/" 为根节点 | |
| 295 | + }); | |
| 296 | + } | |
| 297 | + } | |
| 298 | + return files; | |
| 299 | + }, | |
| 300 | + /** 节点单击事件 **/ | |
| 301 | + handleNodeClick(data) { | |
| 302 | + this.preview.activeName = data.id; | |
| 303 | + }, | |
| 258 | 304 | /** 修改按钮操作 */ |
| 259 | 305 | handleEditTable(row) { |
| 260 | 306 | const tableId = row.id; | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/config/InfConfigDO.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.infra.dal.dataobject.config; |
| 3 | 3 | import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; |
| 4 | 4 | import cn.iocoder.dashboard.modules.infra.enums.config.InfConfigTypeEnum; |
| 5 | 5 | import com.baomidou.mybatisplus.annotation.TableField; |
| 6 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 6 | 7 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | 8 | import lombok.Data; |
| 8 | 9 | import lombok.EqualsAndHashCode; |
| ... | ... | @@ -22,6 +23,7 @@ public class InfConfigDO extends BaseDO { |
| 22 | 23 | /** |
| 23 | 24 | * 参数主键 |
| 24 | 25 | */ |
| 26 | + @TableId | |
| 25 | 27 | private Long id; |
| 26 | 28 | /** |
| 27 | 29 | * 参数分组 | ... | ... |
src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceImplTest.java
| ... | ... | @@ -3,21 +3,22 @@ package cn.iocoder.dashboard.modules.infra.service.config; |
| 3 | 3 | import cn.iocoder.dashboard.BaseSpringBootUnitTest; |
| 4 | 4 | import cn.iocoder.dashboard.common.exception.ServiceException; |
| 5 | 5 | import cn.iocoder.dashboard.modules.infra.controller.config.vo.InfConfigCreateReqVO; |
| 6 | +import cn.iocoder.dashboard.modules.infra.controller.config.vo.InfConfigUpdateReqVO; | |
| 6 | 7 | import cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO; |
| 7 | 8 | import cn.iocoder.dashboard.modules.infra.dal.mysql.config.InfConfigMapper; |
| 8 | 9 | import cn.iocoder.dashboard.modules.infra.enums.config.InfConfigTypeEnum; |
| 9 | 10 | import cn.iocoder.dashboard.modules.infra.mq.producer.config.InfConfigProducer; |
| 10 | 11 | import cn.iocoder.dashboard.modules.infra.service.config.impl.InfConfigServiceImpl; |
| 11 | -import cn.iocoder.dashboard.util.AssertUtils; | |
| 12 | 12 | import org.junit.jupiter.api.Test; |
| 13 | 13 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 14 | 14 | |
| 15 | 15 | import javax.annotation.Resource; |
| 16 | +import java.util.function.Consumer; | |
| 16 | 17 | |
| 17 | 18 | import static cn.hutool.core.util.RandomUtil.randomEle; |
| 18 | 19 | import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.CONFIG_KEY_DUPLICATE; |
| 19 | -import static cn.iocoder.dashboard.util.RandomUtils.randomInfConfigCreateReqVO; | |
| 20 | -import static cn.iocoder.dashboard.util.RandomUtils.randomInfConfigDO; | |
| 20 | +import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals; | |
| 21 | +import static cn.iocoder.dashboard.util.RandomUtils.randomPojo; | |
| 21 | 22 | import static org.junit.jupiter.api.Assertions.*; |
| 22 | 23 | import static org.mockito.Mockito.times; |
| 23 | 24 | import static org.mockito.Mockito.verify; |
| ... | ... | @@ -35,17 +36,17 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { |
| 35 | 36 | |
| 36 | 37 | @Test |
| 37 | 38 | public void testCreateConfig_success() { |
| 38 | - // 入参 | |
| 39 | + // 准备参数 | |
| 39 | 40 | InfConfigCreateReqVO reqVO = randomInfConfigCreateReqVO(); |
| 40 | 41 | // mock |
| 41 | 42 | |
| 42 | 43 | // 调用 |
| 43 | 44 | Long configId = configService.createConfig(reqVO); |
| 44 | - // 校验 | |
| 45 | + // 断言 | |
| 45 | 46 | assertNotNull(configId); |
| 46 | 47 | // 校验记录的属性是否正确 |
| 47 | 48 | InfConfigDO config = configMapper.selectById(configId); |
| 48 | - AssertUtils.assertEquals(reqVO, config); | |
| 49 | + assertPojoEquals(reqVO, config); | |
| 49 | 50 | assertEquals(InfConfigTypeEnum.CUSTOM.getType(), config.getType()); |
| 50 | 51 | // 校验调用 |
| 51 | 52 | verify(configProducer, times(1)).sendConfigRefreshMessage(); |
| ... | ... | @@ -53,18 +54,50 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { |
| 53 | 54 | |
| 54 | 55 | @Test |
| 55 | 56 | public void testCreateConfig_keyDuplicate() { |
| 56 | - // 入参 | |
| 57 | + // 准备参数 | |
| 57 | 58 | InfConfigCreateReqVO reqVO = randomInfConfigCreateReqVO(); |
| 58 | 59 | // mock 数据 |
| 59 | - configMapper.insert(randomInfConfigDO(o -> { | |
| 60 | - o.setKey(reqVO.getKey()); // @Sql:插入一条重复的 key | |
| 61 | - o.setType(randomEle(InfConfigTypeEnum.values()).getType()); | |
| 60 | + configMapper.insert(randomInfConfigDO(o -> { // @Sql | |
| 61 | + o.setKey(reqVO.getKey()); // 模拟 key 重复 | |
| 62 | 62 | })); |
| 63 | 63 | |
| 64 | 64 | // 调用 |
| 65 | 65 | ServiceException serviceException = assertThrows(ServiceException.class, () -> configService.createConfig(reqVO)); |
| 66 | 66 | // 断言 |
| 67 | - AssertUtils.assertEquals(CONFIG_KEY_DUPLICATE, serviceException); | |
| 67 | + assertPojoEquals(CONFIG_KEY_DUPLICATE, serviceException); | |
| 68 | + } | |
| 69 | + | |
| 70 | + @Test | |
| 71 | + public void testUpdateConfig_success() { | |
| 72 | + // 准备参数 | |
| 73 | + InfConfigUpdateReqVO reqVO = randomInfConfigUpdateReqVO(); | |
| 74 | + // mock 数据 | |
| 75 | + configMapper.insert(randomInfConfigDO(o -> o.setId(reqVO.getId())));// @Sql: 先插入出一条存在的数据 | |
| 76 | + | |
| 77 | + // 调用 | |
| 78 | + configService.updateConfig(reqVO); | |
| 79 | + // 校验是否更新正确 | |
| 80 | + InfConfigDO config = configMapper.selectById(reqVO.getId()); // 获取最新的 | |
| 81 | + assertPojoEquals(reqVO, config); | |
| 82 | + // 校验调用 | |
| 83 | + verify(configProducer, times(1)).sendConfigRefreshMessage(); | |
| 84 | + } | |
| 85 | + | |
| 86 | + // ========== 随机对象 ========== | |
| 87 | + | |
| 88 | + @SafeVarargs | |
| 89 | + private static InfConfigDO randomInfConfigDO(Consumer<InfConfigDO>... consumers) { | |
| 90 | + InfConfigDO config = randomPojo(InfConfigDO.class, consumers); | |
| 91 | + config.setType(randomEle(InfConfigTypeEnum.values()).getType()); | |
| 92 | + return config; | |
| 93 | + } | |
| 94 | + | |
| 95 | + private static InfConfigCreateReqVO randomInfConfigCreateReqVO() { | |
| 96 | + return randomPojo(InfConfigCreateReqVO.class); | |
| 97 | + } | |
| 98 | + | |
| 99 | + private static InfConfigUpdateReqVO randomInfConfigUpdateReqVO() { | |
| 100 | + return randomPojo(InfConfigUpdateReqVO.class); | |
| 68 | 101 | } |
| 69 | 102 | |
| 70 | 103 | } | ... | ... |
src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java
| ... | ... | @@ -42,7 +42,7 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { |
| 42 | 42 | // 调用 |
| 43 | 43 | LoginUser loginUser = (LoginUser) authService.loadUserByUsername(username); |
| 44 | 44 | // 校验 |
| 45 | - AssertUtils.assertEquals(user, loginUser, "updateTime"); | |
| 45 | + AssertUtils.assertPojoEquals(user, loginUser, "updateTime"); | |
| 46 | 46 | assertNull(loginUser.getRoleIds()); // 此时不会加载角色,所以是空的 |
| 47 | 47 | } |
| 48 | 48 | |
| ... | ... | @@ -73,7 +73,7 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { |
| 73 | 73 | // 调用 |
| 74 | 74 | LoginUser loginUser = authService.mockLogin(userId); |
| 75 | 75 | // 断言 |
| 76 | - AssertUtils.assertEquals(user, loginUser, "updateTime"); | |
| 76 | + AssertUtils.assertPojoEquals(user, loginUser, "updateTime"); | |
| 77 | 77 | assertEquals(roleIds, loginUser.getRoleIds()); |
| 78 | 78 | } |
| 79 | 79 | ... | ... |
src/test/java/cn/iocoder/dashboard/util/AssertUtils.java
| ... | ... | @@ -25,7 +25,7 @@ public class AssertUtils { |
| 25 | 25 | * @param actual 实际对象 |
| 26 | 26 | * @param ignoreFields 忽略的属性数组 |
| 27 | 27 | */ |
| 28 | - public static void assertEquals(Object expected, Object actual, String... ignoreFields) { | |
| 28 | + public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) { | |
| 29 | 29 | Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); |
| 30 | 30 | Arrays.stream(expectedFields).forEach(expectedField -> { |
| 31 | 31 | // 如果是忽略的属性,则不进行比对 |
| ... | ... | @@ -52,7 +52,7 @@ public class AssertUtils { |
| 52 | 52 | * @param errorCode 错误码对象 |
| 53 | 53 | * @param serviceException 业务异常 |
| 54 | 54 | */ |
| 55 | - public static void assertEquals(ErrorCode errorCode, ServiceException serviceException) { | |
| 55 | + public static void assertPojoEquals(ErrorCode errorCode, ServiceException serviceException) { | |
| 56 | 56 | Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配"); |
| 57 | 57 | Assertions.assertEquals(errorCode.getMessage(), serviceException.getMessage(), "错误提示不匹配"); |
| 58 | 58 | } | ... | ... |
src/test/java/cn/iocoder/dashboard/util/RandomUtils.java
| ... | ... | @@ -2,8 +2,6 @@ package cn.iocoder.dashboard.util; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | 4 | import cn.hutool.core.util.RandomUtil; |
| 5 | -import cn.iocoder.dashboard.modules.infra.controller.config.vo.InfConfigCreateReqVO; | |
| 6 | -import cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO; | |
| 7 | 5 | import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; |
| 8 | 6 | import uk.co.jemos.podam.api.PodamFactory; |
| 9 | 7 | import uk.co.jemos.podam.api.PodamFactoryImpl; |
| ... | ... | @@ -75,17 +73,7 @@ public class RandomUtils { |
| 75 | 73 | } |
| 76 | 74 | |
| 77 | 75 | @SafeVarargs |
| 78 | - public static InfConfigCreateReqVO randomInfConfigCreateReqVO(Consumer<InfConfigCreateReqVO>... consumers) { | |
| 79 | - return randomPojo(InfConfigCreateReqVO.class, consumers); | |
| 80 | - } | |
| 81 | - | |
| 82 | - @SafeVarargs | |
| 83 | - public static InfConfigDO randomInfConfigDO(Consumer<InfConfigDO>... consumers) { | |
| 84 | - return randomPojo(InfConfigDO.class, consumers); | |
| 85 | - } | |
| 86 | - | |
| 87 | - @SafeVarargs | |
| 88 | - private static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) { | |
| 76 | + public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) { | |
| 89 | 77 | T pojo = PODAM_FACTORY.manufacturePojo(clazz); |
| 90 | 78 | // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 |
| 91 | 79 | if (ArrayUtil.isNotEmpty(consumers)) { | ... | ... |