RuoYi 5 yıl önce
ebeveyn
işleme
1c3541cc05
63 değiştirilmiş dosya ile 4383 ekleme ve 1264 silme
  1. 1 1
      README.md
  2. 10 2
      pom.xml
  3. 1 1
      ruoyi-admin/pom.xml
  4. 24 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
  5. 1 1
      ruoyi-admin/src/main/resources/application.yml
  6. 5 0
      ruoyi-admin/src/main/resources/static/ruoyi/css/ry-ui.css
  7. 2 2
      ruoyi-admin/src/main/resources/templates/include.html
  8. 2 2
      ruoyi-admin/src/main/resources/templates/index.html
  9. 2 2
      ruoyi-admin/src/main/resources/templates/login.html
  10. 64 2
      ruoyi-admin/src/main/resources/templates/main.html
  11. 42 0
      ruoyi-admin/src/main/resources/templates/system/dict/type/tree.html
  12. 7 1
      ruoyi-common/pom.xml
  13. 1 1
      ruoyi-common/src/main/java/com/ruoyi/common/config/Global.java
  14. 88 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
  15. 50 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
  16. 17 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
  17. 33 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
  18. 1 1
      ruoyi-framework/pom.xml
  19. 1 1
      ruoyi-generator/pom.xml
  20. 123 12
      ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
  21. 0 72
      ruoyi-generator/src/main/java/com/ruoyi/generator/domain/ColumnConfigInfo.java
  22. 0 125
      ruoyi-generator/src/main/java/com/ruoyi/generator/domain/ColumnInfo.java
  23. 255 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
  24. 353 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
  25. 0 103
      ruoyi-generator/src/main/java/com/ruoyi/generator/domain/TableInfo.java
  26. 0 37
      ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenMapper.java
  27. 52 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
  28. 76 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
  29. 0 36
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenService.java
  30. 44 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java
  31. 100 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
  32. 0 135
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenServiceImpl.java
  33. 69 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableColumnServiceImpl.java
  34. 337 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableServiceImpl.java
  35. 134 173
      ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
  36. 1 2
      ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
  37. 315 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
  38. 0 52
      ruoyi-generator/src/main/resources/mapper/generator/GenMapper.xml
  39. 120 0
      ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
  40. 167 0
      ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
  41. 483 0
      ruoyi-generator/src/main/resources/templates/tool/gen/edit.html
  42. 72 12
      ruoyi-generator/src/main/resources/templates/tool/gen/gen.html
  43. 96 0
      ruoyi-generator/src/main/resources/templates/tool/gen/importTable.html
  44. 149 51
      ruoyi-generator/src/main/resources/vm/html/add.html.vm
  45. 149 51
      ruoyi-generator/src/main/resources/vm/html/edit.html.vm
  46. 150 0
      ruoyi-generator/src/main/resources/vm/html/list-tree.html.vm
  47. 116 100
      ruoyi-generator/src/main/resources/vm/html/list.html.vm
  48. 51 0
      ruoyi-generator/src/main/resources/vm/html/tree.html.vm
  49. 169 96
      ruoyi-generator/src/main/resources/vm/java/Controller.java.vm
  50. 37 38
      ruoyi-generator/src/main/resources/vm/java/Mapper.java.vm
  51. 49 30
      ruoyi-generator/src/main/resources/vm/java/Service.java.vm
  52. 108 51
      ruoyi-generator/src/main/resources/vm/java/ServiceImpl.java.vm
  53. 47 28
      ruoyi-generator/src/main/resources/vm/java/domain.java.vm
  54. 5 5
      ruoyi-generator/src/main/resources/vm/sql/sql.vm
  55. 68 32
      ruoyi-generator/src/main/resources/vm/xml/Mapper.xml.vm
  56. 1 1
      ruoyi-quartz/pom.xml
  57. 1 1
      ruoyi-system/pom.xml
  58. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
  59. 17 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
  60. 45 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
  61. 2 2
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
  62. 5 0
      ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
  63. 57 1
      sql/ry_20190808.sql

+ 1 - 1
README.md

@@ -87,4 +87,4 @@
 
 ## 若依交流群
 
-QQ群: [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN)  [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW)  [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z)  [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU)  [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA)  [![加入QQ群](https://img.shields.io/badge/1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb)  点击按钮入群。
+QQ群: [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN)  [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW)  [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z)  [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU)  [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA)  [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb)  [![加入QQ群](https://img.shields.io/badge/1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz)  点击按钮入群。

+ 10 - 2
pom.xml

@@ -6,14 +6,14 @@
 	
     <groupId>com.ruoyi</groupId>
     <artifactId>ruoyi</artifactId>
-    <version>3.4</version>
+    <version>4.0.0</version>
 
     <name>ruoyi</name>
 	<url>http://www.ruoyi.vip</url>
     <description>若依管理系统</description>
     
     <properties>
-	    <ruoyi.version>3.4</ruoyi.version>
+	    <ruoyi.version>4.0.0</ruoyi.version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 		<java.version>1.8</java.version>
@@ -25,6 +25,7 @@
 		<kaptcha.version>2.3.2</kaptcha.version>
 		<swagger.version>2.9.2</swagger.version>
 		<pagehelper.boot.version>1.2.5</pagehelper.boot.version>
+		<fastjson.version>1.2.47</fastjson.version>
 		<oshi.version>3.9.1</oshi.version>
 		<commons.io.version>2.5</commons.io.version>
 		<commons.fileupload.version>1.3.3</commons.fileupload.version>
@@ -167,6 +168,13 @@
 	            <artifactId>velocity</artifactId>
 	            <version>${velocity.version}</version>
 	        </dependency>
+	        
+	        <!-- 阿里JSON解析器 -->
+			<dependency>
+				<groupId>com.alibaba</groupId>
+				<artifactId>fastjson</artifactId>
+				<version>${fastjson.version}</version>
+			</dependency>
             
             <!-- 定时任务-->
 			<dependency>

+ 1 - 1
ruoyi-admin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.4</version>
+        <version>4.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 	<packaging>jar</packaging>

+ 24 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java

@@ -15,6 +15,7 @@ import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.Ztree;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -155,4 +156,27 @@ public class SysDictTypeController extends BaseController
     {
         return dictTypeService.checkDictTypeUnique(dictType);
     }
+
+    /**
+     * 选择字典树
+     */
+    @GetMapping("/selectDictTree/{columnId}/{dictType}")
+    public String selectDeptTree(@PathVariable("columnId") Long columnId, @PathVariable("dictType") String dictType,
+            ModelMap mmap)
+    {
+        mmap.put("columnId", columnId);
+        mmap.put("dict", dictTypeService.selectDictTypeByType(dictType));
+        return prefix + "/tree";
+    }
+
+    /**
+     * 加载字典列表树
+     */
+    @GetMapping("/treeData")
+    @ResponseBody
+    public List<Ztree> treeData()
+    {
+        List<Ztree> ztrees = dictTypeService.selectDictTree(new SysDictType());
+        return ztrees;
+    }
 }

+ 1 - 1
ruoyi-admin/src/main/resources/application.yml

@@ -3,7 +3,7 @@ ruoyi:
   # 名称
   name: RuoYi
   # 版本
-  version: 3.4.0
+  version: 4.0.0
   # 版权年份
   copyrightYear: 2019
   # 实例演示开关

+ 5 - 0
ruoyi-admin/src/main/resources/static/ruoyi/css/ry-ui.css

@@ -335,6 +335,11 @@ label.error {
 	right: 42px
 }
 
+.input-group.date label.error {
+	z-index:99;
+	right: 3px
+}
+
 .Validform_error,input.error,select.error {
 	background-color: #fbe2e2;
 	border-color: #c66161;

+ 2 - 2
ruoyi-admin/src/main/resources/templates/include.html

@@ -39,8 +39,8 @@
     <script th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
 	<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
 	<script th:src="@{/ajax/libs/layui/layui.js}"></script>
-	<script th:src="@{/ruoyi/js/common.js?v=3.4.0}"></script>
-	<script th:src="@{/ruoyi/js/ry-ui.js?v=3.4.0}"></script>
+	<script th:src="@{/ruoyi/js/common.js?v=4.0.0}"></script>
+	<script th:src="@{/ruoyi/js/ry-ui.js?v=4.0.0}"></script>
 	<script th:inline="javascript"> var ctx = [[@{/}]]; </script>
 </div>
 

+ 2 - 2
ruoyi-admin/src/main/resources/templates/index.html

@@ -15,7 +15,7 @@
     <link th:href="@{/css/animate.css}" rel="stylesheet"/>
     <link th:href="@{/css/style.css}" rel="stylesheet"/>
     <link th:href="@{/css/skins.css}" rel="stylesheet"/>
-    <link th:href="@{/ruoyi/css/ry-ui.css?v=3.4.0}" rel="stylesheet"/>
+    <link th:href="@{/ruoyi/css/ry-ui.css?v=4.0.0}" rel="stylesheet"/>
 </head>
 <body class="fixed-sidebar full-height-layout gray-bg" style="overflow: hidden" th:classappend="|${@config.getKey('sys.index.sideTheme')} ${@config.getKey('sys.index.skinName')}|">
 <div id="wrapper">
@@ -232,7 +232,7 @@
 <script th:src="@{/js/jquery.contextMenu.min.js}"></script>
 <script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
 <script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
-<script th:src="@{/ruoyi/js/ry-ui.js?v=3.4.0}"></script>
+<script th:src="@{/ruoyi/js/ry-ui.js?v=4.0.0}"></script>
 <script th:src="@{/ruoyi/index.js}"></script>
 <script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
 <script th:inline="javascript"> 

+ 2 - 2
ruoyi-admin/src/main/resources/templates/login.html

@@ -10,7 +10,7 @@
     <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
     <link href="../static/css/style.css" th:href="@{/css/style.css}" rel="stylesheet"/>
     <link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
-    <link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=3.4.0}" rel="stylesheet"/>
+    <link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.0.0}" rel="stylesheet"/>
     <!--[if lt IE 9]>
     <meta http-equiv="refresh" content="0;ie.html" />
     <![endif]-->
@@ -80,7 +80,7 @@
 <script src="../static/ajax/libs/validate/messages_zh.min.js" th:src="@{/ajax/libs/validate/messages_zh.min.js}"></script>
 <script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
 <script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
-<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=3.4.0}"></script>
+<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.0.0}"></script>
 <script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
 </body>
 </html>

+ 64 - 2
ruoyi-admin/src/main/resources/templates/main.html

@@ -81,7 +81,7 @@
                     <div class="ibox-content">
                         <p><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
                         </p>
-                        <p><i class="fa fa-qq"></i> QQ群:<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <a href="https://jq.qq.com/?_wv=1027&k=5Ofd4Pb" target="_blank">1382251</a>
+                        <p><i class="fa fa-qq"></i> QQ群:<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <a href="https://jq.qq.com/?_wv=1027&k=5fdQ1eG" target="_blank">1145125</a>
                         </p>
                         <p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
                         </p>
@@ -98,13 +98,75 @@
                     <div class="ibox-content no-padding">
                         <div class="panel-body">
                             <div class="panel-group" id="version">
+                            <div class="panel panel-default">
+								<div class="panel-heading">
+								   <h5 class="panel-title">
+									   <a data-toggle="collapse" data-parent="#version" href="#v40">v4.0.0</a><code class="pull-right">2019.08.08</code>
+								   </h5>
+								</div>
+								<div id="v40" class="panel-collapse collapse in">
+									<div class="panel-body">
+									   <ol>
+									        <li>代码生成支持预览、编辑,保存方案</li>
+									        <li>新增防止表单重复提交注解</li>
+											<li>新增后端校验(和前端保持一致)</li>
+											<li>新增同一个用户最大会话数控制</li>
+											<li>Excel导出子对象支持多个字段</li>
+											<li>定时任务支持静态调用和多参数</li>
+											<li>定时任务增加分组条件查询</li>
+											<li>字典类型增加任务分组数据</li>
+											<li>新增表格是否首次加载数据</li>
+											<li>新增parentTab选项卡可在同一页签打开</li>
+											<li>多数据源支持类注解(允许继承父类的注解)</li>
+											<li>部门及以下数据权限(调整为以下及所有子节点)</li>
+											<li>新增角色数据权限配(仅本人数据权限)</li>
+											<li>修改菜单权限显示问题</li>
+											<li>上传文件修改路径及返回名称</li>
+											<li>添加报表插件及示例</li>
+											<li>添加首页统计模板</li>
+											<li>添加表格拖拽示例</li>
+											<li>添加卡片列表示例</li>
+											<li>添加富文本编辑器示例</li>
+											<li>添加表格动态增删改查示例</li>
+											<li>添加用户页面岗位选择框提示</li>
+											<li>点击菜单操作添加背景高亮显示</li>
+											<li>表格树新增showSearch是否显示检索信息</li>
+											<li>解决表格列设置sortName无效问题</li>
+											<li>表格图片预览支持自定义设置宽高</li>
+											<li>添加表格列浮动提示(单击文本复制)</li>
+											<li>PC端收起菜单后支持浮动显示</li>
+											<li>详细操作样式调整</li>
+											<li>修改用户更新描述空串不更新问题</li>
+											<li>导入修改为模板渲染</li>
+											<li>修改菜单及部门排序规则</li>
+											<li>角色导出数据范围表达式翻译</li>
+											<li>添加summernote富文本字体大小</li>
+											<li>优化表格底部下边框防重叠&汇总像素问题</li>
+											<li>树表格支持属性多层级访问</li>
+											<li>修复IE浏览器用户管理界面右侧留白问题</li>
+											<li>重置按钮刷新表格</li>
+											<li>重置密码更新用户缓存</li>
+											<li>优化验证码属性参数</li>
+											<li>支持数据监控配置用户名和密码</li>
+											<li>文件上传修改按钮背景及加载动画</li>
+											<li>支持配置一级菜单href跳转</li>
+											<li>侧边栏添加一套浅色主题</li>
+											<li>树表格添加回调函数(校验异常状态)</li>
+											<li>用户个人中心适配手机端显示</li>
+											<li>Excel支持设置导出类型&更换样式</li>
+											<li>检查属性改变修改为克隆方式(防止热部署强转异常)</li>
+											<li>其他细节优化</li>
+										</ol>
+									</div>
+								</div>
+							 </div>
                             <div class="panel panel-default">
 								<div class="panel-heading">
 								   <h5 class="panel-title">
 									   <a data-toggle="collapse" data-parent="#version" href="#v34">v3.4.0</a><code class="pull-right">2019.06.03</code>
 								   </h5>
 								</div>
-								<div id="v34" class="panel-collapse collapse in">
+								<div id="v34" class="panel-collapse collapse">
 									<div class="panel-body">
 									   <ol>
 									        <li>新增实例演示菜单及demo</li>

+ 42 - 0
ruoyi-admin/src/main/resources/templates/system/dict/type/tree.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('字典树选择')" />
+	<th:block th:include="include :: ztree-css" />
+</head>
+<style>
+	body{height:auto;font-family: "Microsoft YaHei";}
+	button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+	<input id="columnId" type="hidden" th:value="${columnId}"/>
+	<input id="treeId"   type="hidden" th:value="${dict?.dictId}"/>
+	<input id="dictType" type="hidden" th:value="${dict?.dictType}"/>
+	<div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+		<label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+		<label id="btnHide" title="隐藏搜索">︽</label>
+	</div>
+	<div class="treeSearchInput" id="search">
+		<label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+		<button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+	</div>
+	<div id="tree" class="ztree treeselect"></div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<th:block th:include="include :: ztree-js" />
+	<script th:inline="javascript">
+		$(function() {
+			var url = ctx + "system/dict/treeData";
+			var options = {
+		        url: url,
+		        onClick : zOnClick
+		    };
+			$.tree.init(options);
+		});
+		
+		function zOnClick(event, treeId, treeNode) {
+		    $("#dictType").val(treeNode.title);
+		}
+	</script>
+</body>
+</html>

+ 7 - 1
ruoyi-common/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.4</version>
+        <version>4.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 	
@@ -59,6 +59,12 @@
 		    <artifactId>jackson-databind</artifactId>
 		</dependency>
 
+		<!-- 阿里JSON解析器 -->
+		<dependency>
+			<groupId>com.alibaba</groupId>
+			<artifactId>fastjson</artifactId>
+		</dependency>
+
 		<!-- io常用工具类 -->
 		<dependency>
 			<groupId>commons-io</groupId>

+ 1 - 1
ruoyi-common/src/main/java/com/ruoyi/common/config/Global.java

@@ -81,7 +81,7 @@ public class Global
      */
     public static String getVersion()
     {
-        return StringUtils.nvl(getConfig("ruoyi.version"), "3.4.0");
+        return StringUtils.nvl(getConfig("ruoyi.version"), "4.0.0");
     }
 
     /**

+ 88 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java

@@ -0,0 +1,88 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 代码生成通用常量
+ * 
+ * @author ruoyi
+ */
+public class GenConstants
+{
+    /** 单表(增删改查) */
+    public static final String TPL_CRUD = "crud";
+
+    /** 树表(增删改查) */
+    public static final String TPL_TREE = "tree";
+
+    /** 树编码字段 */
+    public static final String TREE_CODE = "treeCode";
+
+    /** 树父编码字段 */
+    public static final String TREE_PARENT_CODE = "treeParentCode";
+
+    /** 树名称字段 */
+    public static final String TREE_NAME = "treeName";
+
+    /** 数据库字符串类型 */
+    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text",
+            "mediumtext", "longtext" };
+
+    /** 数据库时间类型 */
+    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+    /** 数据库数字类型 */
+    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+            "bigint", "float", "float", "double", "decimal" };
+
+    /** 页面不需要编辑字段 */
+    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+    /** 页面不需要显示的列表字段 */
+    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time" };
+
+    /** 页面不需要查询字段 */
+    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+            "update_time", "remark" };
+
+    /** 文本框 */
+    public static final String HTML_INPUT = "input";
+
+    /** 文本域 */
+    public static final String HTML_TEXTAREA = "textarea";
+
+    /** 下拉框 */
+    public static final String HTML_SELECT = "select";
+
+    /** 单选框 */
+    public static final String HTML_RADIO = "radio";
+
+    /** 复选框 */
+    public static final String HTML_CHECKBOX = "checkbox";
+
+    /** 日期控件 */
+    public static final String HTML_DATETIME = "datetime";
+
+    /** 字符串类型 */
+    public static final String TYPE_STRING = "String";
+
+    /** 整型 */
+    public static final String TYPE_INTEGER = "Integer";
+
+    /** 长整型 */
+    public static final String TYPE_LONG = "Long";
+
+    /** 浮点型 */
+    public static final String TYPE_DOUBLE = "Double";
+
+    /** 高精度计算类型 */
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+    /** 时间类型 */
+    public static final String TYPE_DATE = "Date";
+
+    /** 模糊查询 */
+    public static final String QUERY_LIKE = "Like";
+
+    /** 需要 */
+    public static final String REQUIRE = "1";
+}

+ 50 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java

@@ -0,0 +1,50 @@
+package com.ruoyi.common.core.domain;
+
+/**
+ * Tree基类
+ * 
+ * @author ruoyi
+ */
+public class TreeEntity extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 父菜单名称 */
+    private String parentName;
+
+    /** 父菜单ID */
+    private Long parentId;
+
+    /** 显示顺序 */
+    private Integer orderNum;
+
+    public String getParentName()
+    {
+        return parentName;
+    }
+
+    public void setParentName(String parentName)
+    {
+        this.parentName = parentName;
+    }
+
+    public Long getParentId()
+    {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId)
+    {
+        this.parentId = parentId;
+    }
+
+    public Integer getOrderNum()
+    {
+        return orderNum;
+    }
+
+    public void setOrderNum(Integer orderNum)
+    {
+        this.orderNum = orderNum;
+    }
+}

+ 17 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java

@@ -11,13 +11,19 @@ import java.util.List;
 public class TableDataInfo implements Serializable
 {
     private static final long serialVersionUID = 1L;
+
     /** 总记录数 */
     private long total;
+
     /** 列表数据 */
     private List<?> rows;
+
     /** 消息状态码 */
     private int code;
 
+    /** 消息内容 */
+    private int msg;
+
     /**
      * 表格数据对象
      */
@@ -66,4 +72,14 @@ public class TableDataInfo implements Serializable
     {
         this.code = code;
     }
-}
+
+    public int getMsg()
+    {
+        return msg;
+    }
+
+    public void setMsg(int msg)
+    {
+        this.msg = msg;
+    }
+}

+ 33 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java

@@ -362,4 +362,37 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
         }
         return result.toString();
     }
+
+    /**
+     * 驼峰式命名法 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
 }

+ 1 - 1
ruoyi-framework/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.4</version>
+        <version>4.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 	

+ 1 - 1
ruoyi-generator/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.4</version>
+        <version>4.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 123 - 12
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java

@@ -2,11 +2,14 @@ package com.ruoyi.generator.controller;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.io.IOUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -14,11 +17,15 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.generator.domain.TableInfo;
-import com.ruoyi.generator.service.IGenService;
+import com.ruoyi.common.utils.security.PermissionUtils;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.service.IGenTableColumnService;
+import com.ruoyi.generator.service.IGenTableService;
 
 /**
  * 代码生成 操作处理
@@ -32,7 +39,10 @@ public class GenController extends BaseController
     private String prefix = "tool/gen";
 
     @Autowired
-    private IGenService genService;
+    private IGenTableService genTableService;
+
+    @Autowired
+    private IGenTableColumnService genTableColumnService;
 
     @RequiresPermissions("tool:gen:view")
     @GetMapping()
@@ -41,16 +51,121 @@ public class GenController extends BaseController
         return prefix + "/gen";
     }
 
+    /**
+     * 查询代码生成列表
+     */
     @RequiresPermissions("tool:gen:list")
     @PostMapping("/list")
     @ResponseBody
