Commit db9bae05b0146835c938a65babf0fd96e93ea64e

Authored by YunaiV
1 parent 8e3d7663

多模块重构 11:代码生成器,优化展示

yudao-module-tool/yudao-module-tool-impl/src/main/java/cn/iocoder/yudao/module/tool/service/codegen/inner/CodegenEngine.java
... ... @@ -229,7 +229,8 @@ public class CodegenEngine {
229 229 }
230 230  
231 231 private static String vueFilePath(String path) {
232   - return "vue/" + path;
  232 + return "yudao-ui-${sceneEnum.basePackage}/" + // 顶级目录
  233 + "src/" + path;
233 234 }
234 235  
235 236 }
... ...
yudao-module-tool/yudao-module-tool-impl/src/test/java/cn/iocoder/yudao/module/tool/service/test/TestDemoServiceImplTest.java deleted
1   -package cn.iocoder.yudao.module.tool.service.test;
2   -
3   -import org.junit.jupiter.api.Test;
4   -import org.springframework.boot.test.mock.mockito.MockBean;
5   -
6   -import javax.annotation.Resource;
7   -
8   -import cn.iocoder.yudao.module.tool.test.BaseDbUnitTest;
9   -import cn.iocoder.yudao.module.tool.controller.app.test.vo.*;
10   -import cn.iocoder.yudao.module.tool.dal.dataobject.test.TestDemoDO;
11   -import cn.iocoder.yudao.module.tool.dal.mysql.test.TestDemoMapper;
12   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
13   -
14   -import javax.annotation.Resource;
15   -import org.springframework.context.annotation.Import;
16   -import java.util.*;
17   -
18   -import static cn.hutool.core.util.RandomUtil.*;
19   -import static cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants.*;
20   -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
21   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
22   -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
23   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
24   -import static org.junit.jupiter.api.Assertions.*;
25   -import static org.mockito.Mockito.*;
26   -
27   -/**
28   -* {@link TestDemoServiceImpl} 的单元测试类
29   -*
30   -* @author 芋道源码
31   -*/
32   -@Import(TestDemoServiceImpl.class)
33   -public class TestDemoServiceImplTest extends BaseDbUnitTest {
34   -
35   - @Resource
36   - private TestDemoServiceImpl testDemoService;
37   -
38   - @Resource
39   - private TestDemoMapper testDemoMapper;
40   -
41   - @Test
42   - public void testCreateTestDemo_success() {
43   - // 准备参数
44   - AppTestDemoCreateReqVO reqVO = randomPojo(AppTestDemoCreateReqVO.class);
45   -
46   - // 调用
47   - Long testDemoId = testDemoService.createTestDemo(reqVO);
48   - // 断言
49   - assertNotNull(testDemoId);
50   - // 校验记录的属性是否正确
51   - TestDemoDO testDemo = testDemoMapper.selectById(testDemoId);
52   - assertPojoEquals(reqVO, testDemo);
53   - }
54   -
55   - @Test
56   - public void testUpdateTestDemo_success() {
57   - // mock 数据
58   - TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class);
59   - testDemoMapper.insert(dbTestDemo);// @Sql: 先插入出一条存在的数据
60   - // 准备参数
61   - AppTestDemoUpdateReqVO reqVO = randomPojo(AppTestDemoUpdateReqVO.class, o -> {
62   - o.setId(dbTestDemo.getId()); // 设置更新的 ID
63   - });
64   -
65   - // 调用
66   - testDemoService.updateTestDemo(reqVO);
67   - // 校验是否更新正确
68   - TestDemoDO testDemo = testDemoMapper.selectById(reqVO.getId()); // 获取最新的
69   - assertPojoEquals(reqVO, testDemo);
70   - }
71   -
72   - @Test
73   - public void testUpdateTestDemo_notExists() {
74   - // 准备参数
75   - AppTestDemoUpdateReqVO reqVO = randomPojo(AppTestDemoUpdateReqVO.class);
76   -
77   - // 调用, 并断言异常
78   - assertServiceException(() -> testDemoService.updateTestDemo(reqVO), TEST_DEMO_NOT_EXISTS);
79   - }
80   -
81   - @Test
82   - public void testDeleteTestDemo_success() {
83   - // mock 数据
84   - TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class);
85   - testDemoMapper.insert(dbTestDemo);// @Sql: 先插入出一条存在的数据
86   - // 准备参数
87   - Long id = dbTestDemo.getId();
88   -
89   - // 调用
90   - testDemoService.deleteTestDemo(id);
91   - // 校验数据不存在了
92   - assertNull(testDemoMapper.selectById(id));
93   - }
94   -
95   - @Test
96   - public void testDeleteTestDemo_notExists() {
97   - // 准备参数
98   - Long id = randomLongId();
99   -
100   - // 调用, 并断言异常
101   - assertServiceException(() -> testDemoService.deleteTestDemo(id), TEST_DEMO_NOT_EXISTS);
102   - }
103   -
104   - @Test // TODO 请修改 null 为需要的值
105   - public void testGetTestDemoPage() {
106   - // mock 数据
107   - TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class, o -> { // 等会查询到
108   - o.setName(null);
109   - o.setStatus(null);
110   - o.setType(null);
111   - o.setCategory(null);
112   - o.setRemark(null);
113   - o.setCreateTime(null);
114   - });
115   - testDemoMapper.insert(dbTestDemo);
116   - // 测试 name 不匹配
117   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setName(null)));
118   - // 测试 status 不匹配
119   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setStatus(null)));
120   - // 测试 type 不匹配
121   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setType(null)));
122   - // 测试 category 不匹配
123   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCategory(null)));
124   - // 测试 remark 不匹配
125   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark(null)));
126   - // 测试 createTime 不匹配
127   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(null)));
128   - // 准备参数
129   - AppTestDemoPageReqVO reqVO = new AppTestDemoPageReqVO();
130   - reqVO.setName(null);
131   - reqVO.setStatus(null);
132   - reqVO.setType(null);
133   - reqVO.setCategory(null);
134   - reqVO.setRemark(null);
135   - reqVO.setBeginCreateTime(null);
136   - reqVO.setEndCreateTime(null);
137   -
138   - // 调用
139   - PageResult<TestDemoDO> pageResult = testDemoService.getTestDemoPage(reqVO);
140   - // 断言
141   - assertEquals(1, pageResult.getTotal());
142   - assertEquals(1, pageResult.getList().size());
143   - assertPojoEquals(dbTestDemo, pageResult.getList().get(0));
144   - }
145   -
146   - @Test // TODO 请修改 null 为需要的值
147   - public void testGetTestDemoList() {
148   - // mock 数据
149   - TestDemoDO dbTestDemo = randomPojo(TestDemoDO.class, o -> { // 等会查询到
150   - o.setName(null);
151   - o.setStatus(null);
152   - o.setType(null);
153   - o.setCategory(null);
154   - o.setRemark(null);
155   - o.setCreateTime(null);
156   - });
157   - testDemoMapper.insert(dbTestDemo);
158   - // 测试 name 不匹配
159   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setName(null)));
160   - // 测试 status 不匹配
161   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setStatus(null)));
162   - // 测试 type 不匹配
163   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setType(null)));
164   - // 测试 category 不匹配
165   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCategory(null)));
166   - // 测试 remark 不匹配
167   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setRemark(null)));
168   - // 测试 createTime 不匹配
169   - testDemoMapper.insert(cloneIgnoreId(dbTestDemo, o -> o.setCreateTime(null)));
170   - // 准备参数
171   - AppTestDemoExportReqVO reqVO = new AppTestDemoExportReqVO();
172   - reqVO.setName(null);
173   - reqVO.setStatus(null);
174   - reqVO.setType(null);
175   - reqVO.setCategory(null);
176   - reqVO.setRemark(null);
177   - reqVO.setBeginCreateTime(null);
178   - reqVO.setEndCreateTime(null);
179   -
180   - // 调用
181   - List<TestDemoDO> list = testDemoService.getTestDemoList(reqVO);
182   - // 断言
183   - assertEquals(1, list.size());
184   - assertPojoEquals(dbTestDemo, list.get(0));
185   - }
186   -
187   -}
yudao-ui-admin/src/views/tool/codegen/index.vue
... ... @@ -61,11 +61,11 @@
61 61 <!-- 预览界面 -->
62 62 <el-dialog :title="preview.title" :visible.sync="preview.open" width="90%" top="5vh" append-to-body>
63 63 <el-row>
64   - <el-col :span="9">
  64 + <el-col :span="7">
