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,7 +229,8 @@ public class CodegenEngine {
229 } 229 }
230 230
231 private static String vueFilePath(String path) { 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,11 +61,11 @@
61 <!-- 预览界面 --> 61 <!-- 预览界面 -->
62 <el-dialog :title="preview.title" :visible.sync="preview.open" width="90%" top="5vh" append-to-body> 62 <el-dialog :title="preview.title" :visible.sync="preview.open" width="90%" top="5vh" append-to-body>
63 <el-row> 63 <el-row>
64 - <el-col :span="9"> 64 + <el-col :span="7">
65 <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all highlight-current 65 <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all highlight-current
66 @node-click="handleNodeClick"/> 66 @node-click="handleNodeClick"/>
67 </el-col> 67 </el-col>
68 - <el-col :span="15"> 68 + <el-col :span="17">
69 <el-tabs v-model="preview.activeName"> 69 <el-tabs v-model="preview.activeName">
70 <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" 70 <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)"
71 :name="item.filePath" :key="item.filePath"> 71 :name="item.filePath" :key="item.filePath">
@@ -257,10 +257,45 @@ export default { @@ -257,10 +257,45 @@ export default {
257 for (const data of datas) { 257 for (const data of datas) {
258 let paths = data.filePath.split('/'); 258 let paths = data.filePath.split('/');
259 let fullPath = ''; // 从头开始的路径,用于生成 id 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 for (let i = 0; i < paths.length; i++) { 294 for (let i = 0; i < paths.length; i++) {
261 - // 已经添加大奥 files 中,则跳过 295 + // 已经添加到 files 中,则跳过
262 let oldFullPath = fullPath; 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 if (exists[fullPath]) { 299 if (exists[fullPath]) {
265 continue; 300 continue;
266 } 301 }
@@ -276,7 +311,11 @@ export default { @@ -276,7 +311,11 @@ export default {
276 return files; 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 this.preview.activeName = data.id; 319 this.preview.activeName = data.id;
281 }, 320 },
282 /** 修改按钮操作 */ 321 /** 修改按钮操作 */
更新日志.md
@@ -20,12 +20,15 @@ @@ -20,12 +20,15 @@
20 20
21 ### 📈 Statistic 21 ### 📈 Statistic
22 22
  23 +TODO 待统计
  24 +
23 ### ⭐ New Features 25 ### ⭐ New Features
24 26
25 *【重构】大模块按照多 Maven Module 的方式拆分,提升可维护性,为后续重构 onemall 提供基础 27 *【重构】大模块按照多 Maven Module 的方式拆分,提升可维护性,为后续重构 onemall 提供基础
26 *【新增】Spring Security 支持读取多种用户类型,从不同的数据库表,从而实现单项目提供管理后台、用户 APP 的不同 RESTful API 接口 28 *【新增】Spring Security 支持读取多种用户类型,从不同的数据库表,从而实现单项目提供管理后台、用户 APP 的不同 RESTful API 接口
27 *【新增】代码生成器支持多 Maven Module 的方式生成代码,支持管理后台、用户 APP 两种场景的 RESTful API 的生成,支持 H2 SQL 脚本的生成 29 *【新增】代码生成器支持多 Maven Module 的方式生成代码,支持管理后台、用户 APP 两种场景的 RESTful API 的生成,支持 H2 SQL 脚本的生成
28 *【重构】将数据库文档调整到 tool 模块,更加明确 30 *【重构】将数据库文档调整到 tool 模块,更加明确
  31 +*【优化】代码生成器的前端展示效果,例如说 Java 包路径合并
29 32
30 ### 🐞 Bug Fixes 33 ### 🐞 Bug Fixes
31 34