-    public TableDataInfo list(TableInfo tableInfo)
+    public TableDataInfo genList(GenTable genTable)
+    {
+        startPage();
+        List<GenTable> list = genTableService.selectGenTableList(genTable);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询数据库列表
+     */
+    @RequiresPermissions("tool:gen:list")
+    @PostMapping("/db/list")
+    @ResponseBody
+    public TableDataInfo dataList(GenTable genTable)
     {
         startPage();
-        List<TableInfo> list = genService.selectTableList(tableInfo);
+        List<GenTable> list = genTableService.selectDbTableList(genTable);
         return getDataTable(list);
     }
 
+    /**
+     * 查询数据表字段列表
+     */
+    @RequiresPermissions("tool:gen:list")
+    @PostMapping("/column/list")
+    @ResponseBody
+    public TableDataInfo columnList(GenTableColumn genTableColumn)
+    {
+        TableDataInfo dataInfo = new TableDataInfo();
+        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(genTableColumn);
+        dataInfo.setRows(list);
+        dataInfo.setTotal(list.size());
+        return dataInfo;
+    }
+
+    /**
+     * 导入表结构
+     */
+    @RequiresPermissions("tool:gen:list")
+    @GetMapping("/importTable")
+    public String importTable()
+    {
+        return prefix + "/importTable";
+    }
+
+    /**
+     * 导入表结构(保存)
+     */
+    @RequiresPermissions("tool:gen:list")
+    @Log(title = "代码生成", businessType = BusinessType.IMPORT)
+    @PostMapping("/importTable")
+    @ResponseBody
+    public AjaxResult importTableSave(String tables)
+    {
+        String[] tableNames = Convert.toStrArray(tables);
+        // 查询表信息
+        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
+        String operName = (String) PermissionUtils.getPrincipalProperty("loginName");
+        genTableService.importGenTable(tableList, operName);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改代码生成业务
+     */
+    @GetMapping("/edit/{tableId}")
+    public String edit(@PathVariable("tableId") Long tableId, ModelMap mmap)
+    {
+        GenTable table = genTableService.selectGenTableById(tableId);
+        mmap.put("table", table);
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存代码生成业务
+     */
+    @RequiresPermissions("tool:gen:edit")
+    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(@Validated GenTable genTable)
+    {
+        genTableService.validateEdit(genTable);
+        genTableService.updateGenTable(genTable);
+        return AjaxResult.success();
+    }
+
+    @RequiresPermissions("tool:gen:remove")
+    @Log(title = "代码生成", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        genTableService.deleteGenTableByIds(ids);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 预览代码
+     */
+    @RequiresPermissions("tool:gen:preview")
+    @GetMapping("/preview/{tableId}")
+    @ResponseBody
+    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
+    {
+        Map<String, String> dataMap = genTableService.previewCode(tableId);
+        return AjaxResult.success(dataMap);
+    }
+
     /**
      * 生成代码
      */
@@ -59,7 +174,7 @@ public class GenController extends BaseController
     @GetMapping("/genCode/{tableName}")
     public void genCode(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
     {
-        byte[] data = genService.generatorCode(tableName);
+        byte[] data = genTableService.generatorCode(tableName);
         genCode(response, data);
     }
 
@@ -73,16 +188,12 @@ public class GenController extends BaseController
     public void batchGenCode(HttpServletResponse response, String tables) throws IOException
     {
         String[] tableNames = Convert.toStrArray(tables);
-        byte[] data = genService.generatorCode(tableNames);
+        byte[] data = genTableService.generatorCode(tableNames);
         genCode(response, data);
     }
 
     /**
      * 生成zip文件
-     * 
-     * @param response
-     * @param data
-     * @throws IOException
      */
     private void genCode(HttpServletResponse response, byte[] data) throws IOException
     {
@@ -92,4 +203,4 @@ public class GenController extends BaseController
         response.setContentType("application/octet-stream; charset=UTF-8");
         IOUtils.write(data, response.getOutputStream());
     }
-}
+}

+ 0 - 72
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/ColumnConfigInfo.java

@@ -1,72 +0,0 @@
-package com.ruoyi.generator.domain;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-/**
- * 字段类型配置 由数据库字段的注释解析而来
- * 注释结构示例:{"title": "状态", "type": "dict", "value": "sys_common_status"} {"title": "登录时间", "type": "date"}
- * 
- * @author ruoyi
- *
- */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class ColumnConfigInfo
-{
-    /**
-     * 属性标题
-     */
-    private String title;
-
-    /**
-     * 属性类型 dict(字典,value对应字典管理的字典类型), date(包括date)
-     */
-    private String type;
-
-    /**
-     * 属性值,参考数据类型,可为空
-     */
-    private String value;
-
-    public ColumnConfigInfo()
-    {
-        super();
-    }
-
-    public ColumnConfigInfo(String title, String type, String value)
-    {
-        super();
-        this.title = title;
-        this.type = type;
-        this.value = value;
-    }
-
-    public String getTitle()
-    {
-        return title;
-    }
-
-    public void setTitle(String title)
-    {
-        this.title = title;
-    }
-
-    public String getType()
-    {
-        return type;
-    }
-
-    public void setType(String type)
-    {
-        this.type = type;
-    }
-
-    public String getValue()
-    {
-        return value;
-    }
-
-    public void setValue(String value)
-    {
-        this.value = value;
-    }
-}

+ 0 - 125
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/ColumnInfo.java

@@ -1,125 +0,0 @@
-package com.ruoyi.generator.domain;
-
-import com.ruoyi.common.json.JSON;
-import com.ruoyi.common.utils.StringUtils;
-
-/**
- * ry数据库表列信息
- * 
- * @author ruoyi
- */
-public class ColumnInfo
-{
-    /** 字段名称 */
-    private String columnName;
-
-    /** 字段类型 */
-    private String dataType;
-
-    /** 列描述 */
-    private String columnComment;
-
-    /** 列配置 */
-    private ColumnConfigInfo configInfo;
-
-    /** Java属性类型 */
-    private String attrType;
-
-    /** Java属性名称(第一个字母大写),如:user_name => UserName */
-    private String attrName;
-
-    /** Java属性名称(第一个字母小写),如:user_name => userName */
-    private String attrname;
-
-    /** 执行计划(包含了与索引相关的一些细节信息) */
-    private String extra;
-
-    public String getColumnName()
-    {
-        return columnName;
-    }
-
-    public void setColumnName(String columnName)
-    {
-        this.columnName = columnName;
-    }
-
-    public String getDataType()
-    {
-        return dataType;
-    }
-
-    public void setDataType(String dataType)
-    {
-        this.dataType = dataType;
-    }
-
-    public String getColumnComment()
-    {
-        return columnComment;
-    }
-
-    public void setColumnComment(String columnComment) throws Exception
-    {
-        // 根据列描述解析列的配置信息
-        if (StringUtils.isNotEmpty(columnComment) && columnComment.startsWith("{"))
-        {
-            this.configInfo = JSON.unmarshal(columnComment, ColumnConfigInfo.class);
-            this.columnComment = configInfo.getTitle();
-        }
-        else
-        {
-            this.columnComment = columnComment;
-        }
-    }
-
-    public String getAttrName()
-    {
-        return attrName;
-    }
-
-    public void setAttrName(String attrName)
-    {
-        this.attrName = attrName;
-    }
-
-    public String getAttrname()
-    {
-        return attrname;
-    }
-
-    public void setAttrname(String attrname)
-    {
-        this.attrname = attrname;
-    }
-
-    public String getAttrType()
-    {
-        return attrType;
-    }
-
-    public void setAttrType(String attrType)
-    {
-        this.attrType = attrType;
-    }
-
-    public String getExtra()
-    {
-        return extra;
-    }
-
-    public void setExtra(String extra)
-    {
-        this.extra = extra;
-    }
-
-    public ColumnConfigInfo getConfigInfo()
-    {
-        return configInfo;
-    }
-
-    public void setConfigInfo(ColumnConfigInfo configInfo)
-    {
-        this.configInfo = configInfo;
-    }
-}

+ 255 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java

@@ -0,0 +1,255 @@
+package com.ruoyi.generator.domain;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 业务表 gen_table
+ * 
+ * @author ruoyi
+ */
+public class GenTable extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 编号 */
+    private Long tableId;
+
+    /** 表名称 */
+    @NotBlank(message = "表名称不能为空")
+    private String tableName;
+
+    /** 表描述 */
+    @NotBlank(message = "表描述不能为空")
+    private String tableComment;
+
+    /** 实体类名称(首字母大写) */
+    @NotBlank(message = "实体类名称不能为空")
+    private String className;
+
+    /** 使用的模板(crud单表操作 tree树表操作) */
+    private String tplCategory;
+
+    /** 生成包路径 */
+    @NotBlank(message = "生成包路径不能为空")
+    private String packageName;
+
+    /** 生成模块名 */
+    @NotBlank(message = "生成模块名不能为空")
+    private String moduleName;
+
+    /** 生成业务名 */
+    @NotBlank(message = "生成业务名不能为空")
+    private String businessName;
+
+    /** 生成功能名 */
+    @NotBlank(message = "生成功能名不能为空")
+    private String functionName;
+
+    /** 生成作者 */
+    @NotBlank(message = "作者不能为空")
+    private String functionAuthor;
+
+    /** 主键信息 */
+    private GenTableColumn pkColumn;
+
+    /** 表列信息 */
+    @Valid
+    private List<GenTableColumn> columns;
+
+    /** 其它生成选项 */
+    private String options;
+
+    /** 树编码字段 */
+    private String treeCode;
+
+    /** 树父编码字段 */
+    private String treeParentCode;
+
+    /** 树名称字段 */
+    private String treeName;
+
+    public Long getTableId()
+    {
+        return tableId;
+    }
+
+    public void setTableId(Long tableId)
+    {
+        this.tableId = tableId;
+    }
+
+    public String getTableName()
+    {
+        return tableName;
+    }
+
+    public void setTableName(String tableName)
+    {
+        this.tableName = tableName;
+    }
+
+    public String getTableComment()
+    {
+        return tableComment;
+    }
+
+    public void setTableComment(String tableComment)
+    {
+        this.tableComment = tableComment;
+    }
+
+    public String getClassName()
+    {
+        return className;
+    }
+
+    public void setClassName(String className)
+    {
+        this.className = className;
+    }
+
+    public String getTplCategory()
+    {
+        return tplCategory;
+    }
+
+    public void setTplCategory(String tplCategory)
+    {
+        this.tplCategory = tplCategory;
+    }
+
+    public String getPackageName()
+    {
+        return packageName;
+    }
+
+    public void setPackageName(String packageName)
+    {
+        this.packageName = packageName;
+    }
+
+    public String getModuleName()
+    {
+        return moduleName;
+    }
+
+    public void setModuleName(String moduleName)
+    {
+        this.moduleName = moduleName;
+    }
+
+    public String getBusinessName()
+    {
+        return businessName;
+    }
+
+    public void setBusinessName(String businessName)
+    {
+        this.businessName = businessName;
+    }
+
+    public String getFunctionName()
+    {
+        return functionName;
+    }
+
+    public void setFunctionName(String functionName)
+    {
+        this.functionName = functionName;
+    }
+
+    public String getFunctionAuthor()
+    {
+        return functionAuthor;
+    }
+
+    public void setFunctionAuthor(String functionAuthor)
+    {
+        this.functionAuthor = functionAuthor;
+    }
+
+    public GenTableColumn getPkColumn()
+    {
+        return pkColumn;
+    }
+
+    public void setPkColumn(GenTableColumn pkColumn)
+    {
+        this.pkColumn = pkColumn;
+    }
+
+    public List<GenTableColumn> getColumns()
+    {
+        return columns;
+    }
+
+    public void setColumns(List<GenTableColumn> columns)
+    {
+        this.columns = columns;
+    }
+
+    public String getOptions()
+    {
+        return options;
+    }
+
+    public void setOptions(String options)
+    {
+        this.options = options;
+    }
+
+    public String getTreeCode()
+    {
+        return treeCode;
+    }
+
+    public void setTreeCode(String treeCode)
+    {
+        this.treeCode = treeCode;
+    }
+
+    public String getTreeParentCode()
+    {
+        return treeParentCode;
+    }
+
+    public void setTreeParentCode(String treeParentCode)
+    {
+        this.treeParentCode = treeParentCode;
+    }
+
+    public String getTreeName()
+    {
+        return treeName;
+    }
+
+    public void setTreeName(String treeName)
+    {
+        this.treeName = treeName;
+    }
+
+    public boolean isTree()
+    {
+        return isTree(this.tplCategory);
+    }
+
+    public static boolean isTree(String tplCategory)
+    {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
+    }
+
+    public boolean isCrud()
+    {
+        return isCrud(this.tplCategory);
+    }
+
+    public static boolean isCrud(String tplCategory)
+    {
+        return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
+    }
+}

+ 353 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java

@@ -0,0 +1,353 @@
+package com.ruoyi.generator.domain;
+
+import javax.validation.constraints.NotBlank;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 代码生成业务字段表 gen_table_column
+ * 
+ * @author ruoyi
+ */
+public class GenTableColumn extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 编号 */
+    private Long columnId;
+
+    /** 归属表编号 */
+    private Long tableId;
+
+    /** 列名称 */
+    private String columnName;
+
+    /** 列描述 */
+    private String columnComment;
+
+    /** 列类型 */
+    private String columnType;
+
+    /** JAVA类型 */
+    private String javaType;
+
+    /** JAVA字段名 */
+    @NotBlank(message = "Java属性不能为空")
+    private String javaField;
+
+    /** 是否主键(1是) */
+    private String isPk;
+
+    /** 是否自增(1是) */
+    private String isIncrement;
+
+    /** 是否必填(1是) */
+    private String isRequired;
+
+    /** 是否为插入字段(1是) */
+    private String isInsert;
+
+    /** 是否编辑字段(1是) */
+    private String isEdit;
+
+    /** 是否列表字段(1是) */
+    private String isList;
+
+    /** 是否查询字段(1是) */
+    private String isQuery;
+
+    /** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */
+    private String queryType;
+
+    /** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件) */
+    private String htmlType;
+
+    /** 字典类型 */
+    private String dictType;
+
+    /** 排序 */
+    private Integer sort;
+
+    public void setColumnId(Long columnId)
+    {
+        this.columnId = columnId;
+    }
+
+    public Long getColumnId()
+    {
+        return columnId;
+    }
+
+    public void setTableId(Long tableId)
+    {
+        this.tableId = tableId;
+    }
+
+    public Long getTableId()
+    {
+        return tableId;
+    }
+
+    public void setColumnName(String columnName)
+    {
+        this.columnName = columnName;
+    }
+
+    public String getColumnName()
+    {
+        return columnName;
+    }
+
+    public void setColumnComment(String columnComment)
+    {
+        this.columnComment = columnComment;
+    }
+
+    public String getColumnComment()
+    {
+        return columnComment;
+    }
+
+    public void setColumnType(String columnType)
+    {
+        this.columnType = columnType;
+    }
+
+    public String getColumnType()
+    {
+        return columnType;
+    }
+
+    public void setJavaType(String javaType)
+    {
+        this.javaType = javaType;
+    }
+
+    public String getJavaType()
+    {
+        return javaType;
+    }
+
+    public void setJavaField(String javaField)
+    {
+        this.javaField = javaField;
+    }
+
+    public String getJavaField()
+    {
+        return javaField;
+    }
+
+    public void setIsPk(String isPk)
+    {
+        this.isPk = isPk;
+    }
+
+    public String getIsPk()
+    {
+        return isPk;
+    }
+
+    public boolean isPk()
+    {
+        return isPk(this.isPk);
+    }
+
+    public boolean isPk(String isPk)
+    {
+        return isPk != null && StringUtils.equals("1", isPk);
+    }
+
+    public String getIsIncrement()
+    {
+        return isIncrement;
+    }
+
+    public void setIsIncrement(String isIncrement)
+    {
+        this.isIncrement = isIncrement;
+    }
+
+    public boolean isIncrement()
+    {
+        return isIncrement(this.isIncrement);
+    }
+
+    public boolean isIncrement(String isIncrement)
+    {
+        return isIncrement != null && StringUtils.equals("1", isIncrement);
+    }
+
+    public void setIsRequired(String isRequired)
+    {
+        this.isRequired = isRequired;
+    }
+
+    public String getIsRequired()
+    {
+        return isRequired;
+    }
+
+    public boolean isRequired()
+    {
+        return isRequired(this.isRequired);
+    }
+
+    public boolean isRequired(String isRequired)
+    {
+        return isRequired != null && StringUtils.equals("1", isRequired);
+    }
+
+    public void setIsInsert(String isInsert)
+    {
+        this.isInsert = isInsert;
+    }
+
+    public String getIsInsert()
+    {
+        return isInsert;
+    }
+
+    public boolean isInsert()
+    {
+        return isInsert(this.isInsert);
+    }
+
+    public boolean isInsert(String isInsert)
+    {
+        return isInsert != null && StringUtils.equals("1", isInsert);
+    }
+
+    public void setIsEdit(String isEdit)
+    {
+        this.isEdit = isEdit;
+    }
+
+    public String getIsEdit()
+    {
+        return isEdit;
+    }
+
+    public boolean isEdit()
+    {
+        return isInsert(this.isEdit);
+    }
+
+    public boolean isEdit(String isEdit)
+    {
+        return isEdit != null && StringUtils.equals("1", isEdit);
+    }
+
+    public void setIsList(String isList)
+    {
+        this.isList = isList;
+    }
+
+    public String getIsList()
+    {
+        return isList;
+    }
+
+    public boolean isList()
+    {
+        return isList(this.isList);
+    }
+
+    public boolean isList(String isList)
+    {
+        return isList != null && StringUtils.equals("1", isList);
+    }
+
+    public void setIsQuery(String isQuery)
+    {
+        this.isQuery = isQuery;
+    }
+
+    public String getIsQuery()
+    {
+        return isQuery;
+    }
+
+    public boolean isQuery()
+    {
+        return isQuery(this.isQuery);
+    }
+
+    public boolean isQuery(String isQuery)
+    {
+        return isQuery != null && StringUtils.equals("1", isQuery);
+    }
+
+    public void setQueryType(String queryType)
+    {
+        this.queryType = queryType;
+    }
+
+    public String getQueryType()
+    {
+        return queryType;
+    }
+
+    public String getHtmlType()
+    {
+        return htmlType;
+    }
+
+    public void setHtmlType(String htmlType)
+    {
+        this.htmlType = htmlType;
+    }
+
+    public void setDictType(String dictType)
+    {
+        this.dictType = dictType;
+    }
+
+    public String getDictType()
+    {
+        return dictType;
+    }
+
+    public void setSort(Integer sort)
+    {
+        this.sort = sort;
+    }
+
+    public Integer getSort()
+    {
+        return sort;
+    }
+
+    public boolean isSuperColumn()
+    {
+        return isSuperColumn(this.javaField);
+    }
+
+    public static boolean isSuperColumn(String javaField)
+    {
+        return StringUtils.equalsAnyIgnoreCase(javaField, "createBy", "createTime", "updateBy", "updateTime", "remark");
+    }
+
+    public String readConverterExp()
+    {
+        String remarks = StringUtils.substringBetween(this.columnComment, "(", ")");
+        StringBuffer sb = new StringBuffer();
+        if (StringUtils.isNotEmpty(remarks))
+        {
+            for (String value : remarks.split(" "))
+            {
+                if (StringUtils.isNotEmpty(value))
+                {
+                    Object startStr = value.subSequence(0, 1);
+                    String endStr = value.substring(1);
+                    sb.append("").append(startStr).append("=").append(endStr).append(",");
+                }
+            }
+            return sb.deleteCharAt(sb.length() - 1).toString();
+        }
+        else
+        {
+            return this.columnComment;
+        }
+    }
+}

+ 0 - 103
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/TableInfo.java

@@ -1,103 +0,0 @@
-package com.ruoyi.generator.domain;
-
-import java.util.List;
-import com.ruoyi.common.core.domain.BaseEntity;
-import com.ruoyi.common.utils.StringUtils;
-
-/**
- * ry 数据库表
- * 
- * @author ruoyi
- */
-public class TableInfo extends BaseEntity
-{
-    private static final long serialVersionUID = 1L;
-
-    /** 表名称 */
-    private String tableName;
-
-    /** 表描述 */
-    private String tableComment;
-
-    /** 表的主键列信息 */
-    private ColumnInfo primaryKey;
-
-    /** 表的列名(不包含主键) */
-    private List<ColumnInfo> columns;
-
-    /** 类名(第一个字母大写) */
-    private String className;
-
-    /** 类名(第一个字母小写) */
-    private String classname;
-
-    public String getTableName()
-    {
-        return tableName;
-    }
-
-    public void setTableName(String tableName)
-    {
-        this.tableName = tableName;
-    }
-
-    public String getTableComment()
-    {
-        return tableComment;
-    }
-
-    public void setTableComment(String tableComment)
-    {
-        this.tableComment = tableComment;
-    }
-
-    public List<ColumnInfo> getColumns()
-    {
-        return columns;
-    }
-
-    public ColumnInfo getColumnsLast()
-    {
-        ColumnInfo columnInfo = null;
-        if (StringUtils.isNotNull(columns) && columns.size() > 0)
-        {
-            columnInfo = columns.get(0);
-        }
-        return columnInfo;
-    }
-
-    public void setColumns(List<ColumnInfo> columns)
-    {
-        this.columns = columns;
-    }
-
-    public String getClassName()
-    {
-        return className;
-    }
-
-    public void setClassName(String className)
-    {
-        this.className = className;
-    }
-
-    public String getClassname()
-    {
-        return classname;
-    }
-
-    public void setClassname(String classname)
-    {
-        this.classname = classname;
-    }
-
-    public ColumnInfo getPrimaryKey()
-    {
-        return primaryKey;
-    }
-
-    public void setPrimaryKey(ColumnInfo primaryKey)
-    {
-        this.primaryKey = primaryKey;
-    }
-}

+ 0 - 37
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenMapper.java

@@ -1,37 +0,0 @@
-package com.ruoyi.generator.mapper;
-
-import java.util.List;
-import com.ruoyi.generator.domain.ColumnInfo;
-import com.ruoyi.generator.domain.TableInfo;
-
-/**
- * 代码生成 数据层
- * 
- * @author ruoyi
- */
-public interface GenMapper
-{
-    /**
-     * 查询ry数据库表信息
-     * 
-     * @param tableInfo 表信息
-     * @return 数据库表列表
-     */
-    public List<TableInfo> selectTableList(TableInfo tableInfo);
-
-    /**
-     * 根据表名称查询信息
-     * 
-     * @param tableName 表名称
-     * @return 表信息
-     */
-    public TableInfo selectTableByName(String tableName);
-
-    /**
-     * 根据表名称查询列信息
-     * 
-     * @param tableName 表名称
-     * @return 列信息
-     */
-    public List<ColumnInfo> selectTableColumnsByName(String tableName);
-}

+ 52 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java

@@ -0,0 +1,52 @@
+package com.ruoyi.generator.mapper;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 业务字段 数据层
+ * 
+ * @author ruoyi
+ */
+public interface GenTableColumnMapper
+{
+    /**
+     * 根据表名称查询列信息
+     * 
+     * @param tableName 表名称
+     * @return 列信息
+     */
+    public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
+    
+    /**
+     * 查询业务字段列表
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 业务字段集合
+     */
+    public List<GenTableColumn> selectGenTableColumnListByTableId(GenTableColumn genTableColumn);
+
+    /**
+     * 新增业务字段
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 结果
+     */
+    public int insertGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 修改业务字段
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 结果
+     */
+    public int updateGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 批量删除业务字段
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteGenTableColumnByIds(Long[] ids);
+}

+ 76 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java

@@ -0,0 +1,76 @@
+package com.ruoyi.generator.mapper;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTable;
+
+/**
+ * 业务 数据层
+ * 
+ * @author ruoyi
+ */
+public interface GenTableMapper
+{
+    /**
+     * 查询业务列表
+     * 
+     * @param genTable 业务信息
+     * @return 业务集合
+     */
+    public List<GenTable> selectGenTableList(GenTable genTable);
+
+    /**
+     * 查询据库列表
+     * 
+     * @param genTable 业务信息
+     * @return 数据库表集合
+     */
+    public List<GenTable> selectDbTableList(GenTable genTable);
+
+    /**
+     * 查询据库列表
+     * 
+     * @param tableNames 表名称组
+     * @return 数据库表集合
+     */
+    public List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+    /**
+     * 查询表ID业务信息
+     * 
+     * @param id 业务ID
+     * @return 业务信息
+     */
+    public GenTable selectGenTableById(Long id);
+
+    /**
+     * 查询表名称业务信息
+     * 
+     * @param tableName 表名称
+     * @return 业务信息
+     */
+    public GenTable selectGenTableByName(String tableName);
+
+    /**
+     * 新增业务
+     * 
+     * @param genTable 业务信息
+     * @return 结果
+     */
+    public int insertGenTable(GenTable genTable);
+
+    /**
+     * 修改业务
+     * 
+     * @param genTable 业务信息
+     * @return 结果
+     */
+    public int updateGenTable(GenTable genTable);
+
+    /**
+     * 批量删除业务
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteGenTableByIds(Long[] ids);
+}

+ 0 - 36
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenService.java

@@ -1,36 +0,0 @@
-package com.ruoyi.generator.service;
-
-import java.util.List;
-import com.ruoyi.generator.domain.TableInfo;
-
-/**
- * 代码生成 服务层
- * 
- * @author ruoyi
- */
-public interface IGenService
-{
-    /**
-     * 查询ry数据库表信息
-     * 
-     * @param tableInfo 表信息
-     * @return 数据库表列表
-     */
-    public List<TableInfo> selectTableList(TableInfo tableInfo);
-
-    /**
-     * 生成代码
-     * 
-     * @param tableName 表名称
-     * @return 数据
-     */
-    public byte[] generatorCode(String tableName);
-
-    /**
-     * 批量生成代码
-     * 
-     * @param tableNames 表数组
-     * @return 数据
-     */
-    public byte[] generatorCode(String[] tableNames);
-}

+ 44 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java

@@ -0,0 +1,44 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 业务字段 服务层
+ * 
+ * @author ruoyi
+ */
+public interface IGenTableColumnService
+{
+    /**
+     * 查询业务字段列表
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 业务字段集合
+     */
+    public List<GenTableColumn> selectGenTableColumnListByTableId(GenTableColumn genTableColumn);
+
+    /**
+     * 新增业务字段
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 结果
+     */
+    public int insertGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 修改业务字段
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 结果
+     */
+    public int updateGenTableColumn(GenTableColumn genTableColumn);
+
+    /**
+     * 删除业务字段信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public int deleteGenTableColumnByIds(String ids);
+}

+ 100 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java

@@ -0,0 +1,100 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import java.util.Map;
+import com.ruoyi.generator.domain.GenTable;
+
+/**
+ * 业务 服务层
+ * 
+ * @author ruoyi
+ */
+public interface IGenTableService
+{
+    /**
+     * 查询业务列表
+     * 
+     * @param genTable 业务信息
+     * @return 业务集合
+     */
+    public List<GenTable> selectGenTableList(GenTable genTable);
+
+    /**
+     * 查询据库列表
+     * 
+     * @param genTable 业务信息
+     * @return 数据库表集合
+     */
+    public List<GenTable> selectDbTableList(GenTable genTable);
+
+    /**
+     * 查询据库列表
+     * 
+     * @param tableNames 表名称组
+     * @return 数据库表集合
+     */
+    public List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+    /**
+     * 查询业务信息
+     * 
+     * @param id 业务ID
+     * @return 业务信息
+     */
+    public GenTable selectGenTableById(Long id);
+
+    /**
+     * 修改业务
+     * 
+     * @param genTable 业务信息
+     * @return 结果
+     */
+    public void updateGenTable(GenTable genTable);
+
+    /**
+     * 删除业务信息
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    public void deleteGenTableByIds(String ids);
+
+    /**
+     * 导入表结构
+     * 
+     * @param tableList 导入表列表
+     * @param operName 操作人员
+     */
+    public void importGenTable(List<GenTable> tableList, String operName);
+
+    /**
+     * 预览代码
+     * 
+     * @param tableId 表编号
+     * @return 预览数据列表
+     */
+    public Map<String, String> previewCode(Long tableId);
+
+    /**
+     * 生成代码
+     * 
+     * @param tableName 表名称
+     * @return 数据
+     */
+    public byte[] generatorCode(String tableName);
+
+    /**
+     * 批量生成代码
+     * 
+     * @param tableNames 表数组
+     * @return 数据
+     */
+    public byte[] generatorCode(String[] tableNames);
+
+    /**
+     * 修改保存参数校验
+     * 
+     * @param genTable 业务信息
+     */
+    public void validateEdit(GenTable genTable);
+}

+ 0 - 135
ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenServiceImpl.java

@@ -1,135 +0,0 @@
-package com.ruoyi.generator.service.impl;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-import org.apache.commons.io.IOUtils;
-import org.apache.velocity.Template;
-import org.apache.velocity.VelocityContext;
-import org.apache.velocity.app.Velocity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.generator.config.GenConfig;
-import com.ruoyi.generator.domain.ColumnInfo;
-import com.ruoyi.generator.domain.TableInfo;
-import com.ruoyi.generator.mapper.GenMapper;
-import com.ruoyi.generator.service.IGenService;
-import com.ruoyi.generator.util.GenUtils;
-import com.ruoyi.generator.util.VelocityInitializer;
-
-/**
- * 代码生成 服务层处理
- * 
- * @author ruoyi
- */
-@Service
-public class GenServiceImpl implements IGenService
-{
-    private static final Logger log = LoggerFactory.getLogger(GenServiceImpl.class);
-
-    @Autowired
-    private GenMapper genMapper;
-
-    /**
-     * 查询ry数据库表信息
-     * 
-     * @param tableInfo 表信息
-     * @return 数据库表列表
-     */
-    @Override
-    public List<TableInfo> selectTableList(TableInfo tableInfo)
-    {
-        return genMapper.selectTableList(tableInfo);
-    }
-
-    /**
-     * 生成代码
-     * 
-     * @param tableName 表名称
-     * @return 数据
-     */
-    @Override
-    public byte[] generatorCode(String tableName)
-    {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        ZipOutputStream zip = new ZipOutputStream(outputStream);
-        generatorCode(tableName, zip);
-        IOUtils.closeQuietly(zip);
-        return outputStream.toByteArray();
-    }
-
-    /**
-     * 批量生成代码
-     * 
-     * @param tableNames 表数组
-     * @return 数据
-     */
-    @Override
-    public byte[] generatorCode(String[] tableNames)
-    {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        ZipOutputStream zip = new ZipOutputStream(outputStream);
-        for (String tableName : tableNames)
-        {
-            generatorCode(tableName, zip);
-        }
-        IOUtils.closeQuietly(zip);
-        return outputStream.toByteArray();
-    }
-
-    /**
-     * 查询表信息并生成代码
-     */
-    private void generatorCode(String tableName, ZipOutputStream zip)
-    {
-        // 查询表信息
-        TableInfo table = genMapper.selectTableByName(tableName);
-        // 查询列信息
-        List<ColumnInfo> columns = genMapper.selectTableColumnsByName(tableName);
-
-        // 表名转换成Java属性名
-        String className = GenUtils.tableToJava(table.getTableName());
-        table.setClassName(className);
-        table.setClassname(StringUtils.uncapitalize(className));
-        // 列信息
-        table.setColumns(GenUtils.transColums(columns));
-        // 设置主键
-        table.setPrimaryKey(table.getColumnsLast());
-
-        VelocityInitializer.initVelocity();
-
-        String packageName = GenConfig.getPackageName();
-        String moduleName = GenUtils.getModuleName(packageName);
-
-        VelocityContext context = GenUtils.getVelocityContext(table);
-
-        // 获取模板列表
-        List<String> templates = GenUtils.getTemplates();
-        for (String template : templates)
-        {
-            // 渲染模板
-            StringWriter sw = new StringWriter();
-            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
-            tpl.merge(context, sw);
-            try
-            {
-                // 添加到zip
-                zip.putNextEntry(new ZipEntry(GenUtils.getFileName(template, table, moduleName)));
-                IOUtils.write(sw.toString(), zip, Constants.UTF8);
-                IOUtils.closeQuietly(sw);
-                zip.closeEntry();
-            }
-            catch (IOException e)
-            {
-                log.error("渲染模板失败,表名:" + table.getTableName(), e);
-            }
-        }
-    }
-}

+ 69 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableColumnServiceImpl.java

@@ -0,0 +1,69 @@
+package com.ruoyi.generator.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+import com.ruoyi.generator.service.IGenTableColumnService;
+
+/**
+ * 业务字段 服务层实现
+ * 
+ * @author ruoyi
+ */
+@Service
+public class GenTableColumnServiceImpl implements IGenTableColumnService
+{
+    @Autowired
+    private GenTableColumnMapper genTableColumnMapper;
+
+    /**
+     * 查询业务字段列表
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 业务字段集合
+     */
+    @Override
+    public List<GenTableColumn> selectGenTableColumnListByTableId(GenTableColumn genTableColumn)
+    {
+        return genTableColumnMapper.selectGenTableColumnListByTableId(genTableColumn);
+    }
+
+    /**
+     * 新增业务字段
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 结果
+     */
+    @Override
+    public int insertGenTableColumn(GenTableColumn genTableColumn)
+    {
+        return genTableColumnMapper.insertGenTableColumn(genTableColumn);
+    }
+
+    /**
+     * 修改业务字段
+     * 
+     * @param genTableColumn 业务字段信息
+     * @return 结果
+     */
+    @Override
+    public int updateGenTableColumn(GenTableColumn genTableColumn)
+    {
+        return genTableColumnMapper.updateGenTableColumn(genTableColumn);
+    }
+
+    /**
+     * 删除业务字段对象
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    public int deleteGenTableColumnByIds(String ids)
+    {
+        return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
+    }
+}

+ 337 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/service/impl/GenTableServiceImpl.java

@@ -0,0 +1,337 @@
+package com.ruoyi.generator.service.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.BusinessException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+import com.ruoyi.generator.mapper.GenTableMapper;
+import com.ruoyi.generator.service.IGenTableService;
+import com.ruoyi.generator.util.GenUtils;
+import com.ruoyi.generator.util.VelocityInitializer;
+import com.ruoyi.generator.util.VelocityUtils;
+
+/**
+ * 业务 服务层实现
+ * 
+ * @author ruoyi
+ */
+@Service
+public class GenTableServiceImpl implements IGenTableService
+{
+    private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
+
+    @Autowired
+    private GenTableMapper genTableMapper;
+
+    @Autowired
+    private GenTableColumnMapper genTableColumnMapper;
+
+    /**
+     * 查询业务信息
+     * 
+     * @param id 业务ID
+     * @return 业务信息
+     */
+    @Override
+    public GenTable selectGenTableById(Long id)
+    {
+        GenTable genTable = genTableMapper.selectGenTableById(id);
+        setTableFromOptions(genTable);
+        return genTable;
+    }
+
+    /**
+     * 查询业务列表
+     * 
+     * @param genTable 业务信息
+     * @return 业务集合
+     */
+    @Override
+    public List<GenTable> selectGenTableList(GenTable genTable)
+    {
+        return genTableMapper.selectGenTableList(genTable);
+    }
+
+    /**
+     * 查询据库列表
+     * 
+     * @param genTable 业务信息
+     * @return 数据库表集合
+     */
+    public List<GenTable> selectDbTableList(GenTable genTable)
+    {
+        return genTableMapper.selectDbTableList(genTable);
+    }
+
+    /**
+     * 查询据库列表
+     * 
+     * @param tableNames 表名称组
+     * @return 数据库表集合
+     */
+    public List<GenTable> selectDbTableListByNames(String[] tableNames)
+    {
+        return genTableMapper.selectDbTableListByNames(tableNames);
+    }
+
+    /**
+     * 修改业务
+     * 
+     * @param genTable 业务信息
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public void updateGenTable(GenTable genTable)
+    {
+        String options = JSON.toJSONString(genTable.getParams());
+        genTable.setOptions(options);
+        int row = genTableMapper.updateGenTable(genTable);
+        if (row > 0)
+        {
+            for (GenTableColumn cenTableColumn : genTable.getColumns())
+            {
+                genTableColumnMapper.updateGenTableColumn(cenTableColumn);
+            }
+        }
+    }
+
+    /**
+     * 删除业务对象
+     * 
+     * @param ids 需要删除的数据ID
+     * @return 结果
+     */
+    @Override
+    @Transactional
+    public void deleteGenTableByIds(String ids)
+    {
+        genTableMapper.deleteGenTableByIds(Convert.toLongArray(ids));
+        genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
+    }
+
+    /**
+     * 导入表结构
+     * 
+     * @param tableList 导入表列表
+     * @param operName 操作人员
+     */
+    @Override
+    @Transactional
+    public void importGenTable(List<GenTable> tableList, String operName)
+    {
+        for (GenTable table : tableList)
+        {
+            try
+            {
+                String tableName = table.getTableName();
+                GenUtils.initTable(table, operName);
+                int row = genTableMapper.insertGenTable(table);
+                if (row > 0)
+                {
+                    // 保存列信息
+                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+                    for (GenTableColumn column : genTableColumns)
+                    {
+                        GenUtils.initColumnField(column, table);
+                        genTableColumnMapper.insertGenTableColumn(column);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                log.error("表名 " + table.getTableName() + " 导入失败:", e);
+            }
+        }
+    }
+
+    /**
+     * 预览代码
+     * 
+     * @param tableId 表编号
+     * @return 预览数据列表
+     */
+    public Map<String, String> previewCode(Long tableId)
+    {
+        Map<String, String> dataMap = new LinkedHashMap<>();
+        // 查询表信息
+        GenTable table = genTableMapper.selectGenTableById(tableId);
+        // 查询列信息
+        List<GenTableColumn> columns = table.getColumns();
+        setPkColumn(table, columns);
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 获取模板列表
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
+        for (String template : templates)
+        {
+            // 渲染模板
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            dataMap.put(template, sw.toString());
+        }
+        return dataMap;
+    }
+
+    /**
+     * 生成代码
+     * 
+     * @param tableName 表名称
+     * @return 数据
+     */
+    @Override
+    public byte[] generatorCode(String tableName)
+    {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        generatorCode(tableName, zip);
+        IOUtils.closeQuietly(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 批量生成代码
+     * 
+     * @param tableNames 表数组
+     * @return 数据
+     */
+    @Override
+    public byte[] generatorCode(String[] tableNames)
+    {
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        for (String tableName : tableNames)
+        {
+            generatorCode(tableName, zip);
+        }
+        IOUtils.closeQuietly(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 查询表信息并生成代码
+     */
+    private void generatorCode(String tableName, ZipOutputStream zip)
+    {
+        // 查询表信息
+        GenTable table = genTableMapper.selectGenTableByName(tableName);
+        // 查询列信息
+        List<GenTableColumn> columns = table.getColumns();
+        setPkColumn(table, columns);
+
+        VelocityInitializer.initVelocity();
+
+        VelocityContext context = VelocityUtils.prepareContext(table);
+
+        // 获取模板列表
+        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
+        for (String template : templates)
+        {
+            // 渲染模板
+            StringWriter sw = new StringWriter();
+            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+            tpl.merge(context, sw);
+            try
+            {
+                // 添加到zip
+                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
+                IOUtils.write(sw.toString(), zip, Constants.UTF8);
+                IOUtils.closeQuietly(sw);
+                zip.closeEntry();
+            }
+            catch (IOException e)
+            {
+                log.error("渲染模板失败,表名:" + table.getTableName(), e);
+            }
+        }
+    }
+
+    /**
+     * 修改保存参数校验
+     * 
+     * @param genTable 业务信息
+     */
+    public void validateEdit(GenTable genTable)
+    {
+        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
+        {
+            String options = JSON.toJSONString(genTable.getParams());
+            JSONObject paramsObj = JSONObject.parseObject(options);
+            if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
+            {
+                throw new BusinessException("树编码字段不能为空");
+            }
+            else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
+            {
+                throw new BusinessException("树父编码字段不能为空");
+            }
+            else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
+            {
+                throw new BusinessException("树名称字段不能为空");
+            }
+        }
+    }
+
+    /**
+     * 设置主键列信息
+     * 
+     * @param genTable 业务表信息
+     * @param columns 业务字段列表
+     */
+    public void setPkColumn(GenTable table, List<GenTableColumn> columns)
+    {
+        for (GenTableColumn column : columns)
+        {
+            if (column.isPk())
+            {
+                table.setPkColumn(column);
+                break;
+            }
+        }
+    }
+
+    /**
+     * 设置代码生成其他选项值
+     * 
+     * @param genTable 设置后的生成对象
+     */
+    public void setTableFromOptions(GenTable genTable)
+    {
+        JSONObject paramsObj = JSONObject.parseObject(genTable.getOptions());
+        if (StringUtils.isNotNull(paramsObj))
+        {
+            String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
+            String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
+            String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+            genTable.setTreeCode(treeCode);
+            genTable.setTreeParentCode(treeParentCode);
+            genTable.setTreeName(treeName);
+        }
+    }
+}

+ 134 - 173
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java

@@ -1,16 +1,11 @@
 package com.ruoyi.generator.util;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.velocity.VelocityContext;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.utils.DateUtils;
+import java.util.Arrays;
+import com.ruoyi.common.constant.GenConstants;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.generator.config.GenConfig;
-import com.ruoyi.generator.domain.ColumnInfo;
-import com.ruoyi.generator.domain.TableInfo;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
 
 /**
  * 代码生成器 工具类
@@ -19,161 +14,114 @@ import com.ruoyi.generator.domain.TableInfo;
  */
 public class GenUtils
 {
-    /** 项目空间路径 */
-    private static final String PROJECT_PATH = getProjectPath();
-
-    /** mybatis空间路径 */
-    private static final String MYBATIS_PATH = "main/resources/mapper";
-
-    /** html空间路径 */
-    private static final String TEMPLATES_PATH = "main/resources/templates";
-
-    /** 类型转换 */
-    public static Map<String, String> javaTypeMap = new HashMap<String, String>();
-
-    /**
-     * 设置列信息
-     */
-    public static List<ColumnInfo> transColums(List<ColumnInfo> columns)
-    {
-        // 列信息
-        List<ColumnInfo> columsList = new ArrayList<>();
-        for (ColumnInfo column : columns)
-        {
-            // 列名转换成Java属性名
-            String attrName = StringUtils.convertToCamelCase(column.getColumnName());
-            column.setAttrName(attrName);
-            column.setAttrname(StringUtils.uncapitalize(attrName));
-            column.setExtra(column.getExtra());
-
-            // 列的数据类型,转换成Java类型
-            String attrType = javaTypeMap.get(column.getDataType());
-            column.setAttrType(attrType);
-
-            columsList.add(column);
-        }
-        return columsList;
-    }
-
-    /**
-     * 获取模板信息
-     * 
-     * @return 模板列表
-     */
-    public static VelocityContext getVelocityContext(TableInfo table)
-    {
-        // java对象数据传递到模板文件vm
-        VelocityContext velocityContext = new VelocityContext();
-        String packageName = GenConfig.getPackageName();
-        velocityContext.put("tableName", table.getTableName());
-        velocityContext.put("tableComment", replaceKeyword(table.getTableComment()));
-        velocityContext.put("primaryKey", table.getPrimaryKey());
-        velocityContext.put("className", table.getClassName());
-        velocityContext.put("classname", table.getClassname());
-        velocityContext.put("moduleName", getModuleName(packageName));
-        velocityContext.put("columns", table.getColumns());
-        velocityContext.put("basePackage", getBasePackage(packageName));
-        velocityContext.put("package", packageName);
-        velocityContext.put("author", GenConfig.getAuthor());
-        velocityContext.put("datetime", DateUtils.getDate());
-        return velocityContext;
-    }
-
     /**
-     * 获取模板信息
-     * 
-     * @return 模板列表
+     * 初始化表信息
      */
-    public static List<String> getTemplates()
+    public static void initTable(GenTable genTable, String operName)
     {
-        List<String> templates = new ArrayList<String>();
-        templates.add("vm/java/domain.java.vm");
-        templates.add("vm/java/Mapper.java.vm");
-        templates.add("vm/java/Service.java.vm");
-        templates.add("vm/java/ServiceImpl.java.vm");
-        templates.add("vm/java/Controller.java.vm");
-        templates.add("vm/xml/Mapper.xml.vm");
-        templates.add("vm/html/list.html.vm");
-        templates.add("vm/html/add.html.vm");
-        templates.add("vm/html/edit.html.vm");
-        templates.add("vm/sql/sql.vm");
-        return templates;
+        genTable.setClassName(StringUtils.convertToCamelCase(genTable.getTableName()));
+        genTable.setPackageName(GenConfig.getPackageName());
+        genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
+        genTable.setBusinessName(getBusinessName(genTable.getTableName()));
+        genTable.setFunctionName(replaceText(genTable.getTableComment()));
+        genTable.setFunctionAuthor(GenConfig.getAuthor());
+        genTable.setCreateBy(operName);
     }
 
     /**
-     * 表名转换成Java类名
+     * 初始化列属性字段
      */
-    public static String tableToJava(String tableName)
+    public static void initColumnField(GenTableColumn column, GenTable table)
     {
-        String autoRemovePre = GenConfig.getAutoRemovePre();
-        String tablePrefix = GenConfig.getTablePrefix();
-        if (Constants.AUTO_REOMVE_PRE.equals(autoRemovePre) && StringUtils.isNotEmpty(tablePrefix))
+        String dataType = getDbType(column.getColumnType());
+        String columnName = column.getColumnName();
+        column.setTableId(table.getTableId());
+        column.setCreateBy(table.getCreateBy());
+        // 设置java字段名
+        column.setJavaField(StringUtils.toCamelCase(columnName));
+
+        if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType))
         {
-            tableName = tableName.replaceFirst(tablePrefix, "");
+            column.setJavaType(GenConstants.TYPE_STRING);
+            // 字符串长度超过500设置为文本域
+            Integer columnLength = getColumnLength(column.getColumnType());
+            String htmlType = columnLength >= 500 ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
+            column.setHtmlType(htmlType);
         }
-        return StringUtils.convertToCamelCase(tableName);
-    }
-
-    /**
-     * 获取文件名
-     */
-    public static String getFileName(String template, TableInfo table, String moduleName)
-    {
-        // 小写类名
-        String classname = table.getClassname();
-        // 大写类名
-        String className = table.getClassName();
-        String javaPath = PROJECT_PATH;
-        String mybatisPath = MYBATIS_PATH + "/" + moduleName + "/" + className;
-        String htmlPath = TEMPLATES_PATH + "/" + moduleName + "/" + classname;
-
-        if (template.contains("domain.java.vm"))
+        else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
         {
-            return javaPath + "domain" + "/" + className + ".java";
+            column.setJavaType(GenConstants.TYPE_DATE);
+            column.setHtmlType(GenConstants.HTML_DATETIME);
         }
-
-        if (template.contains("Mapper.java.vm"))
+        else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
         {
-            return javaPath + "mapper" + "/" + className + "Mapper.java";
+            column.setHtmlType(GenConstants.HTML_INPUT);
+
+            // 如果是浮点型
+            String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
+            if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
+            {
+                column.setJavaType(GenConstants.TYPE_DOUBLE);
+            }
+            // 如果是整形
+            else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
+            {
+                column.setJavaType(GenConstants.TYPE_INTEGER);
+            }
+            // 长整形
+            else
+            {
+                column.setJavaType(GenConstants.TYPE_LONG);
+            }
         }
 
-        if (template.contains("Service.java.vm"))
-        {
-            return javaPath + "service" + "/" + "I" + className + "Service.java";
-        }
+        // 插入字段(默认所有字段都需要插入)
+        column.setIsInsert(GenConstants.REQUIRE);
 
-        if (template.contains("ServiceImpl.java.vm"))
+        // 编辑字段
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
         {
-            return javaPath + "service" + "/impl/" + className + "ServiceImpl.java";
+            column.setIsEdit(GenConstants.REQUIRE);
         }
-
-        if (template.contains("Controller.java.vm"))
+        // 列表字段
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
         {
-            return javaPath + "controller" + "/" + className + "Controller.java";
+            column.setIsList(GenConstants.REQUIRE);
         }
-
-        if (template.contains("Mapper.xml.vm"))
+        // 查询字段
+        if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
         {
-            return mybatisPath + "Mapper.xml";
+            column.setIsQuery(GenConstants.REQUIRE);
         }
 
-        if (template.contains("list.html.vm"))
-        {
-            return htmlPath + "/" + classname + ".html";
-        }
-        if (template.contains("add.html.vm"))
+        // 查询字段类型
+        if (StringUtils.endsWithIgnoreCase(columnName, "name"))
         {
-            return htmlPath + "/" + "add.html";
+            column.setQueryType(GenConstants.QUERY_LIKE);
         }
-        if (template.contains("edit.html.vm"))
+        // 状态字段设置单选框
+        if (StringUtils.endsWithIgnoreCase(columnName, "status"))
         {
-            return htmlPath + "/" + "edit.html";
+            column.setHtmlType(GenConstants.HTML_RADIO);
         }
-        if (template.contains("sql.vm"))
+        // 类型&性别字段设置下拉框
+        else if (StringUtils.endsWithIgnoreCase(columnName, "type")
+                || StringUtils.endsWithIgnoreCase(columnName, "sex"))
         {
-            return classname + "Menu.sql";
+            column.setHtmlType(GenConstants.HTML_SELECT);
         }
-        return null;
+    }
+
+    /**
+     * 校验数组是否包含指定值
+     * 
+     * @param arr 数组
+     * @param targetValue 值
+     * @return 是否包含
+     */
+    public static boolean arraysContains(String[] arr, String targetValue)
+    {
+        return Arrays.asList(arr).contains(targetValue);
     }
 
     /**
@@ -190,52 +138,65 @@ public class GenUtils
         return moduleName;
     }
 
-    public static String getBasePackage(String packageName)
+    /**
+     * 获取业务名
+     * 
+     * @param tableName 表名
+     * @return 业务名
+     */
+    public static String getBusinessName(String tableName)
     {
-        int lastIndex = packageName.lastIndexOf(".");
-        String basePackage = StringUtils.substring(packageName, 0, lastIndex);
-        return basePackage;
+        int lastIndex = tableName.lastIndexOf("_");
+        int nameLength = tableName.length();
+        String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength);
+        return businessName;
     }
 
-    public static String getProjectPath()
+    /**
+     * 关键字替换
+     * 
+     * @param name 需要被替换的名字
+     * @return 替换后的名字
+     */
+    public static String replaceText(String text)
     {
-        String packageName = GenConfig.getPackageName();
-        StringBuffer projectPath = new StringBuffer();
-        projectPath.append("main/java/");
-        projectPath.append(packageName.replace(".", "/"));
-        projectPath.append("/");
-        return projectPath.toString();
+        return text.replaceAll("(?:表|若依)", "");
     }
 
-    public static String replaceKeyword(String keyword)
+    /**
+     * 获取数据库类型字段
+     * 
+     * @param columnType 列类型
+     * @return 截取后的列类型
+     */
+    public static String getDbType(String columnType)
     {
-        String keyName = keyword.replaceAll("(?:表|信息|管理)", "");
-        return keyName;
+        if (StringUtils.indexOf(columnType, "(") > 0)
+        {
+            return StringUtils.substringBefore(columnType, "(");
+        }
+        else
+        {
+            return columnType;
+        }
     }
 
-    static
+    /**
+     * 获取字段长度
+     * 
+     * @param columnType 列类型
+     * @return 截取后的列类型
+     */
+    public static Integer getColumnLength(String columnType)
     {
-        javaTypeMap.put("tinyint", "Integer");
-        javaTypeMap.put("smallint", "Integer");
-        javaTypeMap.put("mediumint", "Integer");
-        javaTypeMap.put("int", "Integer");
-        javaTypeMap.put("number", "Integer");
-        javaTypeMap.put("integer", "integer");
-        javaTypeMap.put("bigint", "Long");
-        javaTypeMap.put("float", "Float");
-        javaTypeMap.put("double", "Double");
-        javaTypeMap.put("decimal", "BigDecimal");
-        javaTypeMap.put("bit", "Boolean");
-        javaTypeMap.put("char", "String");
-        javaTypeMap.put("varchar", "String");
-        javaTypeMap.put("varchar2", "String");
-        javaTypeMap.put("tinytext", "String");
-        javaTypeMap.put("text", "String");
-        javaTypeMap.put("mediumtext", "String");
-        javaTypeMap.put("longtext", "String");
-        javaTypeMap.put("time", "Date");
-        javaTypeMap.put("date", "Date");
-        javaTypeMap.put("datetime", "Date");
-        javaTypeMap.put("timestamp", "Date");
+        if (StringUtils.indexOf(columnType, "(") > 0)
+        {
+            String length = StringUtils.substringBetween(columnType, "(", ")");
+            return Integer.valueOf(length);
+        }
+        else
+        {
+            return 0;
+        }
     }
-}
+}

+ 1 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java

@@ -20,8 +20,7 @@ public class VelocityInitializer
         try
         {
             // 加载classpath目录下的vm文件
-            p.setProperty("file.resource.loader.class",
-                    "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+            p.setProperty("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
             // 定义字符集
             p.setProperty(Velocity.ENCODING_DEFAULT, Constants.UTF8);
             p.setProperty(Velocity.OUTPUT_ENCODING, Constants.UTF8);

+ 315 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java

@@ -0,0 +1,315 @@
+package com.ruoyi.generator.util;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.velocity.VelocityContext;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+public class VelocityUtils
+{
+    /** 项目空间路径 */
+    private static final String PROJECT_PATH = "main/java";
+
+    /** mybatis空间路径 */
+    private static final String MYBATIS_PATH = "main/resources/mapper";
+
+    /** html空间路径 */
+    private static final String TEMPLATES_PATH = "main/resources/templates";
+
+    /**
+     * 设置模板变量信息
+     * 
+     * @return 模板列表
+     */
+    public static VelocityContext prepareContext(GenTable genTable)
+    {
+        String moduleName = genTable.getModuleName();
+        String businessName = genTable.getBusinessName();
+        String packageName = genTable.getPackageName();
+        String tplCategory = genTable.getTplCategory();
+
+        VelocityContext velocityContext = new VelocityContext();
+        velocityContext.put("tplCategory", genTable.getTplCategory());
+        velocityContext.put("tableName", genTable.getTableName());
+        velocityContext.put("functionName", genTable.getFunctionName());
+        velocityContext.put("ClassName", genTable.getClassName());
+        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
+        velocityContext.put("moduleName", genTable.getModuleName());
+        velocityContext.put("businessName", genTable.getBusinessName());
+        velocityContext.put("basePackage", getPackagePrefix(packageName));
+        velocityContext.put("packageName", packageName);
+        velocityContext.put("author", genTable.getFunctionAuthor());
+        velocityContext.put("datetime", DateUtils.getDate());
+        velocityContext.put("pkColumn", genTable.getPkColumn());
+        velocityContext.put("importList", getImportList(genTable.getColumns()));
+        velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
+        velocityContext.put("columns", genTable.getColumns());
+        velocityContext.put("table", genTable);
+        if (GenConstants.TPL_TREE.equals(tplCategory))
+        {
+            setTreeVelocityContext(velocityContext, genTable);
+        }
+        return velocityContext;
+    }
+
+    public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSONObject.parseObject(options);
+        String treeCode = getTreecode(paramsObj);
+        String treeParentCode = getTreeParentCode(paramsObj);
+        String treeName = getTreeName(paramsObj);
+
+        context.put("treeCode", treeCode);
+        context.put("treeParentCode", treeParentCode);
+        context.put("treeName", treeName);
+        context.put("expandColumn", getExpandColumn(genTable));
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
+        {
+            context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+        }
+    }
+
+    /**
+     * 获取模板信息
+     * 
+     * @return 模板列表
+     */
+    public static List<String> getTemplateList(String tplCategory)
+    {
+        List<String> templates = new ArrayList<String>();
+        templates.add("vm/java/domain.java.vm");
+        templates.add("vm/java/mapper.java.vm");
+        templates.add("vm/java/service.java.vm");
+        templates.add("vm/java/serviceImpl.java.vm");
+        templates.add("vm/java/controller.java.vm");
+        templates.add("vm/xml/mapper.xml.vm");
+        if (GenConstants.TPL_CRUD.equals(tplCategory))
+        {
+            templates.add("vm/html/list.html.vm");
+        }
+        else if (GenConstants.TPL_TREE.equals(tplCategory))
+        {
+            templates.add("vm/html/tree.html.vm");
+            templates.add("vm/html/list-tree.html.vm");
+        }
+        templates.add("vm/html/add.html.vm");
+        templates.add("vm/html/edit.html.vm");
+        templates.add("vm/sql/sql.vm");
+        return templates;
+    }
+
+    /**
+     * 获取文件名
+     */
+    public static String getFileName(String template, GenTable genTable)
+    {
+        // 文件名称
+        String fileName = "";
+        // 包路径
+        String packageName = genTable.getPackageName();
+        // 模块名
+        String moduleName = genTable.getModuleName();
+        // 大写类名
+        String className = genTable.getClassName();
+        // 业务名称
+        String businessName = genTable.getBusinessName();
+
+        String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
+        String mybatisPath = MYBATIS_PATH + "/" + moduleName;
+        String htmlPath = TEMPLATES_PATH + "/" + moduleName + "/" + businessName;
+
+        if (template.contains("domain.java.vm"))
+        {
+            fileName = StringUtils.format("{}/domain/{}.java ", javaPath, className);
+        }
+        else if (template.contains("mapper.java.vm"))
+        {
+            fileName = StringUtils.format("{}/mapper/{}Mapper.java ", javaPath, className);
+        }
+        else if (template.contains("service.java.vm"))
+        {
+            fileName = StringUtils.format("{}/service/I{}Service.java ", javaPath, className);
+        }
+        else if (template.contains("serviceImpl.java.vm"))
+        {
+            fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java ", javaPath, className);
+        }
+        else if (template.contains("controller.java.vm"))
+        {
+            fileName = StringUtils.format("{}/controller/{}Controller.java ", javaPath, className);
+        }
+        else if (template.contains("mapper.xml.vm"))
+        {
+            fileName = StringUtils.format("{}/{}Mapper.xml ", mybatisPath, className);
+        }
+        else if (template.contains("list.html.vm"))
+        {
+            fileName = StringUtils.format("{}/{}.html", htmlPath, businessName);
+        }
+        else if (template.contains("list-tree.html.vm"))
+        {
+            fileName = StringUtils.format("{}/{}.html", htmlPath, businessName);
+        }
+        else if (template.contains("tree.html.vm"))
+        {
+            fileName = StringUtils.format("{}/tree.html", htmlPath);
+        }
+        else if (template.contains("add.html.vm"))
+        {
+            fileName = StringUtils.format("{}/add.html", htmlPath);
+        }
+        else if (template.contains("edit.html.vm"))
+        {
+            fileName = StringUtils.format("{}/edit.html", htmlPath);
+        }
+        else if (template.contains("sql.vm"))
+        {
+            fileName = businessName + "Menu.sql";
+        }
+        return fileName;
+    }
+
+    /**
+     * 获取项目文件路径
+     * 
+     * @return 路径
+     */
+    public static String getProjectPath()
+    {
+        String packageName = GenConfig.getPackageName();
+        StringBuffer projectPath = new StringBuffer();
+        projectPath.append("main/java/");
+        projectPath.append(packageName.replace(".", "/"));
+        projectPath.append("/");
+        return projectPath.toString();
+    }
+
+    /**
+     * 获取包前缀
+     * 
+     * @param packageName 包名称
+     * @return 包前缀名称
+     */
+    public static String getPackagePrefix(String packageName)
+    {
+        int lastIndex = packageName.lastIndexOf(".");
+        String basePackage = StringUtils.substring(packageName, 0, lastIndex);
+        return basePackage;
+    }
+
+    /**
+     * 根据列类型获取导入包
+     * 
+     * @param column 列集合
+     * @return 返回需要导入的包列表
+     */
+    public static HashSet<String> getImportList(List<GenTableColumn> columns)
+    {
+        HashSet<String> importList = new HashSet<String>();
+        for (GenTableColumn column : columns)
+        {
+            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType()))
+            {
+                importList.add("java.util.Date");
+            }
+            else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType()))
+            {
+                importList.add("java.math.BigDecimal");
+            }
+        }
+        return importList;
+    }
+
+    /**
+     * 获取权限前缀
+     * 
+     * @param moduleName 模块名称
+     * @param businessName 业务名称
+     * @return 返回权限前缀
+     */
+    public static String getPermissionPrefix(String moduleName, String businessName)
+    {
+        return StringUtils.format("{}:{}", moduleName, businessName);
+
+    }
+
+    /**
+     * 获取树编码
+     * 
+     * @param options 生成其他选项
+     * @return 树编码
+     */
+    public static String getTreecode(JSONObject paramsObj)
+    {
+        if (paramsObj.containsKey(GenConstants.TREE_CODE))
+        {
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
+        }
+        return "";
+    }
+
+    /**
+     * 获取树父编码
+     * 
+     * @param options 生成其他选项
+     * @return 树父编码
+     */
+    public static String getTreeParentCode(JSONObject paramsObj)
+    {
+        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
+        {
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+        }
+        return "";
+    }
+
+    /**
+     * 获取树名称
+     * 
+     * @param options 生成其他选项
+     * @return 树名称
+     */
+    public static String getTreeName(JSONObject paramsObj)
+    {
+        if (paramsObj.containsKey(GenConstants.TREE_NAME))
+        {
+            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
+        }
+        return "";
+    }
+
+    /**
+     * 获取需要在哪一列上面显示展开按钮
+     * 
+     * @param genTable 业务表对象
+     * @return 展开按钮列序号
+     */
+    public static int getExpandColumn(GenTable genTable)
+    {
+        String options = genTable.getOptions();
+        JSONObject paramsObj = JSONObject.parseObject(options);
+        String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+        int num = 0;
+        for (GenTableColumn column : genTable.getColumns())
+        {
+            if (column.isList())
+            {
+                num++;
+                String columnName = column.getColumnName();
+                if (columnName.equals(treeName))
+                {
+                    break;
+                }
+            }
+        }
+        return num;
+    }
+}

+ 0 - 52
ruoyi-generator/src/main/resources/mapper/generator/GenMapper.xml

@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper
-PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
-"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.generator.mapper.GenMapper">
-
-	<resultMap type="TableInfo" id="TableInfoResult">
-		<id     property="tableName"      column="table_name"      />
-		<result property="tableComment"   column="table_comment"   />
-		<result property="createTime"     column="create_time"     />
-		<result property="updateTime"     column="update_time"     />
-	</resultMap>
-	
-	<resultMap type="ColumnInfo" id="ColumnInfoResult">
-		<id     property="columnName"     column="column_name"      />
-		<result property="dataType"       column="data_type"        />
-		<result property="columnComment"  column="column_comment"   />
-	</resultMap>
-	
-	<sql id="selectGenVo">
-        select table_name, table_comment, create_time, update_time from information_schema.tables
-    </sql>
-
-	<select id="selectTableList" parameterType="TableInfo" resultMap="TableInfoResult">
-		<include refid="selectGenVo"/>
-		where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
-		<if test="tableName != null and tableName != ''">
-			AND table_name like concat('%', #{tableName}, '%')
-		</if>
-		<if test="tableComment != null and tableComment != ''">
-			AND table_comment like concat('%', #{tableComment}, '%')
-		</if>
-		<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
-			and date_format(create_time,'%y%m%d') &gt;= date_format(#{params.beginTime},'%y%m%d')
-		</if>
-		<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
-			and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
-		</if>
-	</select>
-	
-	<select id="selectTableByName" parameterType="String" resultMap="TableInfoResult">
-		<include refid="selectGenVo"/>
-		where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
-		and table_name = #{tableName}
-	</select>
-	
-	<select id="selectTableColumnsByName" parameterType="String" resultMap="ColumnInfoResult">
-		select column_name, data_type, column_comment, extra from information_schema.columns
-        where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position
-	</select>
-
-</mapper> 

+ 120 - 0
ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.generator.mapper.GenTableColumnMapper">
+    
+    <resultMap type="GenTableColumn" id="GenTableColumnResult">
+        <id     property="columnId"       column="column_id"      />
+        <result property="tableId"        column="table_id"       />
+        <result property="columnName"     column="column_name"    />
+        <result property="columnComment"  column="column_comment" />
+        <result property="columnType"     column="column_type"    />
+        <result property="javaType"       column="java_type"      />
+        <result property="javaField"      column="java_field"     />
+        <result property="isPk"           column="is_pk"          />
+        <result property="isIncrement"    column="is_increment"   />
+        <result property="isRequired"     column="is_required"    />
+        <result property="isInsert"       column="is_insert"      />
+        <result property="isEdit"         column="is_edit"        />
+        <result property="isList"         column="is_list"        />
+        <result property="isQuery"        column="is_query"       />
+        <result property="queryType"      column="query_type"     />
+        <result property="htmlType"       column="html_type"      />
+        <result property="dictType"       column="dict_type"      />
+        <result property="sort"           column="sort"           />
+        <result property="createBy"       column="create_by"      />
+        <result property="createTime"     column="create_time"    />
+        <result property="updateBy"       column="update_by"      />
+        <result property="updateTime"     column="update_time"    />
+    </resultMap>
+	
+	<sql id="selectGenTableColumnVo">
+        select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column
+    </sql>
+	
+    <select id="selectGenTableColumnListByTableId" parameterType="GenTableColumn" resultMap="GenTableColumnResult">
+        <include refid="selectGenTableColumnVo"/>
+        where table_id = #{tableId}
+        order by sort
+    </select>
+    
+    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
+		select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'pri') then '1' else null end) as is_required, (case when column_key = 'pri' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
+		from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
+		order by ordinal_position
+	</select>
+    
+    <insert id="insertGenTableColumn" parameterType="GenTableColumn" useGeneratedKeys="true" keyProperty="columnId">
+        insert into gen_table_column (
+			<if test="tableId != null and tableId != ''">table_id,</if>
+			<if test="columnName != null and columnName != ''">column_name,</if>
+			<if test="columnComment != null and columnComment != ''">column_comment,</if>
+			<if test="columnType != null and columnType != ''">column_type,</if>
+			<if test="javaType != null and javaType != ''">java_type,</if>
+			<if test="javaField != null  and javaField != ''">java_field,</if>
+			<if test="isPk != null and isPk != ''">is_pk,</if>
+			<if test="isIncrement != null and isIncrement != ''">is_increment,</if>
+			<if test="isRequired != null and isRequired != ''">is_required,</if>
+			<if test="isInsert != null and isInsert != ''">is_insert,</if>
+			<if test="isEdit != null and isEdit != ''">is_edit,</if>
+			<if test="isList != null and isList != ''">is_list,</if>
+			<if test="isQuery != null and isQuery != ''">is_query,</if>
+			<if test="queryType != null and queryType != ''">query_type,</if>
+			<if test="htmlType != null and htmlType != ''">html_type,</if>
+			<if test="dictType != null and dictType != ''">dict_type,</if>
+			<if test="sort != null">sort,</if>
+			<if test="createBy != null and createBy != ''">create_by,</if>
+			create_time
+         )values(
+			<if test="tableId != null and tableId != ''">#{tableId},</if>
+			<if test="columnName != null and columnName != ''">#{columnName},</if>
+			<if test="columnComment != null and columnComment != ''">#{columnComment},</if>
+			<if test="columnType != null and columnType != ''">#{columnType},</if>
+			<if test="javaType != null and javaType != ''">#{javaType},</if>
+			<if test="javaField != null and javaField != ''">#{javaField},</if>
+			<if test="isPk != null and isPk != ''">#{isPk},</if>
+			<if test="isIncrement != null and isIncrement != ''">#{isIncrement},</if>
+			<if test="isRequired != null and isRequired != ''">#{isRequired},</if>
+			<if test="isInsert != null and isInsert != ''">#{isInsert},</if>
+			<if test="isEdit != null and isEdit != ''">#{isEdit},</if>
+			<if test="isList != null and isList != ''">#{isList},</if>
+			<if test="isQuery != null and isQuery != ''">#{isQuery},</if>
+			<if test="queryType != null and queryType != ''">#{queryType},</if>
+			<if test="htmlType != null and htmlType != ''">#{htmlType},</if>
+			<if test="dictType != null and dictType != ''">#{dictType},</if>
+			<if test="sort != null">#{sort},</if>
+			<if test="createBy != null and createBy != ''">#{createBy},</if>
+			sysdate()
+         )
+    </insert>
+	 
+    <update id="updateGenTableColumn" parameterType="GenTableColumn">
+        update gen_table_column
+        <set>
+            column_comment = #{columnComment},
+            java_type = #{javaType},
+            java_field = #{javaField},
+            is_insert = #{isInsert},
+            is_edit = #{isEdit},
+            is_list = #{isList},
+            is_query = #{isQuery},
+            is_required = #{isRequired},
+            query_type = #{queryType},
+            html_type = #{htmlType},
+            dict_type = #{dictType},
+            sort = #{sort},
+            update_by = #{updateBy},
+            update_time = sysdate()
+        </set>
+        where column_id = #{columnId}
+    </update>
+
+    <delete id="deleteGenTableColumnByIds" parameterType="Long">
+        delete from gen_table_column where table_id in 
+        <foreach collection="array" item="tableId" open="(" separator="," close=")">
+            #{tableId}
+        </foreach>
+    </delete>
+    
+</mapper>

+ 167 - 0
ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml

@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
+
+	<resultMap type="GenTable" id="GenTableResult">
+	    <id     property="tableId"        column="table_id"        />
+		<result property="tableName"      column="table_name"      />
+		<result property="tableComment"   column="table_comment"   />
+		<result property="className"      column="class_name"      />
+		<result property="tplCategory"    column="tpl_category"    />
+		<result property="packageName"    column="package_name"    />
+		<result property="moduleName"     column="module_name"     />
+		<result property="businessName"   column="business_name"   />
+		<result property="functionName"   column="function_name"   />
+		<result property="functionAuthor" column="function_author" />
+		<result property="options"        column="options"         />
+		<result property="createBy"       column="create_by"       />
+		<result property="createTime"     column="create_time"     />
+		<result property="updateBy"       column="update_by"       />
+		<result property="updateTime"     column="update_time"     />
+		<result property="remark"         column="remark"          />
+		<collection  property="columns"  javaType="java.util.List"  resultMap="GenTableColumnResult" />
+	</resultMap>
+	
+	<resultMap type="GenTableColumn" id="GenTableColumnResult">
+        <id     property="columnId"       column="column_id"      />
+        <result property="tableId"        column="table_id"       />
+        <result property="columnName"     column="column_name"    />
+        <result property="columnComment"  column="column_comment" />
+        <result property="columnType"     column="column_type"    />
+        <result property="javaType"       column="java_type"      />
+        <result property="javaField"      column="java_field"     />
+        <result property="isPk"           column="is_pk"          />
+        <result property="isIncrement"    column="is_increment"   />
+        <result property="isRequired"     column="is_required"    />
+        <result property="isInsert"       column="is_insert"      />
+        <result property="isEdit"         column="is_edit"        />
+        <result property="isList"         column="is_list"        />
+        <result property="isQuery"        column="is_query"       />
+        <result property="queryType"      column="query_type"     />
+        <result property="htmlType"       column="html_type"      />
+        <result property="dictType"       column="dict_type"      />
+        <result property="sort"           column="sort"           />
+        <result property="createBy"       column="create_by"      />
+        <result property="createTime"     column="create_time"    />
+        <result property="updateBy"       column="update_by"      />
+        <result property="updateTime"     column="update_time"    />
+    </resultMap>
+	
+	<sql id="selectGenTableVo">
+        select table_id, table_name, table_comment, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, options, create_by, create_time, update_by, update_time, remark from gen_table
+    </sql>
+    
+    <select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
+		<include refid="selectGenTableVo"/>
+		<if test="tableName != null and tableName != ''">
+			AND table_name like concat('%', #{tableName}, '%')
+		</if>
+		<if test="tableComment != null and tableComment != ''">
+			AND table_comment like concat('%', #{tableComment}, '%')
+		</if>
+	</select>
+
+	<select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
+		select table_name, table_comment, create_time, update_time from information_schema.tables
+		where table_schema = (select database())
+		AND table_name NOT LIKE 'qrtz_%' AND table_name NOT LIKE 'gen_%'
+		AND table_name NOT IN (select table_name from gen_table)
+		<if test="tableName != null and tableName != ''">
+			AND table_name like concat('%', #{tableName}, '%')
+		</if>
+		<if test="tableComment != null and tableComment != ''">
+			AND table_comment like concat('%', #{tableComment}, '%')
+		</if>
+	</select>
+	
+	<select id="selectDbTableListByNames" resultMap="GenTableResult">
+		select table_name, table_comment, create_time, update_time from information_schema.tables
+		where table_name NOT LIKE 'qrtz_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
+		and table_name in
+	    <foreach collection="array" item="name" open="(" separator="," close=")">
+ 			#{name}
+        </foreach> 
+	</select>
+	
+	<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
+		select table_name, table_comment, create_time, update_time from information_schema.tables
+		where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
+		and table_name = #{tableName}
+	</select>
+	
+	<select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
+	    SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+		FROM gen_table t
+			 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+		where t.table_id = #{tableId}
+	</select>
+	
+	<select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
+	    SELECT t.table_id, t.table_name, t.table_comment, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
+			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+		FROM gen_table t
+			 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+		where t.table_name = #{tableName}
+	</select>
+	
+	<insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
+        insert into gen_table (
+			<if test="tableName != null">table_name,</if>
+			<if test="tableComment != null and tableComment != ''">table_comment,</if>
+			<if test="className != null and className != ''">class_name,</if>
+			<if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
+			<if test="packageName != null and packageName != ''">package_name,</if>
+			<if test="moduleName != null and moduleName != ''">module_name,</if>
+			<if test="businessName != null and businessName != ''">business_name,</if>
+			<if test="functionName != null and functionName != ''">function_name,</if>
+			<if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
+			<if test="remark != null and remark != ''">remark,</if>
+ 			<if test="createBy != null and createBy != ''">create_by,</if>
+			create_time
+         )values(
+			<if test="tableName != null">#{tableName},</if>
+			<if test="tableComment != null and tableComment != ''">#{tableComment},</if>
+			<if test="className != null and className != ''">#{className},</if>
+			<if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
+			<if test="packageName != null and packageName != ''">#{packageName},</if>
+			<if test="moduleName != null and moduleName != ''">#{moduleName},</if>
+			<if test="businessName != null and businessName != ''">#{businessName},</if>
+			<if test="functionName != null and functionName != ''">#{functionName},</if>
+			<if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
+			<if test="remark != null and remark != ''">#{remark},</if>
+ 			<if test="createBy != null and createBy != ''">#{createBy},</if>
+			sysdate()
+         )
+    </insert>
+    
+    <update id="updateGenTable" parameterType="GenTable">
+        update gen_table
+        <set>
+            <if test="tableName != null">table_name = #{tableName},</if>
+            <if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
+            <if test="className != null and className != ''">class_name = #{className},</if>
+            <if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
+            <if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
+            <if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
+            <if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
+            <if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
+            <if test="functionName != null and functionName != ''">function_name = #{functionName},</if>
+            <if test="options != null and options != ''">options = #{options},</if>
+            <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+            <if test="remark != null">remark = #{remark},</if>
+            update_time = sysdate()
+        </set>
+        where table_id = #{tableId}
+    </update>
+    
+    <delete id="deleteGenTableByIds" parameterType="Long">
+        delete from gen_table where table_id in 
+        <foreach collection="array" item="tableId" open="(" separator="," close=")">
+            #{tableId}
+        </foreach>
+    </delete>
+
+</mapper> 

+ 483 - 0
ruoyi-generator/src/main/resources/templates/tool/gen/edit.html

@@ -0,0 +1,483 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+	<th:block th:include="include :: header('修改生成信息')" />
+	<th:block th:include="include :: select2-css" />
+	<style type="text/css">
+	    .select-table table{table-layout:fixed;}.table>thead>tr>th{text-align:center;}.select-table .table td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.form-control{padding:3px 6px 4px;height:30px;}.icheckbox-blue{top:0px;left:6px;}.form-control.select2-hidden-accessible{position:static!important;}.select-table table label.error{position: inherit;}select + label.error{z-index:1;right:40px;}
+	</style>
+</head>
+<body class="gray-bg" style="font: 14px Helvetica Neue, Helvetica, PingFang SC, 微软雅黑, Tahoma, Arial, sans-serif !important;">
+    <section class="section-content">
+    <div class="row">
+        <div class="col-xs-12">
+            <div class="ibox float-e-margins">
+                <div class="ibox-content" style="border-style:none;">
+                    <div class="nav-tabs-custom">
+                        <ul class="nav nav-tabs">
+                            <li><a href="#tab-basic" data-toggle="tab" aria-expanded="false">基本信息</a></li>
+                            <li class="active"><a href="#tab-field" data-toggle="tab" aria-expanded="true">字段信息</a></li>
+                            <li><a href="#tab-gen" data-toggle="tab" aria-expanded="false">生成信息</a></li>
+                            <li class="pull-right header">
+								<i class="fa fa-code"></i> 生成配置
+							</li>
+                        </ul>
+                        <form id="form-gen-edit" class="form-horizontal" th:object="${table}">
+                        <input name="tableId" type="hidden" th:field="*{tableId}" />
+                        <div class="tab-content">
+                            <!-- 基本信息 -->
+                            <div class="tab-pane" id="tab-basic">
+				            <div class="row mt20">
+				            	<div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label"><span style="color: red; ">*</span>表名称:</label>
+				                        <div class="col-sm-8">
+				                            <input name="tableName" class="form-control" type="text" placeholder="请输入表名称" maxlength="200" th:field="*{tableName}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				                <div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label"><span style="color: red; ">*</span>表描述:</label>
+				                        <div class="col-sm-8">
+				                            <input name="tableComment" class="form-control" type="text" placeholder="请输入表描述" maxlength="500" th:field="*{tableComment}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				            </div>
+				            <div class="row">
+				                <div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label"><span style="color: red; ">*</span>实体类名称:</label>
+				                        <div class="col-sm-8">
+				                            <input name="className" class="form-control" type="text" placeholder="请输入实体类名称" maxlength="100" th:field="*{className}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				                <div class="col-sm-6">
+				                    <div class="form-group">
+				                        <label class="col-sm-4 control-label"><span style="color: red; ">*</span>作者:</label>
+				                        <div class="col-sm-8">
+				                            <input name="functionAuthor" class="form-control" type="text" placeholder="请输入作者" maxlength="50" th:field="*{functionAuthor}" required>
+				                        </div>
+				                    </div>
+				                </div>
+				            </div>
+				            <div class="row">
+				                <div class="col-sm-12">
+				                    <div class="form-group">
+				                        <label class="col-xs-2 control-label">备注:</label>
+				                        <div class="col-xs-10">
+				                            <textarea name="remark" maxlength="500" class="form-control" rows="3"></textarea>
+				                        </div>
+				                    </div>
+				                </div>
+				            </div>
+                            </div>
+                            
+                            <!-- 字段信息 -->
+                            <div class="tab-pane active" id="tab-field">
+                                <div class="select-table table-striped" style="margin-top: 0px;padding-top: 0px;padding-bottom: 0px;">
+								    <table id="bootstrap-table" data-use-row-attr-func="true" data-reorderable-rows="true"></table>
+								</div>
+                            </div>
+                            
+                            <!-- 生成信息 -->
+                            <div class="tab-pane" id="tab-gen">
+					            <div class="row mt20">
+					            	<div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label"><span style="color: red; ">*</span>生成模板:</label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="tplCategory" name='tplCategory' style="width: 100%">
+												    <option value="crud" th:field="*{tplCategory}">单表(增删改查)</option>
+												    <option value="tree" th:field="*{tplCategory}">树表(增删改查)</option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="生成在哪个java包下,例如 com.ruoyi.system"><span style="color: red; ">*</span>生成包路径:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="packageName" class="form-control" type="text" placeholder="请输入生成包路径" maxlength="100" th:field="*{packageName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="可理解为子系统名,例如 system"><span style="color: red; ">*</span>生成模块名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="moduleName" class="form-control" type="text" placeholder="请输入生成模块名" maxlength="30" th:field="*{moduleName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="可理解为功能英文名,例如 user"><span style="color: red; ">*</span>生成业务名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="businessName" class="form-control" type="text" placeholder="请输入生成业务名" maxlength="50" th:field="*{businessName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="用作类描述,例如 用户"><span style="color: red; ">*</span>生成功能名:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <input name="functionName" class="form-control" type="text" placeholder="请输入生成功能名" maxlength="50" th:field="*{functionName}" required>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="hidden" id="otherInfo">
+					            <h4 class="form-header h4">其他信息</h4>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="树显示的编码字段名, 如:dept_id"><span style="color: red; ">*</span>树编码字段:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="treeCode" name='params[treeCode]' style="width: 100%">
+					                                <option value="">---请选择---</option>
+												    <option th:each="column : ${table.columns}" th:text="${column.columnName + ':' + column.columnComment}" th:value="${column.columnName}" th:field="*{treeCode}"></option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="树显示的父编码字段名, 如:parent_Id"><span style="color: red; ">*</span>树父编码字段:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="treeParentCode" name='params[treeParentCode]' style="width: 100%">
+												    <option value="">---请选择---</option>
+												    <option th:each="column : ${table.columns}" th:text="${column.columnName + ':' + column.columnComment}" th:value="${column.columnName}" th:field="*{treeParentCode}"></option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            <div class="row">
+					                <div class="col-sm-6">
+					                    <div class="form-group">
+					                        <label class="col-sm-4 control-label" title="树节点的显示名称字段名, 如:dept_name"><span style="color: red; ">*</span>树名称字段:<i class="fa fa-question-circle-o"></i></label>
+					                        <div class="col-sm-8">
+					                            <select class='form-control' id="treeName" name='params[treeName]' style="width: 100%">
+												    <option value="">---请选择---</option>
+												    <option th:each="column : ${table.columns}" th:text="${column.columnName + ':' + column.columnComment}" th:value="${column.columnName}" th:field="*{treeName}"></option>
+												</select>
+					                        </div>
+					                    </div>
+					                </div>
+					            </div>
+					            </div>
+                            </div>
+                        </div>
+                        </form>
+                    </div>
+                </div>
+               <div class="box-footer">
+			       <div class="col-sm-offset-5 col-sm-6">
+			           <button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
+			           <button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
+			       </div>
+           	   </div>
+            </div>
+        </div>
+    </div>
+	</section>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: select2-js" />
+    <th:block th:include="include :: bootstrap-table-reorder-js" />
+    <script th:src="@{/js/jquery.tmpl.js}"></script>
+    <script type="text/javascript">
+	    /*用户信息-修改*/
+	    $("#form-table-edit").validate({
+	    	rules: {
+	    	    tableName: {
+	    	        required: true,
+	    	    },
+	    	},
+			focusCleanup: true
+		}); 
+	    
+	    function submitHandler() {
+	        if ($.validate.form()) {
+	        	$.operate.saveTab(prefix + "/edit", $("#form-gen-edit").serializeArray());
+	        }
+	    }
+	    
+	    var prefix = ctx + "tool/gen";
+		$(function() {
+		    var options = {
+		        url: prefix + "/column/list",
+		        sortName: "sort",
+		        sortOrder: "desc",
+		        height: $(window).height() - 166,
+		        pagination: false,
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        onLoadSuccess: onLoadSuccess,
+		        onReorderRow: onReorderRow,
+		        columns: [{
+                    title: "序号",
+                    width: "5%",
+                    formatter: function (value, row, index) {
+                    	// 编号隐藏域
+                    	var columnIdHtml = $.common.sprintf("<input type='hidden' name='columns[%s].columnId' value='%s'>", index, row.columnId);
+                    	// 排序隐藏域
+                    	var sortHtml = $.common.sprintf("<input type='hidden' name='columns[%s].sort' value='%s' id='columns_sort_%s'>", index, row.sort, row.columnId);
+                    	return columnIdHtml + sortHtml + $.table.serialNumber(index);
+                    },
+                    cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "move" } };
+                    }
+                },
+		        {
+		            field: 'columnName',
+		            title: '字段列名',
+		            width: "10%",
+		            class: "nodrag",
+		            cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "default" } };
+                    }
+		        },
+		        {
+		            field: 'columnComment',
+		            title: '字段描述',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		            	var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].columnComment' value='%s'>", index, value);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'columnType',
+		            title: '物理类型',
+		            width: "10%",
+		            class: "nodrag",
+		            cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "default" } };
+                    }
+		        },
+		        {
+		            field: 'javaType',
+		            title: 'Java类型',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		        		var data = [{ index: index, javaType: value }];
+		                return $("#javaTypeTpl").tmpl(data).html();
+		        	}
+		        },
+		        {
+		            field: 'javaField',
+		            title: 'Java属性',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		        		var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].javaField' value='%s' required>", index, value);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isInsert',
+		            title: '插入',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isInsert' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isEdit',
+		            title: '编辑',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isEdit' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isList',
+		            title: '列表',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isList' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'isQuery',
+		            title: '查询',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isQuery' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'queryType',
+		            title: '查询方式',
+		            width: "10%",
+		            formatter: function (value, row, index) {
+		            	var data = [{ index: index, queryType: value }];
+		                return $("#queryTypeTpl").tmpl(data).html();
+		        	}
+		        },
+		        {
+		            field: 'isRequired',
+		            title: '必填',
+		            width: "5%",
+		            formatter: function (value, row, index) {
+		            	var isCheck = value == 1 ? 'checked' : '';
+		            	var html = $.common.sprintf("<label class='check-box'><input type='checkbox' name='columns[%s].isRequired' value='1' %s></label>", index, isCheck);
+		        		return html;
+		        	}
+		        },
+		        {
+		            field: 'htmlType',
+		            title: '显示类型',
+		            width: "12%",
+		            formatter: function (value, row, index) {
+		            	var data = [{ index: index, htmlType: value }];
+		                return $("#htmlTypeTpl").tmpl(data).html();
+		        	}
+		        },
+		        {
+		            field: 'dictType',
+		            title: '字典类型',
+		            width: "13%",
+		            formatter: function (value, row, index) {
+		        		var html = $.common.sprintf("<input class='form-control' type='text' name='columns[%s].dictType' value='%s' id='columns_dict_%s'>", index, value, row.columnId);
+		        		return "<div class='input-group'>" + html + "<span class='input-group-addon input-sm' onclick='selectDictTree(" + row.columnId + ", this)'><i class='fa fa-search'></i></span></div>";
+		        	},
+		        	cellStyle: function(value, row, index) {
+                        return { css: { "cursor": "default" } };
+                    }
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		// 当所有数据被加载时触发处理函数
+		function onLoadSuccess(data){
+			$.fn.select2.defaults.set( "theme", "bootstrap" );
+			$("select.form-control").each(function () {
+				$(this).select2().on("change", function () {
+					$(this).valid();
+				})
+			})
+			$(".check-box").each(function() {
+	            $(this).iCheck({
+	                checkboxClass: 'icheckbox-blue'
+            	})
+        	})
+        }
+		
+		// 当拖拽结束后处理函数
+		function onReorderRow(data) {
+	        for (var i = 0; i < data.length; i++) {
+			    $("#columns_sort_" + data[i].columnId).val(i+1);
+			}
+       }
+		
+		$(function() {
+            var tplCategory = $("#tplCategory option:selected").val();
+            tplCategoryVisible(tplCategory);
+        });
+		
+		$('#tplCategory').on('select2:select', function (event) {
+			var tplCategory = $(event.target).val();
+			tplCategoryVisible(tplCategory);
+		});
+		
+		function tplCategoryVisible(tplCategory) {
+			if("crud" == tplCategory){
+				$("#treeCode").select2("val", [""]);
+				$("#treeParentCode").select2("val", [""]);
+				$("#treeName").select2("val", [""]);
+				$("#otherInfo").addClass("hidden");
+				
+			} else if("tree" == tplCategory){
+				$("#otherInfo").removeClass("hidden");
+				$("#treeCode").attr("required", "true");
+				$("#treeParentCode").attr("required", "true");
+				$("#treeName").attr("required", "true");
+			}
+        }
+		
+		// 选择字典处理函数
+		function selectDictTree(columnId, obj) {
+			var dictType = $.common.nullToStr($(obj).parent().find("input").val());
+        	var url = ctx + "system/dict/selectDictTree/" + columnId + "/" + dictType;
+			var options = {
+				title: '选择字典类型',
+				width: "380",
+				url: url,
+				callBack: doSubmit
+			};
+			$.modal.openOptions(options);
+		}
+		
+		function doSubmit(index, layero){
+			var body = layer.getChildFrame('body', index);
+   			var columnId = body.find('#columnId').val();
+   			var dictType = body.find('#dictType').val();
+   			layer.close(index);
+   			$("#columns_dict_" + columnId).val(dictType);
+		}
+    </script>
+</body>
+</html>
+
+
+<!-- java类型 -->
+<script id="javaTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='columns[${index}].javaType'>
+    <option value="Long" {{if javaType==="Long"}}selected{{/if}}>Long</option>
+    <option value="String" {{if javaType==="String"}}selected{{/if}}>String</option>
+    <option value="Integer" {{if javaType==="Integer"}}selected{{/if}}>Integer</option>
+    <option value="Double" {{if javaType==="Double"}}selected{{/if}}>Double</option>
+    <option value="BigDecimal" {{if javaType==="BigDecimal"}}selected{{/if}}>BigDecimal</option>
+    <option value="Date" {{if javaType==="Date"}}selected{{/if}}>Date</option>
+</select>
+</div>
+</script>
+
+<!-- 查询方式 -->
+<script id="queryTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='columns[${index}].queryType'>
+    <option value="EQ" {{if queryType==="EQ"}}selected{{/if}}>=</option>
+    <option value="NE" {{if queryType==="NE"}}selected{{/if}}>!=</option>
+    <option value="GT" {{if queryType==="GT"}}selected{{/if}}>></option>
+    <option value="GTE" {{if queryType==="GTE"}}selected{{/if}}>>=</option>
+    <option value="LT" {{if queryType==="LT"}}selected{{/if}}><</option>
+    <option value="LTE" {{if queryType==="LTE"}}selected{{/if}}><=</option>
+    <option value="LIKE" {{if queryType==="LIKE"}}selected{{/if}}>Like</option>
+    <option value="BETWEEN" {{if queryType==="BETWEEN"}}selected{{/if}}>Between</option>
+</select>
+</div>
+</script>
+
+<!-- 显示类型 -->
+<script id="htmlTypeTpl" type="text/x-jquery-tmpl">
+<div>
+<select class='form-control' name='columns[${index}].htmlType'>
+    <option value="input" {{if htmlType==="input"}}selected{{/if}}>文本框</option>
+    <option value="textarea" {{if htmlType==="textarea"}}selected{{/if}}>文本域</option>
+    <option value="select" {{if htmlType==="select"}}selected{{/if}}>下拉框</option>
+    <option value="radio" {{if htmlType==="radio"}}selected{{/if}}>单选框</option>
+    <option value="checkbox" {{if htmlType==="checkbox"}}selected{{/if}}>复选框</option>
+    <option value="datetime" {{if htmlType==="datetime"}}selected{{/if}}>日期控件</option>
+</select>
+</div>
+</script>

+ 72 - 12
ruoyi-generator/src/main/resources/templates/tool/gen/gen.html

@@ -32,9 +32,18 @@
 			</div>
 			
 			<div class="btn-group-sm" id="toolbar" role="group">
-				<a class="btn btn-success" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code">
-			        <i class="fa fa-download"></i> 批量生成
+			     <a class="btn btn-success multiple disabled" onclick="javascript:batchGenCode()" shiro:hasPermission="tool:gen:code">
+			        <i class="fa fa-download"></i> 生成
 			    </a>
+				<a class="btn btn-info" onclick="importTable()">
+			        <i class="fa fa-upload"></i> 导入
+			    </a>
+			    <a class="btn btn-primary single disabled" onclick="$.operate.editTab()" shiro:hasPermission="tool:gen:edit">
+		            <i class="fa fa-edit"></i> 修改
+		        </a>
+			    <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="tool:gen:remove">
+		            <i class="fa fa-remove"></i> 删除
+		        </a>
 		    </div>
 		
 		    <div class="col-sm-12 select-table table-striped">
@@ -43,18 +52,30 @@
 		</div>
 	</div>
 	<th:block th:include="include :: footer" />
-	<script type="text/javascript">
+	<script th:inline="javascript">
 		var prefix = ctx + "tool/gen";
+		var editFlag = [[${@permission.hasPermi('tool:gen:edit')}]];
+		var removeFlag = [[${@permission.hasPermi('tool:gen:remove')}]];
+		var previewFlag = [[${@permission.hasPermi('tool:gen:preview')}]];
+		var codeFlag = [[${@permission.hasPermi('tool:gen:code')}]];
 	
 		$(function() {
 		    var options = {
 		        url: prefix + "/list",
+		        updateUrl: prefix + "/edit/{id}",
+		        removeUrl: prefix + "/remove",
 		        sortName: "createTime",
 		        sortOrder: "desc",
 		        showExport: true,
+		        modalName: "生成配置",
 		        columns: [{
 		            checkbox: true
 		        },
+		        {
+		            field: 'tableId',
+		            title: '编号',
+		            visible: false
+		        },
 		        {
                     title: "序号",
                     formatter: function (value, row, index) {
@@ -64,44 +85,77 @@
 		        {
 		            field: 'tableName',
 		            title: '表名称',
-		            width: '20%',
 		            sortable: true
 		        },
 		        {
 		            field: 'tableComment',
 		            title: '表描述',
-		            width: '20%',
+		            sortable: true
+		        },
+		        {
+		            field: 'className',
+		            title: '实体类名称',
 		            sortable: true
 		        },
 		        {
 		            field: 'createTime',
 		            title: '创建时间',
-		            width: '20%',
 		            sortable: true
 		        },
 		        {
 		            field: 'updateTime',
 		            title: '更新时间',
-		            width: '20%',
 		            sortable: true
 		        },
 		        {
 		            title: '操作',
-		            width: '20%',
 		            align: 'center',
 		            formatter: function(value, row, index) {
-		                var msg = '<a class="btn btn-primary btn-xs" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\')"><i class="fa fa-bug"></i>生成代码</a> ';
-		                return msg;
+		                var actions = [];
+		                actions.push('<a class="btn btn-info btn-xs ' + previewFlag + '" href="javascript:void(0)" onclick="preview(\'' + row.tableId + '\')"><i class="fa fa-search"></i>预览</a> ');
+		                actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.tableId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+		                actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.tableId + '\')"><i class="fa fa-remove"></i>删除</a> ');
+		                actions.push('<a class="btn btn-primary btn-xs ' + codeFlag + '" href="javascript:void(0)" onclick="genCode(\'' + row.tableName + '\')"><i class="fa fa-bug"></i>生成代码</a> ');
+		                return actions.join('');
 		            }
 		        }]
 		    };
 		    $.table.init(options);
 		});
+		
+		// 预览代码
+		function preview(tableId) {
+			var preViewUrl = prefix + "/preview/" + tableId;
+			$.modal.loading("正在加载数据,请稍后...");
+			$.get(preViewUrl, function(result) {
+				if (result.code == web_status.SUCCESS) {
+					 var items = [];
+		                $.each(result.data, function(index, value) {
+		                	value = value.replace(/</g, "&lt;");
+		                	value = value.replace(/>/g, "&gt;");
+		                    var templateName = index.substring(index.lastIndexOf("/") + 1, index.length).replace(/\.vm/g, "");
+		                    if(!$.common.equals("sql", templateName) && !$.common.equals("tree.html", templateName)){
+			                    items.push({
+			                        title: templateName , content: "<pre class=\"layui-code\">" + value + "</pre>"
+			                    })
+		                    }
+		                });
+		                top.layer.tab({
+		                    area: ['90%', '90%'],
+		                    shadeClose: true,
+		                    tab: items
+		                });
+				} else {
+					$.modal.alertError(result.msg);
+				}
+				$.modal.closeLoading();
+			});
+		}
 	
 		// 生成代码
 		function genCode(tableName) {
 		    $.modal.confirm("确定要生成" + tableName + "表代码吗?", function() {
-		        location.href = prefix + "/genCode/" + tableName;
+		    	location.href = prefix + "/genCode/" + tableName;
 		        layer.msg('执行成功,正在生成代码请稍后…', { icon: 1 });
 		    })
 		}
@@ -114,10 +168,16 @@
 		        return;
 		    }
 		    $.modal.confirm("确认要生成选中的" + rows.length + "条数据吗?", function() {
-		        location.href = prefix + "/batchGenCode?tables=" + rows;
+		    	location.href = prefix + "/batchGenCode?tables=" + rows;
 		        layer.msg('执行成功,正在生成代码请稍后…', { icon: 1 });
 		    });
 		}
+		
+		// 导入表结构
+		function importTable() {
+			var importTableUrl = prefix + "/importTable";
+			$.modal.open("导入表结构", importTableUrl);
+		}
 	</script>
 </body>
 </html>

+ 96 - 0
ruoyi-generator/src/main/resources/templates/tool/gen/importTable.html

@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+	<th:block th:include="include :: header('导入表结构')" />
+</head>
+<body class="gray-bg">
+    <div class="container-div">
+		<div class="row">
+			<div class="col-sm-12 search-collapse">
+				<form id="gen-form">
+					<div class="select-list">
+						<ul>
+							<li>
+								表名称:<input type="text" name="tableName"/>
+							</li>
+							<li>
+								表描述:<input type="text" name="tableComment"/>
+							</li>
+							<li>
+								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+							</li>
+						</ul>
+					</div>
+				</form>
+			</div>
+			
+		    <div class="col-sm-12 select-table table-striped">
+			    <table id="bootstrap-table" data-mobile-responsive="true"></table>
+			</div>
+		</div>
+	</div>
+	<th:block th:include="include :: footer" />
+	<script type="text/javascript">
+		var prefix = ctx + "tool/gen";
+	
+		$(function() {
+		    var options = {
+		        url: prefix + "/db/list",
+		        sortName: "createTime",
+		        sortOrder: "desc",
+		        showSearch: false,
+		        showRefresh: false,
+		        showToggle: false,
+		        showColumns: false,
+		        clickToSelect: true,
+		        columns: [{
+		            checkbox: true
+		        },
+		        {
+                    title: "序号",
+                    formatter: function (value, row, index) {
+                 	    return $.table.serialNumber(index);
+                    }
+                },
+		        {
+		            field: 'tableName',
+		            title: '表名称',
+		            width: '20%',
+		            sortable: true
+		        },
+		        {
+		            field: 'tableComment',
+		            title: '表描述',
+		            width: '20%',
+		            sortable: true
+		        },
+		        {
+		            field: 'createTime',
+		            title: '创建时间',
+		            width: '20%',
+		            sortable: true
+		        },
+		        {
+		            field: 'updateTime',
+		            title: '更新时间',
+		            width: '20%',
+		            sortable: true
+		        }]
+		    };
+		    $.table.init(options);
+		});
+		
+		/* 导入表结构-选择表结构-提交 */
+		function submitHandler() {
+			var rows = $.table.selectColumns("tableName");
+			if (rows.length == 0) {
+       			$.modal.alertWarning("请至少选择一条记录");
+       			return;
+       		}
+			var data = {"tables": rows.join()};
+			$.operate.save(prefix + "/importTable", data);
+		}
+	</script>
+</body>
+</html>

+ 149 - 51
ruoyi-generator/src/main/resources/vm/html/add.html.vm

@@ -1,61 +1,159 @@
 <!DOCTYPE html>
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" >
 <head>
-	<th:block th:include="include :: header('新增${tableComment}')" />
+    <th:block th:include="include :: header('新增${functionName}')" />
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-css" />
+#break
+#end
+#end
 </head>
 <body class="white-bg">
     <div class="wrapper wrapper-content animated fadeInRight ibox-content">
-        <form class="form-horizontal m" id="form-${classname}-add">
+        <form class="form-horizontal m" id="form-${businessName}-add">
 #foreach($column in $columns)
-#if($column.columnName != $primaryKey.columnName)
-#if(!${column.configInfo})
-			<div class="form-group">	
-				<label class="col-sm-3 control-label">${column.columnComment}:</label>
-				<div class="col-sm-8">
-					<input id="${column.attrname}" name="${column.attrname}" class="form-control" type="text">
-				</div>
-			</div>
+#set($field=$column.javaField)
+#if($column.insert && !$column.superColumn && !$column.pk)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
 #else
-#if(${column.configInfo.type} == "dict")
-			<div class="form-group">	
-				<label class="col-sm-3 control-label">${column.columnComment}:</label>
-				<div class="col-sm-8">
-					<select name="${column.attrname}" class="form-control m-b" th:with="type=${@dict.getType('${column.configInfo.value}')}">
-						<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
-					</select>
-				</div>
-			</div>
-#elseif(${column.configInfo.type} == "date")
-			<div class="form-group">	
-				<label class="col-sm-3 control-label">${column.columnComment}:</label>
-				<div class="col-sm-8">
-					<input id="${column.attrname}" name="${column.attrname}" class="form-control time-input" type="text">
-				</div>
-			</div>
-#elseif(${column.configInfo.type} == "fk")
-#end
-#end
-#end
-#end
-		</form>
-	</div>
-    <div th:include="include::footer"></div>
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="input-group">
+#set($BusinessName=$businessName.substring(0,1).toUpperCase() + ${businessName.substring(1)})
+#set($deptId = "${className}?.deptId")
+#set($deptName = "${className}?.deptName")
+                        <input id="treeId" name="${treeParentCode}" type="hidden" th:value="${${deptId}}"/>
+                        <input class="form-control" type="text" onclick="select${BusinessName}Tree()" id="treeName" readonly="true" th:value="${${deptName}}"#if($column.required) required#end>
+                        <span class="input-group-addon"><i class="fa fa-search"></i></span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "input")
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <input name="${field}" class="form-control" type="text"#if($column.required) required#end>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && "" != $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <select name="${field}" class="form-control m-b" th:with="type=${@dict.getType('${dictType}')}"#if($column.required) required#end>
+                        <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                    </select>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <select name="${field}" class="form-control m-b"#if($column.required) required#end>
+                        <option value="">所有</option>
+                    </select>
+                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="radio-box" th:each="dict : ${@dict.getType('${dictType}')}">
+                        <input type="radio" th:id="${dict.dictCode}" name="${field}" th:value="${dict.dictValue}" th:checked="${dict.default}"#if($column.required) required#end>
+                        <label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="radio-box">
+                        <input type="radio" name="${field}" value=""#if($column.required) required#end>
+                        <label th:for="${field}" th:text="未知"></label>
+                    </div>
+                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                </div>
+            </div>
+#elseif($column.htmlType == "datetime")
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="input-group date">
+                        <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                        <input name="${field}" class="form-control" placeholder="yyyy-MM-dd" type="text"#if($column.required) required#end>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "textarea")
+            <div class="form-group">
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <textarea name="${field}" class="form-control"#if($column.required) required#end></textarea>
+                </div>
+            </div>
+#end
+#end
+#end
+        </form>
+    </div>
+    <th:block th:include="include :: footer" />
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-js" />
+#break
+#end
+#end
     <script type="text/javascript">
-		var prefix = ctx + "${moduleName}/${classname}"
-		$("#form-${classname}-add").validate({
-			rules:{
-				xxxx:{
-					required:true,
-				},
-			},
-			focusCleanup: true
-		});
-		
-		function submitHandler() {
-	        if ($.validate.form()) {
-	            $.operate.save(prefix + "/add", $('#form-${classname}-add').serialize());
-	        }
-	    }
-	</script>
+        var prefix = ctx + "${moduleName}/${businessName}"
+        $("#form-${businessName}-add").validate({
+            focusCleanup: true
+        });
+
+        function submitHandler() {
+            if ($.validate.form()) {
+                $.operate.save(prefix + "/add", $('#form-${businessName}-add').serialize());
+            }
+        }
+#foreach($column in $columns)
+#if($column.insert && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+
+        $("input[name='$column.javaField']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+#break
+#end
+#end
+#if($table.tree)
+
+        /*${functionName}-新增-选择父部门树*/
+        function select${BusinessName}Tree() {
+            var options = {
+                title: '${functionName}选择',
+                width: "380",
+                url: prefix + "/select${BusinessName}Tree/" + $("#treeId").val(),
+                callBack: doSubmit
+            };
+            $.modal.openOptions(options);
+        }
+
+        function doSubmit(index, layero){
+            var body = layer.getChildFrame('body', index);
+               $("#treeId").val(body.find('#treeId').val());
+               $("#treeName").val(body.find('#treeName').val());
+               layer.close(index);
+        }
+#end
+    </script>
 </body>
-</html>
+</html>

+ 149 - 51
ruoyi-generator/src/main/resources/vm/html/edit.html.vm

@@ -1,62 +1,160 @@
 <!DOCTYPE html>
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" >
 <head>
-	<th:block th:include="include :: header('修改${tableComment}')" />
+    <th:block th:include="include :: header('修改${functionName}')" />
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-css" />
+#break
+#end
+#end
 </head>
 <body class="white-bg">
     <div class="wrapper wrapper-content animated fadeInRight ibox-content">
-        <form class="form-horizontal m" id="form-${classname}-edit" th:object="${${classname}}">
-            <input id="${primaryKey.attrname}" name="${primaryKey.attrname}" th:field="*{${primaryKey.attrname}}"  type="hidden">
+        <form class="form-horizontal m" id="form-${businessName}-edit" th:object="${${className}}">
+            <input name="${pkColumn.javaField}" th:field="*{${pkColumn.javaField}}" type="hidden">
 #foreach($column in $columns)
-#if($column.columnName != $primaryKey.columnName)
-#if(!${column.configInfo})
-			<div class="form-group">	
-				<label class="col-sm-3 control-label">${column.columnComment}:</label>
-				<div class="col-sm-8">
-					<input id="${column.attrname}" name="${column.attrname}" th:field="*{${column.attrname}}" class="form-control" type="text">
-				</div>
-			</div>
+#if($column.edit && !$column.superColumn && !$column.pk)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
 #else
-#if(${column.configInfo.type} == "dict")
-			<div class="form-group">	
-				<label class="col-sm-3 control-label">${column.columnComment}:</label>
-				<div class="col-sm-8">
-					<select name="${column.attrname}" class="form-control m-b" th:with="type=${@dict.getType('${column.configInfo.value}')}">
-						<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{${column.attrname}}"></option>
-					</select>
-				</div>
-			</div>
-#elseif(${column.configInfo.type} == "date")
-			<div class="form-group">	
-				<label class="col-sm-3 control-label">${column.columnComment}:</label>
-				<div class="col-sm-8">
-					<input id="${column.attrname}"  name="${column.attrname}" th:field="*{${column.attrname}}" class="form-control time-input" type="text">
-				</div>
-			</div>
-#elseif(${column.configInfo.type} == "fk")	
-#end
-#end
-#end
-#end
-		</form>
+#set($comment=$column.columnComment)
+#end
+#set($field=$column.javaField)
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="input-group">
+#set($BusinessName=$businessName.substring(0,1).toUpperCase() + ${businessName.substring(1)})
+#set($deptId = "${className}?.deptId")
+#set($deptName = "${className}?.deptName")
+                        <input id="treeId" name="${treeParentCode}" type="hidden" th:field="*{${treeParentCode}}" />
+                        <input class="form-control" type="text" onclick="select${BusinessName}Tree()" id="treeName" readonly="true" th:field="*{parentName}"#if($column.required) required#end>
+                        <span class="input-group-addon"><i class="fa fa-search"></i></span>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "input")
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <input name="${field}" th:field="*{${field}}" class="form-control" type="text"#if($column.required) required#end>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && "" != $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <select name="${field}" class="form-control m-b" th:with="type=${@dict.getType('${dictType}')}"#if($column.required) required#end>
+                        <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}" th:field="*{${field}}"></option>
+                    </select>
+                </div>
+            </div>
+#elseif($column.htmlType == "select" && $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <select name="${field}" class="form-control m-b"#if($column.required) required#end>
+                        <option value="">所有</option>
+                    </select>
+                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="radio-box" th:each="dict : ${@dict.getType('${dictType}')}">
+                        <input type="radio" th:id="${dict.dictCode}" name="${field}" th:value="${dict.dictValue}" th:field="*{${field}}"#if($column.required) required#end>
+                        <label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "radio" && $dictType)
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="radio-box">
+                        <input type="radio" name="${field}" value=""#if($column.required) required#end>
+                        <label th:for="${field}" th:text="未知"></label>
+                    </div>
+                    <span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 代码生成请选择字典属性</span>
+                </div>
+            </div>
+#elseif($column.htmlType == "datetime")
+            <div class="form-group">    
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <div class="input-group date">
+                        <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
+                        <input name="${field}" th:value="${#dates.format(${className}.${field}, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text"#if($column.required) required#end>
+                    </div>
+                </div>
+            </div>
+#elseif($column.htmlType == "textarea")
+            <div class="form-group">
+                <label class="col-sm-3 control-label">${comment}:</label>
+                <div class="col-sm-8">
+                    <textarea name="${field}" class="form-control"#if($column.required) required#end>[[*{${field}}]]</textarea>
+                </div>
+            </div>
+#end
+#end
+#end
+        </form>
     </div>
