admin
2024-11-12 a6316ee0ab82a0f3fc2691f8b5ddbd79e1567086
提交 | 用户 | 时间
a6316e 1 package com.billion.generator.service;
A 2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.IOException;
6 import java.io.StringWriter;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.function.Function;
11 import java.util.stream.Collectors;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipOutputStream;
14
15 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
16 import org.apache.commons.io.FileUtils;
17 import org.apache.commons.io.IOUtils;
18 import org.apache.velocity.Template;
19 import org.apache.velocity.VelocityContext;
20 import org.apache.velocity.app.Velocity;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.stereotype.Service;
25 import org.springframework.transaction.annotation.Transactional;
26 import com.alibaba.fastjson2.JSON;
27 import com.alibaba.fastjson2.JSONObject;
28 import com.billion.common.constant.Constants;
29 import com.billion.common.constant.GenConstants;
30 import com.billion.common.core.text.CharsetKit;
31 import com.billion.common.exception.ServiceException;
32 import com.billion.common.utils.StringUtils;
33 import com.billion.generator.domain.GenTable;
34 import com.billion.generator.domain.GenTableColumn;
35 import com.billion.generator.mapper.GenTableColumnMapper;
36 import com.billion.generator.mapper.GenTableMapper;
37 import com.billion.generator.util.GenUtils;
38 import com.billion.generator.util.VelocityInitializer;
39 import com.billion.generator.util.VelocityUtils;
40
41 /**
42  * 业务 服务层实现
43  * 
44  * @author ruoyi
45  */
46 @Service
47 public class GenTableServiceImpl extends ServiceImpl<GenTableMapper, GenTable> implements IGenTableService
48 {
49     private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
50
51     @Autowired
52     private GenTableMapper genTableMapper;
53
54     @Autowired
55     private GenTableColumnMapper genTableColumnMapper;
56
57     /**
58      * 查询业务信息
59      * 
60      * @param id 业务ID
61      * @return 业务信息
62      */
63     @Override
64     public GenTable selectGenTableById(Long id)
65     {
66         GenTable genTable = genTableMapper.selectGenTableById(id);
67         setTableFromOptions(genTable);
68         return genTable;
69     }
70
71     /**
72      * 查询业务列表
73      * 
74      * @param genTable 业务信息
75      * @return 业务集合
76      */
77     @Override
78     public List<GenTable> selectGenTableList(GenTable genTable)
79     {
80         return genTableMapper.selectGenTableList(genTable);
81     }
82
83     /**
84      * 查询据库列表
85      * 
86      * @param genTable 业务信息
87      * @return 数据库表集合
88      */
89     @Override
90     public List<GenTable> selectDbTableList(GenTable genTable)
91     {
92         return genTableMapper.selectDbTableList(genTable);
93     }
94
95     /**
96      * 查询据库列表
97      * 
98      * @param tableNames 表名称组
99      * @return 数据库表集合
100      */
101     @Override
102     public List<GenTable> selectDbTableListByNames(String[] tableNames)
103     {
104         return genTableMapper.selectDbTableListByNames(tableNames);
105     }
106
107     /**
108      * 查询所有表信息
109      * 
110      * @return 表信息集合
111      */
112     @Override
113     public List<GenTable> selectGenTableAll()
114     {
115         return genTableMapper.selectGenTableAll();
116     }
117
118     /**
119      * 修改业务
120      * 
121      * @param genTable 业务信息
122      * @return 结果
123      */
124     @Override
125     @Transactional
126     public void updateGenTable(GenTable genTable)
127     {
128         String options = JSON.toJSONString(genTable.getParams());
129         genTable.setOptions(options);
130         int row = genTableMapper.updateGenTable(genTable);
131         if (row > 0)
132         {
133             for (GenTableColumn cenTableColumn : genTable.getColumns())
134             {
135                 genTableColumnMapper.updateGenTableColumn(cenTableColumn);
136             }
137         }
138     }
139
140     /**
141      * 删除业务对象
142      * 
143      * @param tableIds 需要删除的数据ID
144      * @return 结果
145      */
146     @Override
147     @Transactional
148     public void deleteGenTableByIds(Long[] tableIds)
149     {
150         genTableMapper.deleteGenTableByIds(tableIds);
151         genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
152     }
153
154     /**
155      * 创建表
156      *
157      * @param sql 创建表语句
158      * @return 结果
159      */
160     @Override
161     public boolean createTable(String sql)
162     {
163         return genTableMapper.createTable(sql) == 0;
164     }
165
166     /**
167      * 导入表结构
168      * 
169      * @param tableList 导入表列表
170      */
171     @Override
172     @Transactional
173     public void importGenTable(List<GenTable> tableList, String operName)
174     {
175         try
176         {
177             for (GenTable table : tableList)
178             {
179                 String tableName = table.getTableName();
180                 GenUtils.initTable(table, operName);
181                 int row = genTableMapper.insertGenTable(table);
182                 if (row > 0)
183                 {
184                     // 保存列信息
185                     List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
186                     for (GenTableColumn column : genTableColumns)
187                     {
188                         GenUtils.initColumnField(column, table);
189                         genTableColumnMapper.insertGenTableColumn(column);
190                     }
191                 }
192             }
193         }
194         catch (Exception e)
195         {
196             throw new ServiceException("导入失败:" + e.getMessage());
197         }
198     }
199
200     /**
201      * 预览代码
202      * 
203      * @param tableId 表编号
204      * @return 预览数据列表
205      */
206     @Override
207     public Map<String, String> previewCode(Long tableId)
208     {
209         Map<String, String> dataMap = new LinkedHashMap<>();
210         // 查询表信息
211         GenTable table = genTableMapper.selectGenTableById(tableId);
212         // 设置主子表信息
213         setSubTable(table);
214         // 设置主键列信息
215         setPkColumn(table);
216         VelocityInitializer.initVelocity();
217
218         VelocityContext context = VelocityUtils.prepareContext(table);
219
220         // 获取模板列表
221         List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
222         for (String template : templates)
223         {
224             // 渲染模板
225             StringWriter sw = new StringWriter();
226             Template tpl = Velocity.getTemplate(template, Constants.UTF8);
227             tpl.merge(context, sw);
228             dataMap.put(template, sw.toString());
229         }
230         return dataMap;
231     }
232
233     /**
234      * 生成代码(下载方式)
235      * 
236      * @param tableName 表名称
237      * @return 数据
238      */
239     @Override
240     public byte[] downloadCode(String tableName)
241     {
242         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
243         ZipOutputStream zip = new ZipOutputStream(outputStream);
244         generatorCode(tableName, zip);
245         IOUtils.closeQuietly(zip);
246         return outputStream.toByteArray();
247     }
248
249     /**
250      * 生成代码(自定义路径)
251      * 
252      * @param tableName 表名称
253      */
254     @Override
255     public void generatorCode(String tableName)
256     {
257         // 查询表信息
258         GenTable table = genTableMapper.selectGenTableByName(tableName);
259         // 设置主子表信息
260         setSubTable(table);
261         // 设置主键列信息
262         setPkColumn(table);
263
264         VelocityInitializer.initVelocity();
265
266         VelocityContext context = VelocityUtils.prepareContext(table);
267
268         // 获取模板列表
269         List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
270         for (String template : templates)
271         {
272             if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
273             {
274                 // 渲染模板
275                 StringWriter sw = new StringWriter();
276                 Template tpl = Velocity.getTemplate(template, Constants.UTF8);
277                 tpl.merge(context, sw);
278                 try
279                 {
280                     String path = getGenPath(table, template);
281                     FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
282                 }
283                 catch (IOException e)
284                 {
285                     throw new ServiceException("渲染模板失败,表名:" + table.getTableName());
286                 }
287             }
288         }
289     }
290
291     /**
292      * 同步数据库
293      * 
294      * @param tableName 表名称
295      */
296     @Override
297     @Transactional
298     public void synchDb(String tableName)
299     {
300         GenTable table = genTableMapper.selectGenTableByName(tableName);
301         List<GenTableColumn> tableColumns = table.getColumns();
302         Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));
303
304         List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
305         if (StringUtils.isEmpty(dbTableColumns))
306         {
307             throw new ServiceException("同步数据失败,原表结构不存在");
308         }
309         List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
310
311         dbTableColumns.forEach(column -> {
312             GenUtils.initColumnField(column, table);
313             if (tableColumnMap.containsKey(column.getColumnName()))
314             {
315                 GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
316                 column.setColumnId(prevColumn.getColumnId());
317                 if (column.isList())
318                 {
319                     // 如果是列表,继续保留查询方式/字典类型选项
320                     column.setDictType(prevColumn.getDictType());
321                     column.setQueryType(prevColumn.getQueryType());
322                 }
323                 if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
324                         && (column.isInsert() || column.isEdit())
325                         && ((column.isUsableColumn()) || (!column.isSuperColumn())))
326                 {
327                     // 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项
328                     column.setIsRequired(prevColumn.getIsRequired());
329                     column.setHtmlType(prevColumn.getHtmlType());
330                 }
331                 genTableColumnMapper.updateGenTableColumn(column);
332             }
333             else
334             {
335                 genTableColumnMapper.insertGenTableColumn(column);
336             }
337         });
338
339         List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
340         if (StringUtils.isNotEmpty(delColumns))
341         {
342             genTableColumnMapper.deleteGenTableColumns(delColumns);
343         }
344     }
345
346     /**
347      * 批量生成代码(下载方式)
348      * 
349      * @param tableNames 表数组
350      * @return 数据
351      */
352     @Override
353     public byte[] downloadCode(String[] tableNames)
354     {
355         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
356         ZipOutputStream zip = new ZipOutputStream(outputStream);
357         for (String tableName : tableNames)
358         {
359             generatorCode(tableName, zip);
360         }
361         IOUtils.closeQuietly(zip);
362         return outputStream.toByteArray();
363     }
364
365     /**
366      * 查询表信息并生成代码
367      */
368     private void generatorCode(String tableName, ZipOutputStream zip)
369     {
370         // 查询表信息
371         GenTable table = genTableMapper.selectGenTableByName(tableName);
372         // 设置主子表信息
373         setSubTable(table);
374         // 设置主键列信息
375         setPkColumn(table);
376
377         VelocityInitializer.initVelocity();
378
379         VelocityContext context = VelocityUtils.prepareContext(table);
380
381         // 获取模板列表
382         List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
383         for (String template : templates)
384         {
385             // 渲染模板
386             StringWriter sw = new StringWriter();
387             Template tpl = Velocity.getTemplate(template, Constants.UTF8);
388             tpl.merge(context, sw);
389             try
390             {
391                 // 添加到zip
392                 zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
393                 IOUtils.write(sw.toString(), zip, Constants.UTF8);
394                 IOUtils.closeQuietly(sw);
395                 zip.flush();
396                 zip.closeEntry();
397             }
398             catch (IOException e)
399             {
400                 log.error("渲染模板失败,表名:" + table.getTableName(), e);
401             }
402         }
403     }
404
405     /**
406      * 修改保存参数校验
407      * 
408      * @param genTable 业务信息
409      */
410     @Override
411     public void validateEdit(GenTable genTable)
412     {
413         if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
414         {
415             String options = JSON.toJSONString(genTable.getParams());
416             JSONObject paramsObj = JSON.parseObject(options);
417             if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
418             {
419                 throw new ServiceException("树编码字段不能为空");
420             }
421             else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
422             {
423                 throw new ServiceException("树父编码字段不能为空");
424             }
425             else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
426             {
427                 throw new ServiceException("树名称字段不能为空");
428             }
429             else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
430             {
431                 if (StringUtils.isEmpty(genTable.getSubTableName()))
432                 {
433                     throw new ServiceException("关联子表的表名不能为空");
434                 }
435                 else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
436                 {
437                     throw new ServiceException("子表关联的外键名不能为空");
438                 }
439             }
440         }
441     }
442
443     /**
444      * 设置主键列信息
445      * 
446      * @param table 业务表信息
447      */
448     public void setPkColumn(GenTable table)
449     {
450         for (GenTableColumn column : table.getColumns())
451         {
452             if (column.isPk())
453             {
454                 table.setPkColumn(column);
455                 break;
456             }
457         }
458         if (StringUtils.isNull(table.getPkColumn()))
459         {
460             table.setPkColumn(table.getColumns().get(0));
461         }
462         if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
463         {
464             for (GenTableColumn column : table.getSubTable().getColumns())
465             {
466                 if (column.isPk())
467                 {
468                     table.getSubTable().setPkColumn(column);
469                     break;
470                 }
471             }
472             if (StringUtils.isNull(table.getSubTable().getPkColumn()))
473             {
474                 table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
475             }
476         }
477     }
478
479     /**
480      * 设置主子表信息
481      * 
482      * @param table 业务表信息
483      */
484     public void setSubTable(GenTable table)
485     {
486         String subTableName = table.getSubTableName();
487         if (StringUtils.isNotEmpty(subTableName))
488         {
489             table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
490         }
491     }
492
493     /**
494      * 设置代码生成其他选项值
495      * 
496      * @param genTable 设置后的生成对象
497      */
498     public void setTableFromOptions(GenTable genTable)
499     {
500         JSONObject paramsObj = JSON.parseObject(genTable.getOptions());
501         if (StringUtils.isNotNull(paramsObj))
502         {
503             String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
504             String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
505             String treeName = paramsObj.getString(GenConstants.TREE_NAME);
506             Long parentMenuId = paramsObj.getLongValue(GenConstants.PARENT_MENU_ID);
507             String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
508
509             genTable.setTreeCode(treeCode);
510             genTable.setTreeParentCode(treeParentCode);
511             genTable.setTreeName(treeName);
512             genTable.setParentMenuId(parentMenuId);
513             genTable.setParentMenuName(parentMenuName);
514         }
515     }
516
517     /**
518      * 获取代码生成地址
519      * 
520      * @param table 业务表信息
521      * @param template 模板文件路径
522      * @return 生成地址
523      */
524     public static String getGenPath(GenTable table, String template)
525     {
526         String genPath = table.getGenPath();
527         if (StringUtils.equals(genPath, "/"))
528         {
529             return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
530         }
531         return genPath + File.separator + VelocityUtils.getFileName(template, table);
532     }
533 }