65 65 <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all highlight-current
66 66 @node-click="handleNodeClick"/>
67 67 </el-col>
68   - <el-col :span="15">
  68 + <el-col :span="17">
69 69 <el-tabs v-model="preview.activeName">
70 70 <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)"
71 71 :name="item.filePath" :key="item.filePath">
... ... @@ -257,10 +257,45 @@ export default {
257 257 for (const data of datas) {
258 258 let paths = data.filePath.split('/');
259 259 let fullPath = ''; // 从头开始的路径,用于生成 id
  260 + // 特殊处理 java 文件
  261 + if (paths[paths.length - 1].indexOf('.java') >= 0) {
  262 + let newPaths = [];
  263 + for (let i = 0; i < paths.length; i++) {
  264 + let path = paths[i];
  265 + if (path !== 'java') {
  266 + newPaths.push(path);
  267 + continue;
  268 + }
  269 + newPaths.push(path);
  270 + // 特殊处理中间的 package,进行合并
  271 + let tmp = undefined;
  272 + while (i < paths.length) {
  273 + path = paths[i + 1];
  274 + if (path === 'controller'
  275 + || path === 'convert'
  276 + || path === 'dal'
  277 + || path === 'enums'
  278 + || path === 'service'
  279 + || path === 'vo' // 下面三个,主要是兜底。可能考虑到有人改了包结构
  280 + || path === 'mysql'
  281 + || path === 'dataobject') {
  282 + break;
  283 + }
  284 + tmp = tmp ? tmp + '.' + path : path;
  285 + i++;
  286 + }
  287 + if (tmp) {
  288 + newPaths.push(tmp);
  289 + }
  290 + }
  291 + paths = newPaths;
  292 + }
  293 + // 遍历每个 path, 拼接成树
260 294 for (let i = 0; i < paths.length; i++) {
261   - // 已经添加大奥 files 中,则跳过
  295 + // 已经添加到 files 中,则跳过
262 296 let oldFullPath = fullPath;
263   - fullPath = fullPath.length === 0 ? paths[i] : fullPath + '/' + paths[i];
  297 + // 下面的 replaceAll 的原因,是因为上面包处理了,导致和 tabs 不匹配,所以 replaceAll 下
  298 + fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i];
264 299 if (exists[fullPath]) {
265 300 continue;
266 301 }
... ... @@ -276,7 +311,11 @@ export default {
276 311 return files;
277 312 },
278 313 /** 节点单击事件 **/
279   - handleNodeClick(data) {
  314 + handleNodeClick(data, node) {
  315 + if (node && !node.isLeaf) {
  316 + return false;
  317 + }
  318 + // 判断,如果非子节点,不允许选中
280 319 this.preview.activeName = data.id;
281 320 },
282 321 /** 修改按钮操作 */
... ...
更新日志.md
... ... @@ -20,12 +20,15 @@
20 20  
21 21 ### 📈 Statistic
22 22  
  23 +TODO 待统计
  24 +
23 25 ### ⭐ New Features
24 26  
25 27 *【重构】大模块按照多 Maven Module 的方式拆分,提升可维护性,为后续重构 onemall 提供基础
26 28 *【新增】Spring Security 支持读取多种用户类型,从不同的数据库表,从而实现单项目提供管理后台、用户 APP 的不同 RESTful API 接口
27 29 *【新增】代码生成器支持多 Maven Module 的方式生成代码,支持管理后台、用户 APP 两种场景的 RESTful API 的生成,支持 H2 SQL 脚本的生成
28 30 *【重构】将数据库文档调整到 tool 模块,更加明确
  31 +*【优化】代码生成器的前端展示效果,例如说 Java 包路径合并
29 32  
30 33 ### 🐞 Bug Fixes
31 34  
... ...