-    <div th:include="include::footer"></div>
+    <th:block th:include="include :: footer" />
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+    <th:block th:include="include :: datetimepicker-js" />
+#break
+#end
+#end
     <script type="text/javascript">
-		var prefix = ctx + "${moduleName}/${classname}";
-		$("#form-${classname}-edit").validate({
-			rules:{
-				xxxx:{
-					required:true,
-				},
-			},
-			focusCleanup: true
-		});
-		
-		function submitHandler() {
-	        if ($.validate.form()) {
-	            $.operate.save(prefix + "/edit", $('#form-${classname}-edit').serialize());
-	        }
-	    }
-	</script>
+        var prefix = ctx + "${moduleName}/${businessName}";
+        $("#form-${businessName}-edit").validate({
+            focusCleanup: true
+        });
+
+        function submitHandler() {
+            if ($.validate.form()) {
+                $.operate.save(prefix + "/edit", $('#form-${businessName}-edit').serialize());
+            }
+        }
+#foreach($column in $columns)
+#if($column.edit && !$column.superColumn && !$column.pk && $column.htmlType == "datetime")
+
+        $("input[name='$column.javaField']").datetimepicker({
+            format: "yyyy-mm-dd",
+            minView: "month",
+            autoclose: true
+        });
+#break
+#end
+#end
+#if($table.tree)
+
+        /*${functionName}-新增-选择父部门树*/
+        function select${BusinessName}Tree() {
+            var options = {
+                title: '${functionName}选择',
+                width: "380",
+                url: prefix + "/select${BusinessName}Tree/" + $("#treeId").val(),
+                callBack: doSubmit
+            };
+            $.modal.openOptions(options);
+        }
+
+        function doSubmit(index, layero){
+            var body = layer.getChildFrame('body', index);
+               $("#treeId").val(body.find('#treeId').val());
+               $("#treeName").val(body.find('#treeName').val());
+               layer.close(index);
+        }
+#end
+    </script>
 </body>
-</html>
+</html>

+ 150 - 0
ruoyi-generator/src/main/resources/vm/html/list-tree.html.vm

@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('${functionName}列表')" />
+</head>
+<body class="gray-bg">
+     <div class="container-div">
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="formId">
+                    <div class="select-list">
+                        <ul>
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else  
+#set($comment=$column.columnComment)
+#end  
+#if($column.htmlType == "input")
+                            <li>
+                                <p>${comment}:</p>
+                                <input type="text" name="${column.javaField}"/>
+                            </li>
+#elseif($column.htmlType == "select" || $column.htmlType == "radio" && "" != $dictType)
+                            <li>
+                                <p>${comment}:</p>
+                                <select name="${column.javaField}" th:with="type=${@dict.getType('${dictType}')}">
+                                    <option value="">所有</option>
+                                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                                </select>
+                            </li>
+#elseif($column.htmlType == "select" || $column.htmlType == "radio" && $dictType)
+                            <li>
+                                <p>${comment}:</p>
+                                <select name="${column.javaField}">
+                                    <option value="">所有</option>
+                                </select>
+                            </li>
+#elseif($column.htmlType == "datetime")
+                            <li class="select-time">
+                                <p>${comment}:</p>
+                                <input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[begin${AttrName}]"/>
+                                <span>-</span>
+                                <input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[end${AttrName}]"/>
+                            </li>                
+#end
+#end
+#end
+                            <li>
+                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.treeTable.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+
+            <div class="btn-group-sm" id="toolbar" role="group">
+                <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="${permissionPrefix}:add">
+                    <i class="fa fa-plus"></i> 新增
+                </a>
+                <a class="btn btn-primary" onclick="$.operate.edit()" shiro:hasPermission="${permissionPrefix}:edit">
+                    <i class="fa fa-edit"></i> 修改
+                </a>
+                <a class="btn btn-info" id="expandAllBtn">
+                    <i class="fa fa-exchange"></i> 展开/折叠
+                </a>
+            </div>
+            <div class="col-sm-12 select-table table-striped">
+                <table id="bootstrap-tree-table"></table>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <script th:inline="javascript">
+        var addFlag = [[${@permission.hasPermi('${permissionPrefix}:add')}]];
+        var editFlag = [[${@permission.hasPermi('${permissionPrefix}:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('${permissionPrefix}:remove')}]];
+#foreach($column in $columns)
+#if(${column.dictType} != '')
+        var ${column.javaField}Datas = [[${@dict.getType('${column.dictType}')}]];
+#end
+#end
+        var prefix = ctx + "${moduleName}/${businessName}";
+
+        $(function() {
+            var options = {
+                code: "${treeCode}",
+                parentCode: "${treeParentCode}",
+                expandColumn: "${expandColumn}",
+                uniqueId: "${pkColumn.javaField}",
+                url: prefix + "/list",
+                createUrl: prefix + "/add/{id}",
+                updateUrl: prefix + "/edit/{id}",
+                removeUrl: prefix + "/remove/{id}",
+                exportUrl: prefix + "/export",
+                modalName: "${functionName}",
+                columns: [{
+                    field: 'selectItem', 
+                    radio: true
+                },
+#foreach($column in $columns)
+#set($dictType=$column.dictType)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && "" != $dictType)
+                {
+                    field : '${javaField}', 
+                    title : '${comment}',
+                    align: 'left',
+                    formatter: function(value, row, index) {
+                        return $.table.selectDictLabel(${javaField}Datas, value);
+                    }
+                },
+#elseif($column.list && "" != $javaField)
+                {
+                    field : '${javaField}', 
+                    title : '${comment}',
+                    align: 'left'
+                },
+#end                
+#end
+                {
+                    title: '操作',
+                    align: 'center',
+                    align: 'left',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-info  btn-xs ' + addFlag + '" href="javascript:void(0)" onclick="$.operate.add(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-plus"></i>新增</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        return actions.join('');
+                    }
+                }]
+            };
+            $.treeTable.init(options);
+        });
+    </script>
+</body>
+</html>

+ 116 - 100
ruoyi-generator/src/main/resources/vm/html/list.html.vm

@@ -1,80 +1,93 @@
 <!DOCTYPE html>
 <html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
 <head>
-	<th:block th:include="include :: header('${tableComment}列表')" />
+    <th:block th:include="include :: header('${functionName}列表')" />
 </head>
 <body class="gray-bg">
      <div class="container-div">
-		<div class="row">
-			<div class="col-sm-12 search-collapse">
-				<form id="formId">
-					<div class="select-list">
-						<ul>
+        <div class="row">
+            <div class="col-sm-12 search-collapse">
+                <form id="formId">
+                    <div class="select-list">
+                        <ul>
 #foreach($column in $columns)
-#if($column.columnName != $primaryKey.columnName)
-#if(!${column.configInfo})
-							<li>
-								${column.columnComment}:<input type="text" name="${column.attrname}"/>
-							</li>
-
-#else
-#if(${column.configInfo.type} == "dict")
-							<li>
-								${column.columnComment}:<select name="${column.attrname}" th:with="type=${@dict.getType('${column.configInfo.value}')}">
-									<option value="">所有</option>
-									<option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
-								</select>
-							</li>
-#elseif(${column.configInfo.type} == "date")
-							<li class="select-time">
-								<label>${column.columnComment}: </label>
-								<input type="text" class="time-input" id="start${column.attrName}" placeholder="开始" name="params[begin${column.attrName}]"/>
-								<span>-</span>
-								<input type="text" class="time-input" id="end${column.attrName}" placeholder="结束" name="params[end${column.attrName}]"/>
-							</li>
-#elseif(${column.configInfo.type} == "fk")					
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else  
+#set($comment=$column.columnComment)
+#end  
+#if($column.htmlType == "input")
+                            <li>
+                                <p>${comment}:</p>
+                                <input type="text" name="${column.javaField}"/>
+                            </li>
+#elseif($column.htmlType == "select" || $column.htmlType == "radio" && "" != $dictType)
+                            <li>
+                                <p>${comment}:</p>
+                                <select name="${column.javaField}" th:with="type=${@dict.getType('${dictType}')}">
+                                    <option value="">所有</option>
+                                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                                </select>
+                            </li>
+#elseif($column.htmlType == "select" || $column.htmlType == "radio" && $dictType)
+                            <li>
+                                <p>${comment}:</p>
+                                <select name="${column.javaField}">
+                                    <option value="">所有</option>
+                                </select>
+                            </li>
+#elseif($column.htmlType == "datetime")
+                            <li class="select-time">
+                                <p>${comment}:</p>
+                                <input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[begin${AttrName}]"/>
+                                <span>-</span>
+                                <input type="text" class="time-input" id="endTime" placeholder="结束时间" name="params[end${AttrName}]"/>
+                            </li>
 #end
 #end
 #end
-#end
-							<li>
-								<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
-								<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
-							</li>
-						</ul>
-					</div>
-				</form>
-			</div>
-			
-	        <div class="btn-group-sm" id="toolbar" role="group">
-				<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="${moduleName}:${classname}:add">
-					<i class="fa fa-plus"></i> 添加
-				</a>
-				<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="${moduleName}:${classname}:edit">
-					<i class="fa fa-edit"></i> 修改
-				</a>
-				<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="${moduleName}:${classname}:remove">
-					<i class="fa fa-remove"></i> 删除
-				</a>
-				<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="${moduleName}:${classname}:export">
-						<i class="fa fa-download"></i> 导出
-				 </a>
-			</div>
-			<div class="col-sm-12 select-table table-striped">
-				<table id="bootstrap-table" data-mobile-responsive="true"></table>
-			</div>
-		</div>
-	</div>
-    <div th:include="include :: footer"></div>
+                            <li>
+                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
+                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </form>
+            </div>
+
+            <div class="btn-group-sm" id="toolbar" role="group">
+                <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="${permissionPrefix}:add">
+                    <i class="fa fa-plus"></i> 添加
+                </a>
+                <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="${permissionPrefix}:edit">
+                    <i class="fa fa-edit"></i> 修改
+                </a>
+                <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="${permissionPrefix}:remove">
+                    <i class="fa fa-remove"></i> 删除
+                </a>
+                <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="${permissionPrefix}:export">
+                    <i class="fa fa-download"></i> 导出
+                 </a>
+            </div>
+            <div class="col-sm-12 select-table table-striped">
+                <table id="bootstrap-table" data-mobile-responsive="true"></table>
+            </div>
+        </div>
+    </div>
+    <th:block th:include="include :: footer" />
     <script th:inline="javascript">
-        var editFlag = [[${@permission.hasPermi('${moduleName}:${classname}:edit')}]];
-        var removeFlag = [[${@permission.hasPermi('${moduleName}:${classname}:remove')}]];
-        var prefix = ctx + "${moduleName}/${classname}";
+        var editFlag = [[${@permission.hasPermi('${permissionPrefix}:edit')}]];
+        var removeFlag = [[${@permission.hasPermi('${permissionPrefix}:remove')}]];
 #foreach($column in $columns)
-#if(${column.configInfo} && ${column.configInfo.type} == 'dict')
-        var datas = [[${@dict.getType('${column.configInfo.value}')}]];
+#if(${column.dictType} != '')
+        var ${column.javaField}Datas = [[${@dict.getType('${column.dictType}')}]];
 #end
 #end
+        var prefix = ctx + "${moduleName}/${businessName}";
 
         $(function() {
             var options = {
@@ -82,48 +95,51 @@
                 createUrl: prefix + "/add",
                 updateUrl: prefix + "/edit/{id}",
                 removeUrl: prefix + "/remove",
-				exportUrl: prefix + "/export",
-                modalName: "${tableComment}",
-		        showExport: true,
+                exportUrl: prefix + "/export",
+                modalName: "${functionName}",
                 columns: [{
-		            checkbox: true
-		        },
+                    checkbox: true
+                },
 #foreach($column in $columns)
-#if($column.columnName == $primaryKey.columnName)
-				{
-					field : '${column.attrname}', 
-					title : '${column.columnComment}',
-					visible: false
-				},
-#elseif($column.columnName != $primaryKey.columnName)
-#if(${column.configInfo} && ${column.configInfo.type} == 'dict')
-				{
-					field : '${column.attrname}', 
-					title : '${column.columnComment}',
-					sortable: true,
-					formatter: function(value, row, index) {
-		            	return $.table.selectDictLabel(datas, value);
-		            }
-				},
+#set($dictType=$column.dictType)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
 #else
-				{
-					field : '${column.attrname}', 
-					title : '${column.columnComment}',
-					sortable: true
-				},
+#set($comment=$column.columnComment)
 #end
-#end				
+#if($column.pk)
+                {
+                    field : '${javaField}', 
+                    title : '${comment}',
+                    visible: false
+                },
+#elseif($column.list && "" != $dictType)
+                {
+                    field : '${javaField}', 
+                    title : '${comment}',
+                    formatter: function(value, row, index) {
+                       return $.table.selectDictLabel(${javaField}Datas, value);
+                    }
+                },
+#elseif($column.list && "" != $javaField)
+                {
+                    field : '${javaField}', 
+                    title : '${comment}'
+                },
+#end                
 #end
-		        {
-		            title: '操作',
-		            align: 'center',
-		            formatter: function(value, row, index) {
-		            	var actions = [];
-		            	actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.${primaryKey.attrname} + '\')"><i class="fa fa-edit"></i>编辑</a> ');
-                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.${primaryKey.attrname} + '\')"><i class="fa fa-remove"></i>删除</a>');
-						return actions.join('');
-		            }
-		        }]
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-edit"></i>编辑</a> ');
+                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.${pkColumn.javaField} + '\')"><i class="fa fa-remove"></i>删除</a>');
+                        return actions.join('');
+                    }
+                }]
             };
             $.table.init(options);
         });

+ 51 - 0
ruoyi-generator/src/main/resources/vm/html/tree.html.vm

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: header('${functionName}树选择')" />
+    <th:block th:include="include :: ztree-css" />
+</head>
+<style>
+    body{height:auto;font-family: "Microsoft YaHei";}
+    button{font-family: "SimSun","Helvetica Neue",Helvetica,Arial;}
+</style>
+<body class="hold-transition box box-main">
+#set($treeId = "${className}?." + $treeCode)
+#set($treeName = "${className}?." + $treeName)
+    <input id="treeId"   name="treeId"    type="hidden" th:value="${${treeId}}"/>
+    <input id="treeName" name="treeName"  type="hidden" th:value="${${treeName}}"/>
+    <div class="wrapper"><div class="treeShowHideButton" onclick="$.tree.toggleSearch();">
+        <label id="btnShow" title="显示搜索" style="display:none;">︾</label>
+        <label id="btnHide" title="隐藏搜索">︽</label>
+    </div>
+    <div class="treeSearchInput" id="search">
+        <label for="keyword">关键字:</label><input type="text" class="empty" id="keyword" maxlength="50">
+        <button class="btn" id="btn" onclick="$.tree.searchNode()"> 搜索 </button>
+    </div>
+    <div class="treeExpandCollapse">
+        <a href="#" onclick="$.tree.expand()">展开</a> /
+        <a href="#" onclick="$.tree.collapse()">折叠</a>
+    </div>
+    <div id="tree" class="ztree treeselect"></div>
+    </div>
+    <th:block th:include="include :: footer" />
+    <th:block th:include="include :: ztree-js" />
+    <script th:inline="javascript">
+        $(function() {
+            var url = ctx + "system/${businessName}/treeData";
+            var options = {
+                url: url,
+                expandLevel: 2,
+                onClick : zOnClick
+            };
+            $.tree.init(options);
+        });
+
+        function zOnClick(event, treeId, treeNode) {
+            var treeId = treeNode.id;
+            var treeName = treeNode.name;
+            $("#treeId").val(treeId);
+            $("#treeName").val(treeName);
+        }
+    </script>
+</body>
+</html>

+ 169 - 96
ruoyi-generator/src/main/resources/vm/java/Controller.java.vm

@@ -12,116 +12,189 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.enums.BusinessType;
-import ${package}.domain.${className};
-import ${package}.service.I${className}Service;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
 import com.ruoyi.common.core.controller.BaseController;
-import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.poi.ExcelUtil;
+#if($table.crud)
+import com.ruoyi.common.core.page.TableDataInfo;
+#elseif($table.tree)
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.core.domain.Ztree;
+#end
 
 /**
- * ${tableComment} 信息操作处理
+ * ${functionName}Controller
  * 
  * @author ${author}
  * @date ${datetime}
  */
 @Controller
-@RequestMapping("/${moduleName}/${classname}")
-public class ${className}Controller extends BaseController
+@RequestMapping("/${moduleName}/${businessName}")
+public class ${ClassName}Controller extends BaseController
 {
-    private String prefix = "${moduleName}/${classname}";
-	
-	@Autowired
-	private I${className}Service ${classname}Service;
-	
-	@RequiresPermissions("${moduleName}:${classname}:view")
-	@GetMapping()
-	public String ${classname}()
-	{
-	    return prefix + "/${classname}";
-	}
-	
-	/**
-	 * 查询${tableComment}列表
-	 */
-	@RequiresPermissions("${moduleName}:${classname}:list")
-	@PostMapping("/list")
-	@ResponseBody
-	public TableDataInfo list(${className} ${classname})
-	{
-		startPage();
-        List<${className}> list = ${classname}Service.select${className}List(${classname});
-		return getDataTable(list);
-	}
-	
-	
-	/**
-	 * 导出${tableComment}列表
-	 */
-	@RequiresPermissions("${moduleName}:${classname}:export")
+    private String prefix = "${moduleName}/${businessName}";
+
+    @Autowired
+    private I${ClassName}Service ${className}Service;
+
+    @RequiresPermissions("${permissionPrefix}:view")
+    @GetMapping()
+    public String ${businessName}()
+    {
+        return prefix + "/${businessName}";
+    }
+
+#if($table.tree)
+    /**
+     * 查询${functionName}树列表
+     */
+    @RequiresPermissions("${permissionPrefix}:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public List<${ClassName}> list(${ClassName} ${className})
+    {
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        return list;
+    }
+#elseif($table.crud)
+    /**
+     * 查询${functionName}列表
+     */
+    @RequiresPermissions("${permissionPrefix}:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list(${ClassName} ${className})
+    {
+        startPage();
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        return getDataTable(list);
+    }
+#end
+
+    /**
+     * 导出${functionName}列表
+     */
+    @RequiresPermissions("${permissionPrefix}:export")
     @PostMapping("/export")
     @ResponseBody
-    public AjaxResult export(${className} ${classname})
+    public AjaxResult export(${ClassName} ${className})
     {
-    	List<${className}> list = ${classname}Service.select${className}List(${classname});
-        ExcelUtil<${className}> util = new ExcelUtil<${className}>(${className}.class);
-        return util.exportExcel(list, "${classname}");
+        List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+        ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
+        return util.exportExcel(list, "${businessName}");
     }
-	
-	/**
-	 * 新增${tableComment}
-	 */
-	@GetMapping("/add")
-	public String add()
-	{
-	    return prefix + "/add";
-	}
-	
-	/**
-	 * 新增保存${tableComment}
-	 */
-	@RequiresPermissions("${moduleName}:${classname}:add")
-	@Log(title = "${tableComment}", businessType = BusinessType.INSERT)
-	@PostMapping("/add")
-	@ResponseBody
-	public AjaxResult addSave(${className} ${classname})
-	{		
-		return toAjax(${classname}Service.insert${className}(${classname}));
-	}
 
-	/**
-	 * 修改${tableComment}
-	 */
-	@GetMapping("/edit/{${primaryKey.attrname}}")
-	public String edit(@PathVariable("${primaryKey.attrname}") ${primaryKey.attrType} ${primaryKey.attrname}, ModelMap mmap)
-	{
-		${className} ${classname} = ${classname}Service.select${className}ById(${primaryKey.attrname});
-		mmap.put("${classname}", ${classname});
-	    return prefix + "/edit";
-	}
-	
-	/**
-	 * 修改保存${tableComment}
-	 */
-	@RequiresPermissions("${moduleName}:${classname}:edit")
-	@Log(title = "${tableComment}", businessType = BusinessType.UPDATE)
-	@PostMapping("/edit")
-	@ResponseBody
-	public AjaxResult editSave(${className} ${classname})
-	{		
-		return toAjax(${classname}Service.update${className}(${classname}));
-	}
-	
-	/**
-	 * 删除${tableComment}
-	 */
-	@RequiresPermissions("${moduleName}:${classname}:remove")
-	@Log(title = "${tableComment}", businessType = BusinessType.DELETE)
-	@PostMapping( "/remove")
-	@ResponseBody
-	public AjaxResult remove(String ids)
-	{		
-		return toAjax(${classname}Service.delete${className}ByIds(ids));
-	}
-	
+#if($table.crud)
+    /**
+     * 新增${functionName}
+     */
+    @GetMapping("/add")
+    public String add()
+    {
+        return prefix + "/add";
+    }
+#elseif($table.tree)
+    /**
+     * 新增${functionName}
+     */
+    @GetMapping(value = { "/add/{${pkColumn.javaField}}", "/add/" })
+    public String add(@PathVariable(value = "${pkColumn.javaField}", required = false) Long ${pkColumn.javaField}, ModelMap mmap)
+    {
+        if (StringUtils.isNotNull(${pkColumn.javaField}))
+        {
+            mmap.put("${className}", ${className}Service.select${ClassName}ById(${pkColumn.javaField}));
+        }
+        return prefix + "/add";
+    }
+#end
+
+    /**
+     * 新增保存${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:add")
+    @Log(title = "${functionName}", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave(${ClassName} ${className})
+    {
+        return toAjax(${className}Service.insert${ClassName}(${className}));
+    }
+
+    /**
+     * 修改${functionName}
+     */
+    @GetMapping("/edit/{${pkColumn.javaField}}")
+    public String edit(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}, ModelMap mmap)
+    {
+        ${ClassName} ${className} = ${className}Service.select${ClassName}ById(${pkColumn.javaField});
+        mmap.put("${className}", ${className});
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:edit")
+    @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave(${ClassName} ${className})
+    {
+        return toAjax(${className}Service.update${ClassName}(${className}));
+    }
+
+#if($table.crud)
+    /**
+     * 删除${functionName}
+     */
+    @RequiresPermissions("${permissionPrefix}:remove")
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+    @PostMapping( "/remove")
+    @ResponseBody
+    public AjaxResult remove(String ids)
+    {
+        return toAjax(${className}Service.delete${ClassName}ByIds(ids));
+    }
+#elseif($table.tree)
+    /**
+     * 删除
+     */
+    @RequiresPermissions("${permissionPrefix}:remove")
+    @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+    @GetMapping("/remove/{${pkColumn.javaField}}")
+    @ResponseBody
+    public AjaxResult remove(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
+    {
+        return toAjax(${className}Service.delete${ClassName}ById(${pkColumn.javaField}));
+    }
+#end
+#if($table.tree)
+
+    /**
+     * 选择${functionName}树
+     */
+#set($BusinessName=$businessName.substring(0,1).toUpperCase() + ${businessName.substring(1)})
+    @GetMapping(value = { "/select${BusinessName}Tree/{${pkColumn.javaField}}", "/select${BusinessName}Tree/" })
+    public String select${BusinessName}Tree(@PathVariable(value = "${pkColumn.javaField}", required = false) Long ${pkColumn.javaField}, ModelMap mmap)
+    {
+        if (StringUtils.isNotNull(${pkColumn.javaField}))
+        {
+            mmap.put("${className}", ${className}Service.select${ClassName}ById(${pkColumn.javaField}));
+        }
+        return prefix + "/tree";
+    }
+
+    /**
+     * 加载${functionName}树列表
+     */
+    @GetMapping("/treeData")
+    @ResponseBody
+    public List<Ztree> treeData()
+    {
+        List<Ztree> ztrees = ${className}Service.select${ClassName}Tree();
+        return ztrees;
+    }
+#end
 }

+ 37 - 38
ruoyi-generator/src/main/resources/vm/java/Mapper.java.vm

@@ -1,62 +1,61 @@
-package ${package}.mapper;
+package ${packageName}.mapper;
 
-import ${package}.domain.${className};
-import java.util.List;	
+import ${packageName}.domain.${ClassName};
+import java.util.List;
 
 /**
- * ${tableComment} 数据层
+ * ${functionName}Mapper接口
  * 
  * @author ${author}
  * @date ${datetime}
  */
-public interface ${className}Mapper 
+public interface ${ClassName}Mapper 
 {
-	/**
-     * 查询${tableComment}信息
+    /**
+     * 查询${functionName}
      * 
-     * @param ${primaryKey.attrname} ${tableComment}ID
-     * @return ${tableComment}信息
+     * @param ${pkColumn.javaField} ${functionName}ID
+     * @return ${functionName}
      */
-	public ${className} select${className}ById(${primaryKey.attrType} ${primaryKey.attrname});
-	
-	/**
-     * 查询${tableComment}列表
+    public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
+
+    /**
+     * 查询${functionName}列表
      * 
-     * @param ${classname} ${tableComment}信息
-     * @return ${tableComment}集合
+     * @param ${className} ${functionName}
+     * @return ${functionName}集合
      */
-	public List<${className}> select${className}List(${className} ${classname});
-	
-	/**
-     * 新增${tableComment}
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+    /**
+     * 新增${functionName}
      * 
-     * @param ${classname} ${tableComment}信息
+     * @param ${className} ${functionName}
      * @return 结果
      */
-	public int insert${className}(${className} ${classname});
-	
-	/**
-     * 修改${tableComment}
+    public int insert${ClassName}(${ClassName} ${className});
+
+    /**
+     * 修改${functionName}
      * 
-     * @param ${classname} ${tableComment}信息
+     * @param ${className} ${functionName}
      * @return 结果
      */
-	public int update${className}(${className} ${classname});
-	
-	/**
-     * 删除${tableComment}
+    public int update${ClassName}(${ClassName} ${className});
+
+    /**
+     * 删除${functionName}
      * 
-     * @param ${primaryKey.attrname} ${tableComment}ID
+     * @param ${pkColumn.javaField} ${functionName}ID
      * @return 结果
      */
-	public int delete${className}ById(${primaryKey.attrType} ${primaryKey.attrname});
-	
-	/**
-     * 批量删除${tableComment}
+    public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
+
+    /**
+     * 批量删除${functionName}
      * 
-     * @param ${primaryKey.attrname}s 需要删除的数据ID
+     * @param ${pkColumn.javaField}s 需要删除的数据ID
      * @return 结果
      */
-	public int delete${className}ByIds(String[] ${primaryKey.attrname}s);
-	
-}
+    public int delete${ClassName}ByIds(String[] ${pkColumn.javaField}s);
+}

+ 49 - 30
ruoyi-generator/src/main/resources/vm/java/Service.java.vm

@@ -1,54 +1,73 @@
-package ${package}.service;
+package ${packageName}.service;
 
-import ${package}.domain.${className};
+import ${packageName}.domain.${ClassName};
 import java.util.List;
+#if($table.tree)
+import com.ruoyi.common.core.domain.Ztree;
+#end
 
 /**
- * ${tableComment} 服务层
+ * ${functionName}Service接口
  * 
  * @author ${author}
  * @date ${datetime}
  */
-public interface I${className}Service 
+public interface I${ClassName}Service 
 {
-	/**
-     * 查询${tableComment}信息
+    /**
+     * 查询${functionName}
      * 
-     * @param ${primaryKey.attrname} ${tableComment}ID
-     * @return ${tableComment}信息
+     * @param ${pkColumn.javaField} ${functionName}ID
+     * @return ${functionName}
      */
-	public ${className} select${className}ById(${primaryKey.attrType} ${primaryKey.attrname});
-	
-	/**
-     * 查询${tableComment}列表
+    public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
+
+    /**
+     * 查询${functionName}列表
      * 
-     * @param ${classname} ${tableComment}信息
-     * @return ${tableComment}集合
+     * @param ${className} ${functionName}
+     * @return ${functionName}集合
      */
-	public List<${className}> select${className}List(${className} ${classname});
-	
-	/**
-     * 新增${tableComment}
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+    /**
+     * 新增${functionName}
      * 
-     * @param ${classname} ${tableComment}信息
+     * @param ${className} ${functionName}
      * @return 结果
      */
-	public int insert${className}(${className} ${classname});
-	
-	/**
-     * 修改${tableComment}
+    public int insert${ClassName}(${ClassName} ${className});
+
+    /**
+     * 修改${functionName}
      * 
-     * @param ${classname} ${tableComment}信息
+     * @param ${className} ${functionName}
      * @return 结果
      */
-	public int update${className}(${className} ${classname});
-		
-	/**
-     * 删除${tableComment}信息
+    public int update${ClassName}(${ClassName} ${className});
+
+    /**
+     * 批量删除${functionName}
      * 
      * @param ids 需要删除的数据ID
      * @return 结果
      */
-	public int delete${className}ByIds(String ids);
-	
+    public int delete${ClassName}ByIds(String ids);
+
+    /**
+     * 删除${functionName}信息
+     * 
+     * @param ${pkColumn.javaField} ${functionName}ID
+     * @return 结果
+     */
+    public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField});
+#if($table.tree)
+
+    /**
+     * 查询${functionName}树列表
+     * 
+     * @return 所有${functionName}信息
+     */
+    public List<Ztree> select${ClassName}Tree();
+#end
 }

+ 108 - 51
ruoyi-generator/src/main/resources/vm/java/ServiceImpl.java.vm

@@ -1,83 +1,140 @@
-package ${package}.service.impl;
+package ${packageName}.service.impl;
 
 import java.util.List;
+#if($table.tree)
+import java.util.ArrayList;
+import com.ruoyi.common.core.domain.Ztree;
+#end
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
+import com.ruoyi.common.utils.DateUtils;
+#break
+#end
+#end
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import ${package}.mapper.${className}Mapper;
-import ${package}.domain.${className};
-import ${package}.service.I${className}Service;
+import ${packageName}.mapper.${ClassName}Mapper;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
 import com.ruoyi.common.core.text.Convert;
 
 /**
- * ${tableComment} 服务层实现
+ * ${functionName}Service业务层处理
  * 
  * @author ${author}
  * @date ${datetime}
  */
 @Service
-public class ${className}ServiceImpl implements I${className}Service 
+public class ${ClassName}ServiceImpl implements I${ClassName}Service 
 {
-	@Autowired
-	private ${className}Mapper ${classname}Mapper;
+    @Autowired
+    private ${ClassName}Mapper ${className}Mapper;
 
-	/**
-     * 查询${tableComment}信息
+    /**
+     * 查询${functionName}
      * 
-     * @param ${primaryKey.attrname} ${tableComment}ID
-     * @return ${tableComment}信息
+     * @param ${pkColumn.javaField} ${functionName}ID
+     * @return ${functionName}
      */
     @Override
-	public ${className} select${className}ById(${primaryKey.attrType} ${primaryKey.attrname})
-	{
-	    return ${classname}Mapper.select${className}ById(${primaryKey.attrname});
-	}
-	
-	/**
-     * 查询${tableComment}列表
+    public ${ClassName} select${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField})
+    {
+        return ${className}Mapper.select${ClassName}ById(${pkColumn.javaField});
+    }
+
+    /**
+     * 查询${functionName}列表
      * 
-     * @param ${classname} ${tableComment}信息
-     * @return ${tableComment}集合
+     * @param ${className} ${functionName}
+     * @return ${functionName}
      */
-	@Override
-	public List<${className}> select${className}List(${className} ${classname})
-	{
-	    return ${classname}Mapper.select${className}List(${classname});
-	}
-	
+    @Override
+    public List<${ClassName}> select${ClassName}List(${ClassName} ${className})
+    {
+        return ${className}Mapper.select${ClassName}List(${className});
+    }
+
     /**
-     * 新增${tableComment}
+     * 新增${functionName}
      * 
-     * @param ${classname} ${tableComment}信息
+     * @param ${className} ${functionName}
      * @return 结果
      */
-	@Override
-	public int insert${className}(${className} ${classname})
-	{
-	    return ${classname}Mapper.insert${className}(${classname});
-	}
-	
-	/**
-     * 修改${tableComment}
+    @Override
+    public int insert${ClassName}(${ClassName} ${className})
+    {
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime')
+        ${className}.setCreateTime(DateUtils.getNowDate());
+#end
+#end
+        return ${className}Mapper.insert${ClassName}(${className});
+    }
+
+    /**
+     * 修改${functionName}
      * 
-     * @param ${classname} ${tableComment}信息
+     * @param ${className} ${functionName}
      * @return 结果
      */
-	@Override
-	public int update${className}(${className} ${classname})
-	{
-	    return ${classname}Mapper.update${className}(${classname});
-	}
+    @Override
+    public int update${ClassName}(${ClassName} ${className})
+    {
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime')
+        ${className}.setUpdateTime(DateUtils.getNowDate());
+#end
+#end
+        return ${className}Mapper.update${ClassName}(${className});
+    }
 
-	/**
-     * 删除${tableComment}对象
+    /**
+     * 删除${functionName}对象
      * 
      * @param ids 需要删除的数据ID
      * @return 结果
      */
-	@Override
-	public int delete${className}ByIds(String ids)
-	{
-		return ${classname}Mapper.delete${className}ByIds(Convert.toStrArray(ids));
-	}
-	
+    @Override
+    public int delete${ClassName}ByIds(String ids)
+    {
+        return ${className}Mapper.delete${ClassName}ByIds(Convert.toStrArray(ids));
+    }
+
+    /**
+     * 删除${functionName}信息
+     * 
+     * @param ${pkColumn.javaField} ${functionName}ID
+     * @return 结果
+     */
+    public int delete${ClassName}ById(${pkColumn.javaType} ${pkColumn.javaField})
+    {
+        return ${className}Mapper.delete${ClassName}ById(${pkColumn.javaField});
+    }
+#if($table.tree)
+
+    /**
+     * 查询${functionName}树列表
+     * 
+     * @return 所有${functionName}信息
+     */
+    @Override
+    public List<Ztree> select${ClassName}Tree()
+    {
+        List<${ClassName}> ${className}List = ${className}Mapper.select${ClassName}List(new ${ClassName}());
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        for (${ClassName} ${className} : ${className}List)
+        {
+            Ztree ztree = new Ztree();
+#set($TreeCode=$treeCode.substring(0,1).toUpperCase() + ${treeCode.substring(1)})
+#set($TreeParentCode=$treeParentCode.substring(0,1).toUpperCase() + ${treeParentCode.substring(1)})
+#set($TreeName=$treeName.substring(0,1).toUpperCase() + ${treeName.substring(1)})
+            ztree.setId(${className}.get${TreeCode}());
+            ztree.setpId(${className}.get${TreeParentCode}());
+            ztree.setName(${className}.get${TreeName}());
+            ztree.setTitle(${className}.get${TreeName}());
+            ztrees.add(ztree);
+        }
+        return ztrees;
+    }
+#end
 }

+ 47 - 28
ruoyi-generator/src/main/resources/vm/java/domain.java.vm

@@ -1,56 +1,75 @@
-package ${package}.domain;
+package ${packageName}.domain;
 
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+#if($table.crud)
 import com.ruoyi.common.core.domain.BaseEntity;
-#foreach ($column in $columns)
-#if($column.attrType == 'Date' && ($column.attrname != 'createBy' && $column.attrname != 'createTime' && $column.attrname != 'updateBy' && $column.attrname != 'updateTime' && $column.attrname != 'remark'))
-import java.util.Date;
-#break
-#end
-#end
-#foreach ($column in $columns)
-#if($column.attrType == 'BigDecimal')
-import java.math.BigDecimal;
-#break
+#elseif($table.tree)
+import com.ruoyi.common.core.domain.TreeEntity;
 #end
+#foreach ($import in $importList)
+import ${import};
 #end
 
 /**
- * ${tableComment}表 ${tableName}
+ * ${functionName}对象 ${tableName}
  * 
  * @author ${author}
  * @date ${datetime}
  */
-public class ${className} extends BaseEntity
+#if($table.crud)
+#set($Entity="BaseEntity")
+#elseif($table.tree)
+#set($Entity="TreeEntity")
+#end
+public class ${ClassName} extends ${Entity}
 {
-	private static final long serialVersionUID = 1L;
-	
+    private static final long serialVersionUID = 1L;
+
 #foreach ($column in $columns)
-#if($column.attrname != 'createBy' && $column.attrname != 'createTime' && $column.attrname != 'updateBy' && $column.attrname != 'updateTime' && $column.attrname != 'remark')
-	/** $column.columnComment */
-	private $column.attrType $column.attrname;
+#if(!$column.superColumn)
+    /** $column.columnComment */
+#if($column.list)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
 #end
+#if($parentheseIndex != -1)
+    @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+#elseif($column.javaType == 'Date')
+    @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
+#else
+    @Excel(name = "${comment}")
 #end
+#end
+    private $column.javaType $column.javaField;
 
+#end
+#end
 #foreach ($column in $columns)
-#if($column.attrname != 'createBy' && $column.attrname != 'createTime' && $column.attrname != 'updateBy' && $column.attrname != 'updateTime' && $column.attrname != 'remark')
-	public void set${column.attrName}($column.attrType $column.attrname) 
-	{
-		this.$column.attrname = $column.attrname;
-	}
+#if(!$column.superColumn)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+    public void set${AttrName}($column.javaType $column.javaField) 
+    {
+        this.$column.javaField = $column.javaField;
+    }
 
-	public $column.attrType get${column.attrName}() 
-	{
-		return $column.attrname;
-	}
+    public $column.javaType get${AttrName}() 
+    {
+        return $column.javaField;
+    }
 #end
 #end
 
+    @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
 #foreach ($column in $columns)
-            .append("${column.attrname}", get${column.attrName}())
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+            .append("${column.javaField}", get${AttrName}())
 #end
             .toString();
     }

+ 5 - 5
ruoyi-generator/src/main/resources/vm/sql/sql.vm

@@ -1,19 +1,19 @@
 -- 菜单 SQL
 insert into sys_menu (menu_name, parent_id, order_num, url,menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('${tableComment}', '3', '1', '/${moduleName}/${classname}', 'C', '0', '${moduleName}:${classname}:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${tableComment}菜单');
+values('${functionName}', '3', '1', '/${moduleName}/${businessName}', 'C', '0', '${permissionPrefix}:view', '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '${functionName}菜单');
 
 -- 按钮父菜单ID
 SELECT @parentId := LAST_INSERT_ID();
 
 -- 按钮 SQL
 insert into sys_menu  (menu_name, parent_id, order_num, url,menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('${tableComment}查询', @parentId, '1',  '#',  'F', '0', '${moduleName}:${classname}:list',         '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
+values('${functionName}查询', @parentId, '1',  '#',  'F', '0', '${permissionPrefix}:list',         '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
 insert into sys_menu  (menu_name, parent_id, order_num, url,menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('${tableComment}新增', @parentId, '2',  '#',  'F', '0', '${moduleName}:${classname}:add',          '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
+values('${functionName}新增', @parentId, '2',  '#',  'F', '0', '${permissionPrefix}:add',          '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
 insert into sys_menu  (menu_name, parent_id, order_num, url,menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('${tableComment}修改', @parentId, '3',  '#',  'F', '0', '${moduleName}:${classname}:edit',         '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
+values('${functionName}修改', @parentId, '3',  '#',  'F', '0', '${permissionPrefix}:edit',         '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
 
 insert into sys_menu  (menu_name, parent_id, order_num, url,menu_type, visible, perms, icon, create_by, create_time, update_by, update_time, remark)
-values('${tableComment}删除', @parentId, '4',  '#',  'F', '0', '${moduleName}:${classname}:remove',       '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');
+values('${functionName}删除', @parentId, '4',  '#',  'F', '0', '${permissionPrefix}:remove',       '#', 'admin', '2018-03-01', 'ry', '2018-03-01', '');

+ 68 - 32
ruoyi-generator/src/main/resources/vm/xml/Mapper.xml.vm

@@ -2,70 +2,106 @@
 <!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="${package}.mapper.${className}Mapper">
+<mapper namespace="${packageName}.mapper.${ClassName}Mapper">
     
-    <resultMap type="${className}" id="${className}Result">
+    <resultMap type="${ClassName}" id="${ClassName}Result">
 #foreach ($column in $columns)
-        <result property="${column.attrname}"    column="${column.columnName}"    />
+        <result property="${column.javaField}"    column="${column.columnName}"    />
+#end
+#if($table.tree)
+        <result property="parentName" column="parent_name" />
 #end
     </resultMap>
-	
-	<sql id="select${className}Vo">
+
+    <sql id="select${ClassName}Vo">
         select#foreach($column in $columns) $column.columnName#if($velocityCount != $columns.size()),#end#end from ${tableName}
     </sql>
-	
-    <select id="select${className}List" parameterType="${className}" resultMap="${className}Result">
-        <include refid="select${className}Vo"/>
+
+    <select id="select${ClassName}List" parameterType="${ClassName}" resultMap="${ClassName}Result">
+        <include refid="select${ClassName}Vo"/>
         <where>  
 #foreach($column in $columns)
-            <if test="$column.attrname != null #if($column.attrType == 'String' ) and $column.attrname.trim() != '' #end"> and $column.columnName = #{$column.attrname}</if>
- #end
+#set($queryType=$column.queryType)
+#set($javaField=$column.javaField)
+#set($javaType=$column.javaType)
+#set($columnName=$column.columnName)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#if($column.query)
+#if($column.queryType == "EQ")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName = #{$javaField}</if>
+#elseif($queryType == "NE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName != #{$javaField}</if>
+#elseif(\$queryType == "GT")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &gt; #{$javaField}</if>
+#elseif(\$queryType == "GTE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &gt;= #{$javaField}</if>
+#elseif(\$queryType == "LT")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &lt; #{$javaField}</if>
+#elseif(\$queryType == "LTE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName &lt;= #{$javaField}</if>
+#elseif($queryType == "LIKE")
+            <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName like concat('%', #{$javaField}, '%')</if>
+#elseif($queryType == "BETWEEN")
+            <if test="params.begin$AttrName != null and params.begin$AttrName != '' and params.end$AttrName != null and params.end$AttrName != ''"> and $columnName between #{params.begin$AttrName} and #{params.end$AttrName}</if>
+#end
+#end
+#end
         </where>
+#if($table.tree)
+        order by ${tree_parent_code}
+#end
     </select>
     
-    <select id="select${className}ById" parameterType="${primaryKey.attrType}" resultMap="${className}Result">
-        <include refid="select${className}Vo"/>
-        where ${primaryKey.columnName} = #{${primaryKey.attrname}}
+    <select id="select${ClassName}ById" parameterType="${pkColumn.javaType}" resultMap="${ClassName}Result">
+#if($table.crud)
+        <include refid="select${ClassName}Vo"/>
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+#elseif($table.tree)
+        select#foreach($column in $columns) t.$column.columnName,#end p.dept_name as parent_name
+        from ${tableName} t
+        left join ${tableName} p on p.${pkColumn.columnName} = t.${tree_parent_code}
+        where t.${pkColumn.columnName} = #{${pkColumn.javaField}}
+#end
     </select>
         
-    <insert id="insert${className}" parameterType="${className}"#if($primaryKey.extra == 'auto_increment') useGeneratedKeys="true" keyProperty="$primaryKey.attrname"#end>
+    <insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
         insert into ${tableName}
-		<trim prefix="(" suffix=")" suffixOverrides=",">
+        <trim prefix="(" suffix=")" suffixOverrides=",">
 #foreach($column in $columns)
-#if($column.columnName != $primaryKey.columnName || $primaryKey.extra != 'auto_increment')
-			<if test="$column.attrname != null #if($column.attrType == 'String' ) and $column.attrname != '' #end ">$column.columnName,</if>
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+            <if test="$column.javaField != null #if($column.javaType == 'String' ) and $column.javaField != ''#end">$column.columnName,</if>
 #end
 #end
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
 #foreach($column in $columns)
-#if($column.columnName != $primaryKey.columnName || $primaryKey.extra != 'auto_increment')
-			<if test="$column.attrname != null #if($column.attrType == 'String' ) and $column.attrname != '' #end ">#{$column.attrname},</if>
-#end			
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+            <if test="$column.javaField != null #if($column.javaType == 'String' ) and $column.javaField != ''#end">#{$column.javaField},</if>
+#end
 #end
          </trim>
     </insert>
-	 
-    <update id="update${className}" parameterType="${className}">
+
+    <update id="update${ClassName}" parameterType="${ClassName}">
         update ${tableName}
         <trim prefix="SET" suffixOverrides=",">
 #foreach($column in $columns)
-#if($column.columnName != $primaryKey.columnName)
-            <if test="$column.attrname != null #if($column.attrType == 'String' ) and $column.attrname != '' #end ">$column.columnName = #{$column.attrname},</if>
+#if($column.columnName != $pkColumn.columnName)
+            <if test="$column.javaField != null #if($column.javaType == 'String' ) and $column.javaField != ''#end">$column.columnName = #{$column.javaField},</if>
 #end
 #end
         </trim>
-        where ${primaryKey.columnName} = #{${primaryKey.attrname}}
+        where ${pkColumn.columnName} = #{${pkColumn.javaField}}
     </update>
 
-	<delete id="delete${className}ById" parameterType="${primaryKey.attrType}">
-        delete from ${tableName} where ${primaryKey.columnName} = #{${primaryKey.attrname}}
+    <delete id="delete${ClassName}ById" parameterType="${pkColumn.javaType}">
+        delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
     </delete>
-	
-    <delete id="delete${className}ByIds" parameterType="String">
-        delete from ${tableName} where ${primaryKey.columnName} in 
-        <foreach item="${primaryKey.attrname}" collection="array" open="(" separator="," close=")">
-            #{${primaryKey.attrname}}
+
+    <delete id="delete${ClassName}ByIds" parameterType="String">
+        delete from ${tableName} where ${pkColumn.columnName} in 
+        <foreach item="${pkColumn.javaField}" collection="array" open="(" separator="," close=")">
+            #{${pkColumn.javaField}}
         </foreach>
     </delete>
     

+ 1 - 1
ruoyi-quartz/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.4</version>
+        <version>4.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
ruoyi-system/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.4</version>
+        <version>4.0.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java

@@ -35,6 +35,14 @@ public interface SysDictTypeMapper
      */
     public SysDictType selectDictTypeById(Long dictId);
 
+    /**
+     * 根据字典类型查询信息
+     * 
+     * @param dictType 字典类型
+     * @return 字典类型
+     */
+    public SysDictType selectDictTypeByType(String dictType);
+
     /**
      * 通过字典ID删除字典信息
      * 

+ 17 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java

@@ -1,6 +1,7 @@
 package com.ruoyi.system.service;
 
 import java.util.List;
+import com.ruoyi.common.core.domain.Ztree;
 import com.ruoyi.system.domain.SysDictType;
 
 /**
@@ -33,6 +34,14 @@ public interface ISysDictTypeService
      */
     public SysDictType selectDictTypeById(Long dictId);
 
+    /**
+     * 根据字典类型查询信息
+     * 
+     * @param dictType 字典类型
+     * @return 字典类型
+     */
+    public SysDictType selectDictTypeByType(String dictType);
+
     /**
      * 通过字典ID删除字典信息
      * 
@@ -73,4 +82,12 @@ public interface ISysDictTypeService
      * @return 结果
      */
     public String checkDictTypeUnique(SysDictType dictType);
+
+    /**
+     * 查询字典类型树
+     * 
+     * @param dictType 字典类型
+     * @return 所有字典类型
+     */
+    public List<Ztree> selectDictTree(SysDictType dictType);
 }

+ 45 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java

@@ -1,10 +1,12 @@
 package com.ruoyi.system.service.impl;
 
+import java.util.ArrayList;
 import java.util.List;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.Ztree;
 import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.exception.BusinessException;
 import com.ruoyi.common.utils.StringUtils;
@@ -62,6 +64,17 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
         return dictTypeMapper.selectDictTypeById(dictId);
     }
 
+    /**
+     * 根据字典类型查询信息
+     * 
+     * @param dictType 字典类型
+     * @return 字典类型
+     */
+    public SysDictType selectDictTypeByType(String dictType)
+    {
+        return dictTypeMapper.selectDictTypeByType(dictType);
+    }
+
     /**
      * 通过字典ID删除字典信息
      * 
@@ -140,4 +153,36 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService
         }
         return UserConstants.DICT_TYPE_UNIQUE;
     }
+
+    /**
+     * 查询字典类型树
+     * 
+     * @param dictType 字典类型
+     * @return 所有字典类型
+     */
+    public List<Ztree> selectDictTree(SysDictType dictType)
+    {
+        List<Ztree> ztrees = new ArrayList<Ztree>();
+        List<SysDictType> dictList = dictTypeMapper.selectDictTypeList(dictType);
+        for (SysDictType dict : dictList)
+        {
+            if (UserConstants.DICT_NORMAL.equals(dict.getStatus()))
+            {
+                Ztree ztree = new Ztree();
+                ztree.setId(dict.getDictId());
+                ztree.setName(transDictName(dict));
+                ztree.setTitle(dict.getDictType());
+                ztrees.add(ztree);
+            }
+        }
+        return ztrees;
+    }
+
+    public String transDictName(SysDictType dictType)
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append("(" + dictType.getDictName() + ")");
+        sb.append("&nbsp;&nbsp;&nbsp;" + dictType.getDictType());
+        return sb.toString();
+    }
 }

+ 2 - 2
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java

@@ -206,7 +206,7 @@ public class SysMenuServiceImpl implements ISysMenuService
             Ztree ztree = new Ztree();
             ztree.setId(menu.getMenuId());
             ztree.setpId(menu.getParentId());
-            ztree.setName(transMenuName(menu, roleMenuList, permsFlag));
+            ztree.setName(transMenuName(menu, permsFlag));
             ztree.setTitle(menu.getMenuName());
             if (isCheck)
             {
@@ -217,7 +217,7 @@ public class SysMenuServiceImpl implements ISysMenuService
         return ztrees;
     }
 
-    public String transMenuName(SysMenu menu, List<String> roleMenuList, boolean permsFlag)
+    public String transMenuName(SysMenu menu, boolean permsFlag)
     {
         StringBuffer sb = new StringBuffer();
         sb.append(menu.getMenuName());

+ 5 - 0
ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml

@@ -50,6 +50,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		where dict_id = #{dictId}
 	</select>
 	
+	<select id="selectDictTypeByType" parameterType="String" resultMap="SysDictTypeResult">
+		<include refid="selectDictTypeVo"/>
+		where dict_type = #{dictType}
+	</select>
+	
 	<select id="checkDictTypeUnique" parameterType="String" resultMap="SysDictTypeResult">
 		<include refid="selectDictTypeVo"/>
 		where dict_type = #{dictType}

+ 57 - 1
sql/ry_20190719.sql → sql/ry_20190808.sql

@@ -632,4 +632,60 @@ create table sys_notice (
 -- 初始化-公告信息表数据
 -- ----------------------------
 insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
-insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容',   '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
+insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容',   '0', 'admin', '2018-03-16 11-33-00', 'ry', '2018-03-16 11-33-00', '管理员');
+
+
+-- ----------------------------
+-- 19、代码生成业务表
+-- ----------------------------
+drop table if exists gen_table;
+create table gen_table (
+  table_id          bigint(20)      not null auto_increment    comment '编号',
+  table_name        varchar(200)    default ''                 comment '表名称',
+  table_comment     varchar(500)    default ''                 comment '表描述',
+  class_name        varchar(100)    default ''                 comment '实体类名称',
+  tpl_category      varchar(200)    default 'crud'             comment '使用的模板(crud单表操作 tree树表操作)',
+  package_name      varchar(100)                               comment '生成包路径',
+  module_name       varchar(30)                                comment '生成模块名',
+  business_name     varchar(30)                                comment '生成业务名',
+  function_name     varchar(50)                                comment '生成功能名',
+  function_author   varchar(50)                                comment '生成功能作者',
+  options           varchar(1000)                              comment '其它生成选项',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time 	    datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  remark            varchar(500)    default null               comment '备注',
+  primary key (table_id)
+) engine=innodb auto_increment=1 comment = '代码生成业务表';
+
+
+-- ----------------------------
+-- 20、代码生成业务表字段
+-- ----------------------------
+drop table if exists gen_table_column;
+create table gen_table_column (
+  column_id         bigint(20)      not null auto_increment    comment '编号',
+  table_id          varchar(64)                                comment '归属表编号',
+  column_name       varchar(200)                               comment '列名称',
+  column_comment    varchar(500)                               comment '列描述',
+  column_type       varchar(100)                               comment '列类型',
+  java_type         varchar(500)                               comment 'JAVA类型',
+  java_field        varchar(200)                               comment 'JAVA字段名',
+  is_pk             char(1)                                    comment '是否主键(1是)',
+  is_increment      char(1)                                    comment '是否自增(1是)',
+  is_required       char(1)                                    comment '是否必填(1是)',
+  is_insert         char(1)                                    comment '是否为插入字段(1是)',
+  is_edit           char(1)                                    comment '是否编辑字段(1是)',
+  is_list           char(1)                                    comment '是否列表字段(1是)',
+  is_query          char(1)                                    comment '是否查询字段(1是)',
+  query_type        varchar(200)    default '='                comment '查询方式(等于、不等于、大于、小于、范围)',
+  html_type         varchar(200)                               comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)',
+  dict_type         varchar(200)    default ''                 comment '字典类型',
+  sort              int                                        comment '排序',
+  create_by         varchar(64)     default ''                 comment '创建者',
+  create_time 	    datetime                                   comment '创建时间',
+  update_by         varchar(64)     default ''                 comment '更新者',
+  update_time       datetime                                   comment '更新时间',
+  primary key (column_id)
+) engine=innodb auto_increment=1 comment = '代码生成业务表字段';