Browse Source

完成代码生成器~

YunaiV 4 years ago
parent
commit
2f66829a41

+ 0 - 30
ruoyi-common/src/main/java/com/ruoyi/generator/config/GenConfig.java

@@ -1,30 +0,0 @@
-package com.ruoyi.generator.config;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.PropertySource;
-import org.springframework.stereotype.Component;
-
-/**
- * 读取代码生成相关配置
- *
- * @author ruoyi
- */
-@Component
-@ConfigurationProperties(prefix = "gen")
-@PropertySource(value = { "classpath:generator.yml" })
-public class GenConfig {
-
-    /** 作者 */
-    public static String author;
-
-    /** 生成包路径 */
-    public static String packageName;
-
-    /** 自动去除表前缀,默认是false */
-    public static boolean autoRemovePre;
-
-    /** 表前缀(类名不会包含表前缀) */
-    public static String tablePrefix;
-
-}

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

@@ -1,45 +0,0 @@
-package com.ruoyi.generator.domain;
-
-import java.util.List;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
-
-import org.apache.commons.lang3.ArrayUtils;
-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 {
-
-    /**
-     * 生成包路径
-     */
-    @NotBlank(message = "生成包路径不能为空")
-    private String packageName;
-
-    /**
-     * 其它生成选项
-     */
-    private String options;
-
-    /**
-     * 树编码字段
-     */
-    private String treeCode;
-
-    /**
-     * 树父编码字段
-     */
-    private String treeParentCode;
-
-    /**
-     * 树名称字段
-     */
-    private String treeName;
-
-}

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

@@ -1,265 +0,0 @@
-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.domain.GenTable;
-import com.ruoyi.generator.domain.GenTableColumn;
-
-/**
- * 模板处理工具类
- *
- * @author ruoyi
- */
-public class VelocityUtils {
-
-    /**
-     * 默认上级菜单,系统工具
-     */
-    private static final String DEFAULT_PARENT_MENU_ID = "3";
-
-    /**
-     * 设置模板变量信息
-     *
-     * @return 模板列表
-     */
-    public static VelocityContext prepareContext(GenTable genTable) {
-        String moduleName = genTable.getModuleName();
-        String businessName = genTable.getBusinessName();
-        String packageName = genTable.getPackageName();
-        String tplCategory = genTable.getTplCategory();
-        String functionName = genTable.getFunctionName();
-
-        VelocityContext velocityContext = new VelocityContext();
-        velocityContext.put("tplCategory", genTable.getTplCategory());
-        velocityContext.put("tableName", genTable.getTableName());
-        velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】");
-        velocityContext.put("ClassName", genTable.getClassName());
-        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
-        velocityContext.put("moduleName", genTable.getModuleName());
-        velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
-        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);
-        setMenuVelocityContext(velocityContext, 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));
-        }
-        if (paramsObj.containsKey(GenConstants.TREE_NAME)) {
-            context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME));
-        }
-    }
-
-    /**
-     * 获取模板信息
-     *
-     * @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");
-        templates.add("vm/sql/sql.vm");
-        templates.add("vm/js/api.js.vm");
-        if (GenConstants.TPL_CRUD.equals(tplCategory)) {
-            templates.add("vm/vue/index.vue.vm");
-        } else if (GenConstants.TPL_TREE.equals(tplCategory)) {
-            templates.add("vm/vue/index-tree.vue.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 vuePath = "vue";
-
-        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("sql.vm")) {
-            fileName = businessName + "Menu.sql";
-        } else if (template.contains("api.js.vm")) {
-            fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
-        } else if (template.contains("index.vue.vm")) {
-            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
-        } else if (template.contains("index-tree.vue.vm")) {
-            fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
-        }
-        return fileName;
-    }
-
-    /**
-     * 获取包前缀
-     *
-     * @param packageName 包名称
-     * @return 包前缀名称
-     */
-    public static String getPackagePrefix(String packageName) {
-        int lastIndex = packageName.lastIndexOf(".");
-        String basePackage = StringUtils.substring(packageName, 0, lastIndex);
-        return basePackage;
-    }
-
-    /**
-     * 根据列类型获取导入包
-     *
-     * @param columns 列集合
-     * @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");
-                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
-            } 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);
-    }
-
-    /**
-     * 获取上级菜单ID字段
-     *
-     * @param paramsObj 生成其他选项
-     * @return 上级菜单ID字段
-     */
-    public static String getParentMenuId(JSONObject paramsObj) {
-        if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)) {
-            return paramsObj.getString(GenConstants.PARENT_MENU_ID);
-        }
-        return DEFAULT_PARENT_MENU_ID;
-    }
-
-    /**
-     * 获取树编码
-     *
-     * @param paramsObj 生成其他选项
-     * @return 树编码
-     */
-    public static String getTreecode(JSONObject paramsObj) {
-        if (paramsObj.containsKey(GenConstants.TREE_CODE)) {
-            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 获取树父编码
-     *
-     * @param paramsObj 生成其他选项
-     * @return 树父编码
-     */
-    public static String getTreeParentCode(JSONObject paramsObj) {
-        if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) {
-            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 获取树名称
-     *
-     * @param paramsObj 生成其他选项
-     * @return 树名称
-     */
-    public static String getTreeName(JSONObject paramsObj) {
-        if (paramsObj.containsKey(GenConstants.TREE_NAME)) {
-            return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
-        }
-        return StringUtils.EMPTY;
-    }
-
-    /**
-     * 获取需要在哪一列上面显示展开按钮
-     *
-     * @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 - 10
ruoyi-common/src/main/resources/generator.yml

@@ -1,10 +0,0 @@
-# 代码生成
-gen: 
-  # 作者
-  author: ruoyi
-  # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
-  packageName: com.ruoyi.system
-  # 自动去除表前缀,默认是false
-  autoRemovePre: false
-  # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
-  tablePrefix: sys_

+ 28 - 4
ruoyi-ui/src/api/tool/codegen.js

@@ -27,13 +27,25 @@ export function updateCodegen(data) {
 }
 
 // 基于数据库的表结构,同步数据库的表和字段定义
-export function syncCodegen(tableId) {
+export function syncCodegenFromDB(tableId) {
   return request({
-    url: '/tool/codegen/sync?tableId=' + tableId,
+    url: '/tool/codegen/sync-from-db?tableId=' + tableId,
     method: 'put'
   })
 }
 
+// 基于 SQL 建表语句,同步数据库的表和字段定义
+export function syncCodegenFromSQL(tableId, sql) {
+  return request({
+    url: '/tool/codegen/sync-from-sql?tableId=' + tableId,
+    method: 'put',
+    headers:{
+      'Content-type': 'application/x-www-form-urlencoded'
+    },
+    data: 'tableId=' + tableId + "&sql=" + sql,
+  })
+}
+
 // 预览生成代码
 export function previewCodegen(tableId) {
   return request({
@@ -61,9 +73,9 @@ export function getSchemaTableList(query) {
 }
 
 // 基于数据库的表结构,创建代码生成器的表定义
-export function createCodegenList(tableNames) {
+export function createCodegenListFromDB(tableNames) {
   return request({
-    url: '/tool/codegen/create-list',
+    url: '/tool/codegen/create-list-from-db',
     method: 'post',
     headers:{
       'Content-type': 'application/x-www-form-urlencoded'
@@ -72,6 +84,18 @@ export function createCodegenList(tableNames) {
   })
 }
 
+// 基于 SQL 建表语句,创建代码生成器的表定义
+export function createCodegenListFromSQL(data) {
+  return request({
+    url: '/tool/codegen/create-list-from-sql',
+    method: 'post',
+    headers:{
+      'Content-type': 'application/x-www-form-urlencoded'
+    },
+    data: 'sql=' + data.sql,
+  })
+}
+
 // 删除数据库的表和字段定义
 export function deleteCodegen(tableId) {
   return request({

+ 2 - 2
ruoyi-ui/src/router/index.js

@@ -107,13 +107,13 @@ export const constantRoutes = [
     ]
   },
   {
-    path: '/gen',
+    path: '/codegen',
     component: Layout,
     hidden: true,
     children: [
       {
         path: 'edit/:tableId(\\d+)',
-        component: (resolve) => require(['@/views/tool/gen/editTable'], resolve),
+        component: (resolve) => require(['@/views/tool/codegen/editTable'], resolve),
         name: 'GenEdit',
         meta: { title: '修改生成配置' }
       }

+ 61 - 61
ruoyi-ui/src/views/tool/gen/basicInfoForm.vue → ruoyi-ui/src/views/tool/codegen/basicInfoForm.vue

@@ -1,61 +1,61 @@
-<template>
-  <el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
-    <el-row>
-      <el-col :span="12">
-        <el-form-item label="表名称" prop="tableName">
-          <el-input placeholder="请输入仓库名称" v-model="info.tableName" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="表描述" prop="tableComment">
-          <el-input placeholder="请输入" v-model="info.tableComment" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item label="实体类名称" prop="className">
-          <el-input placeholder="请输入" v-model="info.className" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item label="作者" prop="author">
-          <el-input placeholder="请输入" v-model="info.author" />
-        </el-form-item>
-      </el-col>
-      <el-col :span="24">
-        <el-form-item label="备注" prop="remark">
-          <el-input type="textarea" :rows="3" v-model="info.remark"></el-input>
-        </el-form-item>
-      </el-col>
-    </el-row>
-  </el-form>
-</template>
-<script>
-export default {
-  name: "BasicInfoForm",
-  props: {
-    info: {
-      type: Object,
-      default: null
-    }
-  },
-  data() {
-    return {
-      rules: {
-        tableName: [
-          { required: true, message: "请输入表名称", trigger: "blur" }
-        ],
-        tableComment: [
-          { required: true, message: "请输入表描述", trigger: "blur" }
-        ],
-        className: [
-          { required: true, message: "请输入实体类名称", trigger: "blur" }
-        ],
-        author: [
-          { required: true, message: "请输入作者", trigger: "blur" }
-        ]
-      }
-    };
-  }
-};
-</script>
+<template>
+  <el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item label="表名称" prop="tableName">
+          <el-input placeholder="请输入仓库名称" v-model="info.tableName" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="表描述" prop="tableComment">
+          <el-input placeholder="请输入" v-model="info.tableComment" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item label="实体类名称" prop="className">
+          <el-input placeholder="请输入" v-model="info.className" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="作者" prop="author">
+          <el-input placeholder="请输入" v-model="info.author" />
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="备注" prop="remark">
+          <el-input type="textarea" :rows="3" v-model="info.remark"></el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+<script>
+export default {
+  name: "BasicInfoForm",
+  props: {
+    info: {
+      type: Object,
+      default: null
+    }
+  },
+  data() {
+    return {
+      rules: {
+        tableName: [
+          { required: true, message: "请输入表名称", trigger: "blur" }
+        ],
+        tableComment: [
+          { required: true, message: "请输入表描述", trigger: "blur" }
+        ],
+        className: [
+          { required: true, message: "请输入实体类名称", trigger: "blur" }
+        ],
+        author: [
+          { required: true, message: "请输入作者", trigger: "blur" }
+        ]
+      }
+    };
+  }
+};
+</script>

+ 232 - 233
ruoyi-ui/src/views/tool/gen/editTable.vue → ruoyi-ui/src/views/tool/codegen/editTable.vue

@@ -1,233 +1,232 @@
-<template>
-  <el-card>
-    <el-tabs v-model="activeName">
-      <el-tab-pane label="基本信息" name="basic">
-        <basic-info-form ref="basicInfo" :info="table" />
-      </el-tab-pane>
-      <el-tab-pane label="字段信息" name="cloum">
-        <el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
-          <el-table-column
-            label="字段列名"
-            prop="columnName"
-            min-width="10%"
-            :show-overflow-tooltip="true"
-          />
-          <el-table-column label="字段描述" min-width="10%">
-            <template slot-scope="scope">
-              <el-input v-model="scope.row.columnComment"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column
-            label="物理类型"
-            prop="columnType"
-            min-width="10%"
-            :show-overflow-tooltip="true"
-          />
-          <el-table-column label="Java类型" min-width="11%">
-            <template slot-scope="scope">
-              <el-select v-model="scope.row.javaType">
-                <el-option label="Long" value="Long" />
-                <el-option label="String" value="String" />
-                <el-option label="Integer" value="Integer" />
-                <el-option label="Double" value="Double" />
-                <el-option label="BigDecimal" value="BigDecimal" />
-                <el-option label="Date" value="Date" />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="java属性" min-width="10%">
-            <template slot-scope="scope">
-              <el-input v-model="scope.row.javaField"></el-input>
-            </template>
-          </el-table-column>
-          <el-table-column label="插入" min-width="4%">
-            <template slot-scope="scope">
-              <el-checkbox true-label="true" false-label="false" v-model="scope.row.createOperation"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="编辑" min-width="4%">
-            <template slot-scope="scope">
-              <el-checkbox true-label="true" false-label="false" v-model="scope.row.updateOperation"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="列表" min-width="4%">
-            <template slot-scope="scope">
-              <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperationResult"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="查询" min-width="4%">
-            <template slot-scope="scope">
-              <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperation"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="查询方式" min-width="10%">
-            <template slot-scope="scope">
-              <el-select v-model="scope.row.listOperationCondition">
-                <el-option label="=" value="=" />
-                <el-option label="!=" value="!=" />
-                <el-option label=">" value=">" />
-                <el-option label=">=" value=">=" />
-                <el-option label="<" value="<>" />
-                <el-option label="<=" value="<=" />
-                <el-option label="LIKE" value="LIKE" />
-                <el-option label="BETWEEN" value="BETWEEN" />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="允许空" min-width="5%">
-            <template slot-scope="scope">
-              <el-checkbox true-label="true" false-label="false" v-model="scope.row.nullable"></el-checkbox>
-            </template>
-          </el-table-column>
-          <el-table-column label="显示类型" min-width="12%">
-            <template slot-scope="scope">
-              <el-select v-model="scope.row.htmlType">
-                <el-option label="文本框" value="input" />
-                <el-option label="文本域" value="textarea" />
-                <el-option label="下拉框" value="select" />
-                <el-option label="单选框" value="radio" />
-                <el-option label="复选框" value="checkbox" />
-                <el-option label="日期控件" value="datetime" />
-                <el-option label="图片上传" value="imageUpload" />
-                <el-option label="文件上传" value="fileUpload" />
-                <el-option label="富文本控件" value="editor" />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="字典类型" min-width="12%">
-            <template slot-scope="scope">
-              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
-                <el-option
-                    v-for="dict in dictOptions"
-                    :key="dict.id"
-                    :label="dict.name"
-                    :value="dict.type"
-                />
-              </el-select>
-            </template>
-          </el-table-column>
-          <el-table-column label="示例" min-width="10%">
-            <template slot-scope="scope">
-              <el-input v-model="scope.row.example"></el-input>
-            </template>
-          </el-table-column>
-        </el-table>
-      </el-tab-pane>
-      <el-tab-pane label="生成信息" name="genInfo">
-        <gen-info-form ref="genInfo" :info="table" :tables="tables" :menus="menus"/>
-      </el-tab-pane>
-    </el-tabs>
-    <el-form label-width="100px">
-      <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;">
-        <el-button type="primary" @click="submitForm()">提交</el-button>
-        <el-button @click="close()">返回</el-button>
-      </el-form-item>
-    </el-form>
-  </el-card>
-</template>
-<script>
-import { getCodegenDetail, updateCodegen } from "@/api/tool/codegen";
-import { listAllSimple as listAllSimpleDictType } from "@/api/system/dict/type";
-import { listMenu as getMenuTreeselect } from "@/api/system/menu";
-import { listSimpleMenus } from "@/api/system/menu";
-import basicInfoForm from "./basicInfoForm";
-import genInfoForm from "./genInfoForm";
-import Sortable from 'sortablejs'
-
-export default {
-  name: "GenEdit",
-  components: {
-    basicInfoForm,
-    genInfoForm
-  },
-  data() {
-    return {
-      // 选中选项卡的 name
-      activeName: "cloum",
-      // 表格的高度
-      tableHeight: document.documentElement.scrollHeight - 245 + "px",
-      // 表信息
-      tables: [],
-      // 表列信息
-      columns: [],
-      // 字典信息
-      dictOptions: [],
-      // 菜单信息
-      menus: [],
-      // 表详细信息
-      table: {}
-    };
-  },
-  created() {
-    const tableId = this.$route.params && this.$route.params.tableId;
-    if (tableId) {
-      // 获取表详细信息
-      getCodegenDetail(tableId).then(res => {
-        this.table = res.data.table;
-        this.columns = res.data.columns;
-      });
-      /** 查询字典下拉列表 */
-      listAllSimpleDictType().then(response => {
-        this.dictOptions = response.data;
-      });
-      /** 查询菜单下拉列表 */
-      listSimpleMenus().then(response => {
-        this.menus = [];
-        this.menus.push(...this.handleTree(response.data, "id"));
-      });
-    }
-  },
-  methods: {
-    /** 提交按钮 */
-    submitForm() {
-      const basicForm = this.$refs.basicInfo.$refs.basicInfoForm;
-      const genForm = this.$refs.genInfo.$refs.genInfoForm;
-      Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => {
-        const validateResult = res.every(item => !!item);
-        if (validateResult) {
-          const genTable = {};
-          genTable.table = Object.assign({}, basicForm.model, genForm.model);
-          genTable.columns = this.columns;
-          genTable.params = {
-            treeCode: genTable.treeCode,
-            treeName: genTable.treeName,
-            treeParentCode: genTable.treeParentCode,
-            parentMenuId: genTable.parentMenuId
-          };
-          updateCodegen(genTable).then(res => {
-            this.msgSuccess("修改成功!");
-            this.close();
-          });
-        } else {
-          this.msgError("表单校验未通过,请重新检查提交内容");
-        }
-      });
-    },
-    getFormPromise(form) {
-      return new Promise(resolve => {
-        form.validate(res => {
-          resolve(res);
-        });
-      });
-    },
-    /** 关闭按钮 */
-    close() {
-      this.$store.dispatch("tagsView/delView", this.$route);
-      this.$router.push({ path: "/tool/gen", query: { t: Date.now()}})
-    }
-  },
-  mounted() {
-    const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0];
-    const sortable = Sortable.create(el, {
-      handle: ".allowDrag",
-      onEnd: evt => {
-        const targetRow = this.columns.splice(evt.oldIndex, 1)[0];
-        this.columns.splice(evt.newIndex, 0, targetRow);
-        for (let index in this.columns) {
-          this.columns[index].sort = parseInt(index) + 1;
-        }
-      }
-    });
-  }
-};
-</script>
+<template>
+  <el-card>
+    <el-tabs v-model="activeName">
+      <el-tab-pane label="基本信息" name="basic">
+        <basic-info-form ref="basicInfo" :info="table" />
+      </el-tab-pane>
+      <el-tab-pane label="字段信息" name="cloum">
+        <el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
+          <el-table-column
+            label="字段列名"
+            prop="columnName"
+            min-width="10%"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="字段描述" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.columnComment"></el-input>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="物理类型"
+            prop="columnType"
+            min-width="10%"
+            :show-overflow-tooltip="true"
+          />
+          <el-table-column label="Java类型" min-width="11%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.javaType">
+                <el-option label="Long" value="Long" />
+                <el-option label="String" value="String" />
+                <el-option label="Integer" value="Integer" />
+                <el-option label="Double" value="Double" />
+                <el-option label="BigDecimal" value="BigDecimal" />
+                <el-option label="Date" value="Date" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="java属性" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.javaField"></el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="插入" min-width="4%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="true" false-label="false" v-model="scope.row.createOperation"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="编辑" min-width="4%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="true" false-label="false" v-model="scope.row.updateOperation"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="列表" min-width="4%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperationResult"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="查询" min-width="4%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperation"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="查询方式" min-width="10%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.listOperationCondition">
+                <el-option label="=" value="=" />
+                <el-option label="!=" value="!=" />
+                <el-option label=">" value=">" />
+                <el-option label=">=" value=">=" />
+                <el-option label="<" value="<>" />
+                <el-option label="<=" value="<=" />
+                <el-option label="LIKE" value="LIKE" />
+                <el-option label="BETWEEN" value="BETWEEN" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="允许空" min-width="5%">
+            <template slot-scope="scope">
+              <el-checkbox true-label="true" false-label="false" v-model="scope.row.nullable"></el-checkbox>
+            </template>
+          </el-table-column>
+          <el-table-column label="显示类型" min-width="12%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.htmlType">
+                <el-option label="文本框" value="input" />
+                <el-option label="文本域" value="textarea" />
+                <el-option label="下拉框" value="select" />
+                <el-option label="单选框" value="radio" />
+                <el-option label="复选框" value="checkbox" />
+                <el-option label="日期控件" value="datetime" />
+                <el-option label="图片上传" value="imageUpload" />
+                <el-option label="文件上传" value="fileUpload" />
+                <el-option label="富文本控件" value="editor" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="字典类型" min-width="12%">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
+                <el-option
+                    v-for="dict in dictOptions"
+                    :key="dict.id"
+                    :label="dict.name"
+                    :value="dict.type"
+                />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="示例" min-width="10%">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.example"></el-input>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-tab-pane>
+      <el-tab-pane label="生成信息" name="genInfo">
+        <gen-info-form ref="genInfo" :info="table" :tables="tables" :menus="menus"/>
+      </el-tab-pane>
+    </el-tabs>
+    <el-form label-width="100px">
+      <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;">
+        <el-button type="primary" @click="submitForm()">提交</el-button>
+        <el-button @click="close()">返回</el-button>
+      </el-form-item>
+    </el-form>
+  </el-card>
+</template>
+<script>
+import { getCodegenDetail, updateCodegen } from "@/api/tool/codegen";
+import { listAllSimple as listAllSimpleDictType } from "@/api/system/dict/type";
+import { listSimpleMenus } from "@/api/system/menu";
+import basicInfoForm from "./basicInfoForm";
+import genInfoForm from "./genInfoForm";
+import Sortable from 'sortablejs'
+
+export default {
+  name: "GenEdit",
+  components: {
+    basicInfoForm,
+    genInfoForm
+  },
+  data() {
+    return {
+      // 选中选项卡的 name
+      activeName: "cloum",
+      // 表格的高度
+      tableHeight: document.documentElement.scrollHeight - 245 + "px",
+      // 表信息
+      tables: [],
+      // 表列信息
+      columns: [],
+      // 字典信息
+      dictOptions: [],
+      // 菜单信息
+      menus: [],
+      // 表详细信息
+      table: {}
+    };
+  },
+  created() {
+    const tableId = this.$route.params && this.$route.params.tableId;
+    if (tableId) {
+      // 获取表详细信息
+      getCodegenDetail(tableId).then(res => {
+        this.table = res.data.table;
+        this.columns = res.data.columns;
+      });
+      /** 查询字典下拉列表 */
+      listAllSimpleDictType().then(response => {
+        this.dictOptions = response.data;
+      });
+      /** 查询菜单下拉列表 */
+      listSimpleMenus().then(response => {
+        this.menus = [];
+        this.menus.push(...this.handleTree(response.data, "id"));
+      });
+    }
+  },
+  methods: {
+    /** 提交按钮 */
+    submitForm() {
+      const basicForm = this.$refs.basicInfo.$refs.basicInfoForm;
+      const genForm = this.$refs.genInfo.$refs.genInfoForm;
+      Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => {
+        const validateResult = res.every(item => !!item);
+        if (validateResult) {
+          const genTable = {};
+          genTable.table = Object.assign({}, basicForm.model, genForm.model);
+          genTable.columns = this.columns;
+          genTable.params = {
+            treeCode: genTable.treeCode,
+            treeName: genTable.treeName,
+            treeParentCode: genTable.treeParentCode,
+            parentMenuId: genTable.parentMenuId
+          };
+          updateCodegen(genTable).then(res => {
+            this.msgSuccess("修改成功!");
+            this.close();
+          });
+        } else {
+          this.msgError("表单校验未通过,请重新检查提交内容");
+        }
+      });
+    },
+    getFormPromise(form) {
+      return new Promise(resolve => {
+        form.validate(res => {
+          resolve(res);
+        });
+      });
+    },
+    /** 关闭按钮 */
+    close() {
+      this.$store.dispatch("tagsView/delView", this.$route);
+      this.$router.push({ path: "/tool/gen", query: { t: Date.now()}})
+    }
+  },
+  mounted() {
+    const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0];
+    const sortable = Sortable.create(el, {
+      handle: ".allowDrag",
+      onEnd: evt => {
+        const targetRow = this.columns.splice(evt.oldIndex, 1)[0];
+        this.columns.splice(evt.newIndex, 0, targetRow);
+        for (let index in this.columns) {
+          this.columns[index].sort = parseInt(index) + 1;
+        }
+      }
+    });
+  }
+};
+</script>

+ 319 - 319
ruoyi-ui/src/views/tool/gen/genInfoForm.vue → ruoyi-ui/src/views/tool/codegen/genInfoForm.vue

@@ -1,319 +1,319 @@
-<template>
-  <el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
-    <el-row>
-      <el-col :span="12">
-        <el-form-item prop="tplCategory">
-          <span slot="label">生成模板</span>
-          <el-select v-model="info.templateType" @change="tplSelectChange">
-            <el-option
-                v-for="dict in this.getDictDatas(DICT_TYPE.TOOL_CODEGEN_TEMPLATE_TYPE)"
-                :key="parseInt(dict.value)"
-                :label="dict.label"
-                :value="parseInt(dict.value)"
-            />
-          </el-select>
-        </el-form-item>
-      </el-col>
-
-<!--      <el-col :span="12">-->
-<!--        <el-form-item prop="packageName">-->
-<!--          <span slot="label">-->
-<!--            生成包路径-->
-<!--            <el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">-->
-<!--              <i class="el-icon-question"></i>-->
-<!--            </el-tooltip>-->
-<!--          </span>-->
-<!--          <el-input v-model="info.packageName" />-->
-<!--        </el-form-item>-->
-<!--      </el-col>-->
-
-      <el-col :span="12">
-        <el-form-item prop="moduleName">
-          <span slot="label">
-            模块名
-            <el-tooltip content="模块名,即一级目录,例如 system、infra、tool 等等" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-input v-model="info.moduleName" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="businessName">
-          <span slot="label">
-            业务名
-            <el-tooltip content="业务名,即二级目录,例如 user、permission、dict 等等" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-input v-model="info.businessName" />
-        </el-form-item>
-      </el-col>
-
-<!--      <el-col :span="12">-->
-<!--        <el-form-item prop="businessPackage">-->
-<!--          <span slot="label">-->
-<!--            业务包-->
-<!--            <el-tooltip content="业务包,自定义二级目录。例如说,我们希望将 dictType 和 dictData 归类成 dict 业务" placement="top">-->
-<!--              <i class="el-icon-question"></i>-->
-<!--            </el-tooltip>-->
-<!--          </span>-->
-<!--          <el-input v-model="info.businessPackage" />-->
-<!--        </el-form-item>-->
-<!--      </el-col>-->
-
-      <el-col :span="12">
-        <el-form-item prop="className">
-          <span slot="label">
-            类名称
-            <el-tooltip content="类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-input v-model="info.className" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item prop="classComment">
-          <span slot="label">
-            类描述
-            <el-tooltip content="用作类描述,例如 用户" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-input v-model="info.classComment" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="12">
-        <el-form-item>
-          <span slot="label">
-            上级菜单
-            <el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <treeselect :append-to-body="true" v-model="info.parentMenuId" :options="menus"
-            :normalizer="normalizer" :show-count="true" placeholder="请选择系统菜单" />
-        </el-form-item>
-      </el-col>
-
-      <el-col :span="24" v-if="info.genType == '1'">
-        <el-form-item prop="genPath">
-          <span slot="label">
-            自定义路径
-            <el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-input v-model="info.genPath">
-            <el-dropdown slot="append">
-              <el-button type="primary">
-                最近路径快速选择
-                <i class="el-icon-arrow-down el-icon--right"></i>
-              </el-button>
-              <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item @click.native="info.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item>
-              </el-dropdown-menu>
-            </el-dropdown>
-          </el-input>
-        </el-form-item>
-      </el-col>
-    </el-row>
-
-    <el-row v-show="info.tplCategory == 'tree'">
-      <h4 class="form-header">其他信息</h4>
-      <el-col :span="12">
-        <el-form-item>
-          <span slot="label">
-            树编码字段
-            <el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-select v-model="info.treeCode" placeholder="请选择">
-            <el-option
-              v-for="(column, index) in info.columns"
-              :key="index"
-              :label="column.columnName + ':' + column.columnComment"
-              :value="column.columnName"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item>
-          <span slot="label">
-            树父编码字段
-            <el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-select v-model="info.treeParentCode" placeholder="请选择">
-            <el-option
-              v-for="(column, index) in info.columns"
-              :key="index"
-              :label="column.columnName + ':' + column.columnComment"
-              :value="column.columnName"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item>
-          <span slot="label">
-            树名称字段
-            <el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-select v-model="info.treeName" placeholder="请选择">
-            <el-option
-              v-for="(column, index) in info.columns"
-              :key="index"
-              :label="column.columnName + ':' + column.columnComment"
-              :value="column.columnName"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-    </el-row>
-    <el-row v-show="info.tplCategory == 'sub'">
-      <h4 class="form-header">关联信息</h4>
-      <el-col :span="12">
-        <el-form-item>
-          <span slot="label">
-            关联子表的表名
-            <el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange">
-            <el-option
-              v-for="(table, index) in tables"
-              :key="index"
-              :label="table.tableName + ':' + table.tableComment"
-              :value="table.tableName"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-      <el-col :span="12">
-        <el-form-item>
-          <span slot="label">
-            子表关联的外键名
-            <el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
-              <i class="el-icon-question"></i>
-            </el-tooltip>
-          </span>
-          <el-select v-model="info.subTableFkName" placeholder="请选择">
-            <el-option
-              v-for="(column, index) in subColumns"
-              :key="index"
-              :label="column.columnName + ':' + column.columnComment"
-              :value="column.columnName"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-      </el-col>
-    </el-row>
-  </el-form>
-</template>
-<script>
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-
-export default {
-  name: "BasicInfoForm",
-  components: { Treeselect },
-  props: {
-    info: {
-      type: Object,
-      default: null
-    },
-    tables: {
-      type: Array,
-      default: null
-    },
-    menus: {
-      type: Array,
-      default: []
-    },
-  },
-  data() {
-    return {
-      subColumns: [],
-      rules: {
-        templateType: [
-          { required: true, message: "请选择生成模板", trigger: "blur" }
-        ],
-        // packageName: [
-        //   { required: true, message: "请输入生成包路径", trigger: "blur" }
-        // ],
-        moduleName: [
-          { required: true, message: "请输入生成模块名", trigger: "blur" }
-        ],
-        businessName: [
-          { required: true, message: "请输入生成业务名", trigger: "blur" }
-        ],
-        businessPackage: [
-          { required: true, message: "请输入生成业务包", trigger: "blur" }
-        ],
-        className: [
-          { required: true, message: "请输入生成类名称", trigger: "blur" }
-        ],
-        classComment: [
-          { required: true, message: "请输入生成类描述", trigger: "blur" }
-        ],
-      }
-    };
-  },
-  created() {},
-  watch: {
-    'info.subTableName': function(val) {
-      this.setSubTableColumns(val);
-    }
-  },
-  methods: {
-    /** 转换菜单数据结构 */
-    normalizer(node) {
-      if (node.children && !node.children.length) {
-        delete node.children;
-      }
-      return {
-        id: node.id,
-        label: node.name,
-        children: node.children
-      };
-    },
-    /** 选择子表名触发 */
-    subSelectChange(value) {
-      this.info.subTableFkName = '';
-    },
-    /** 选择生成模板触发 */
-    tplSelectChange(value) {
-      if (value !== 1) {
-        // TODO 芋艿:暂时不考虑支持树形结构
-        this.msgError('暂时不考虑支持【树形】和【主子表】的代码生成。原因是:导致 vm 模板过于复杂,不利于胖友二次开发');
-        return false;
-      }
-      if(value !== 'sub') {
-        this.info.subTableName = '';
-        this.info.subTableFkName = '';
-      }
-    },
-    /** 设置关联外键 */
-    setSubTableColumns(value) {
-      for (var item in this.tables) {
-        const name = this.tables[item].tableName;
-        if (value === name) {
-          this.subColumns = this.tables[item].columns;
-          break;
-        }
-      }
-    }
-  }
-};
-</script>
+<template>
+  <el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
+    <el-row>
+      <el-col :span="12">
+        <el-form-item prop="tplCategory">
+          <span slot="label">生成模板</span>
+          <el-select v-model="info.templateType" @change="tplSelectChange">
+            <el-option
+                v-for="dict in this.getDictDatas(DICT_TYPE.TOOL_CODEGEN_TEMPLATE_TYPE)"
+                :key="parseInt(dict.value)"
+                :label="dict.label"
+                :value="parseInt(dict.value)"
+            />
+          </el-select>
+        </el-form-item>
+      </el-col>
+
+<!--      <el-col :span="12">-->
+<!--        <el-form-item prop="packageName">-->
+<!--          <span slot="label">-->
+<!--            生成包路径-->
+<!--            <el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">-->
+<!--              <i class="el-icon-question"></i>-->
+<!--            </el-tooltip>-->
+<!--          </span>-->
+<!--          <el-input v-model="info.packageName" />-->
+<!--        </el-form-item>-->
+<!--      </el-col>-->
+
+      <el-col :span="12">
+        <el-form-item prop="moduleName">
+          <span slot="label">
+            模块名
+            <el-tooltip content="模块名,即一级目录,例如 system、infra、tool 等等" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.moduleName" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="businessName">
+          <span slot="label">
+            业务名
+            <el-tooltip content="业务名,即二级目录,例如 user、permission、dict 等等" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.businessName" />
+        </el-form-item>
+      </el-col>
+
+<!--      <el-col :span="12">-->
+<!--        <el-form-item prop="businessPackage">-->
+<!--          <span slot="label">-->
+<!--            业务包-->
+<!--            <el-tooltip content="业务包,自定义二级目录。例如说,我们希望将 dictType 和 dictData 归类成 dict 业务" placement="top">-->
+<!--              <i class="el-icon-question"></i>-->
+<!--            </el-tooltip>-->
+<!--          </span>-->
+<!--          <el-input v-model="info.businessPackage" />-->
+<!--        </el-form-item>-->
+<!--      </el-col>-->
+
+      <el-col :span="12">
+        <el-form-item prop="className">
+          <span slot="label">
+            类名称
+            <el-tooltip content="类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.className" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item prop="classComment">
+          <span slot="label">
+            类描述
+            <el-tooltip content="用作类描述,例如 用户" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.classComment" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            上级菜单
+            <el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <treeselect :append-to-body="true" v-model="info.parentMenuId" :options="menus"
+            :normalizer="normalizer" :show-count="true" placeholder="请选择系统菜单" />
+        </el-form-item>
+      </el-col>
+
+      <el-col :span="24" v-if="info.genType == '1'">
+        <el-form-item prop="genPath">
+          <span slot="label">
+            自定义路径
+            <el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-input v-model="info.genPath">
+            <el-dropdown slot="append">
+              <el-button type="primary">
+                最近路径快速选择
+                <i class="el-icon-arrow-down el-icon--right"></i>
+              </el-button>
+              <el-dropdown-menu slot="dropdown">
+                <el-dropdown-item @click.native="info.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item>
+              </el-dropdown-menu>
+            </el-dropdown>
+          </el-input>
+        </el-form-item>
+      </el-col>
+    </el-row>
+
+    <el-row v-show="info.tplCategory == 'tree'">
+      <h4 class="form-header">其他信息</h4>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            树编码字段
+            <el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeCode" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            树父编码字段
+            <el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeParentCode" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            树名称字段
+            <el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.treeName" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in info.columns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+    <el-row v-show="info.tplCategory == 'sub'">
+      <h4 class="form-header">关联信息</h4>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            关联子表的表名
+            <el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange">
+            <el-option
+              v-for="(table, index) in tables"
+              :key="index"
+              :label="table.tableName + ':' + table.tableComment"
+              :value="table.tableName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item>
+          <span slot="label">
+            子表关联的外键名
+            <el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
+              <i class="el-icon-question"></i>
+            </el-tooltip>
+          </span>
+          <el-select v-model="info.subTableFkName" placeholder="请选择">
+            <el-option
+              v-for="(column, index) in subColumns"
+              :key="index"
+              :label="column.columnName + ':' + column.columnComment"
+              :value="column.columnName"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+    </el-row>
+  </el-form>
+</template>
+<script>
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "BasicInfoForm",
+  components: { Treeselect },
+  props: {
+    info: {
+      type: Object,
+      default: null
+    },
+    tables: {
+      type: Array,
+      default: null
+    },
+    menus: {
+      type: Array,
+      default: []
+    },
+  },
+  data() {
+    return {
+      subColumns: [],
+      rules: {
+        templateType: [
+          { required: true, message: "请选择生成模板", trigger: "blur" }
+        ],
+        // packageName: [
+        //   { required: true, message: "请输入生成包路径", trigger: "blur" }
+        // ],
+        moduleName: [
+          { required: true, message: "请输入生成模块名", trigger: "blur" }
+        ],
+        businessName: [
+          { required: true, message: "请输入生成业务名", trigger: "blur" }
+        ],
+        businessPackage: [
+          { required: true, message: "请输入生成业务包", trigger: "blur" }
+        ],
+        className: [
+          { required: true, message: "请输入生成类名称", trigger: "blur" }
+        ],
+        classComment: [
+          { required: true, message: "请输入生成类描述", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {},
+  watch: {
+    'info.subTableName': function(val) {
+      this.setSubTableColumns(val);
+    }
+  },
+  methods: {
+    /** 转换菜单数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.id,
+        label: node.name,
+        children: node.children
+      };
+    },
+    /** 选择子表名触发 */
+    subSelectChange(value) {
+      this.info.subTableFkName = '';
+    },
+    /** 选择生成模板触发 */
+    tplSelectChange(value) {
+      if (value !== 1) {
+        // TODO 芋艿:暂时不考虑支持树形结构
+        this.msgError('暂时不考虑支持【树形】和【主子表】的代码生成。原因是:导致 vm 模板过于复杂,不利于胖友二次开发');
+        return false;
+      }
+      if(value !== 'sub') {
+        this.info.subTableName = '';
+        this.info.subTableFkName = '';
+      }
+    },
+    /** 设置关联外键 */
+    setSubTableColumns(value) {
+      for (var item in this.tables) {
+        const name = this.tables[item].tableName;
+        if (value === name) {
+          this.subColumns = this.tables[item].columns;
+          break;
+        }
+      }
+    }
+  }
+};
+</script>

+ 106 - 106
ruoyi-ui/src/views/tool/gen/importTable.vue → ruoyi-ui/src/views/tool/codegen/importTable.vue

@@ -1,106 +1,106 @@
-<template>
-  <!-- 导入表 -->
-  <el-dialog title="导入表" :visible.sync="visible" width="800px" top="5vh" append-to-body>
-    <el-form :model="queryParams" ref="queryForm" :inline="true">
-      <el-form-item label="表名称" prop="tableName">
-        <el-input
-          v-model="queryParams.tableName"
-          placeholder="请输入表名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="表描述" prop="tableComment">
-        <el-input
-          v-model="queryParams.tableComment"
-          placeholder="请输入表描述"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
-    <el-row>
-      <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
-        <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column prop="tableSchema" label="数据库" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
-        <el-table-column prop="createTime" label="创建时间">
-          <template slot-scope="scope">
-            <span>{{ parseTime(scope.row.createTime) }}</span>
-          </template>
-        </el-table-column>
-      </el-table>
-    </el-row>
-    <div slot="footer" class="dialog-footer">
-      <el-button type="primary" @click="handleImportTable">确 定</el-button>
-      <el-button @click="visible = false">取 消</el-button>
-    </div>
-  </el-dialog>
-</template>
-
-<script>
-import { getSchemaTableList, createCodegenList } from "@/api/tool/codegen";
-export default {
-  data() {
-    return {
-      // 遮罩层
-      visible: false,
-      // 选中数组值
-      tables: [],
-      // 总条数
-      total: 0,
-      // 表数据
-      dbTableList: [],
-      // 查询参数
-      queryParams: {
-        tableName: undefined,
-        tableComment: undefined
-      }
-    };
-  },
-  methods: {
-    // 显示弹框
-    show() {
-      this.getList();
-      this.visible = true;
-    },
-    clickRow(row) {
-      this.$refs.table.toggleRowSelection(row);
-    },
-    // 多选框选中数据
-    handleSelectionChange(selection) {
-      this.tables = selection.map(item => item.tableName);
-    },
-    // 查询表数据
-    getList() {
-      getSchemaTableList(this.queryParams).then(res => {
-        this.dbTableList = res.data;
-      });
-    },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.getList();
-    },
-    /** 重置按钮操作 */
-    resetQuery() {
-      this.resetForm("queryForm");
-      this.handleQuery();
-    },
-    /** 导入按钮操作 */
-    handleImportTable() {
-      createCodegenList(this.tables.join(",")).then(res => {
-        this.msgSuccess("导入成功");
-        this.visible = false;
-        this.$emit("ok");
-      });
-    }
-  }
-};
-</script>
+<template>
+  <!-- 导入表 -->
+  <el-dialog title="导入表" :visible.sync="visible" width="800px" top="5vh" append-to-body>
+    <el-form :model="queryParams" ref="queryForm" :inline="true">
+      <el-form-item label="表名称" prop="tableName">
+        <el-input
+          v-model="queryParams.tableName"
+          placeholder="请输入表名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="表描述" prop="tableComment">
+        <el-input
+          v-model="queryParams.tableComment"
+          placeholder="请输入表描述"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row>
+      <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
+        <el-table-column type="selection" width="55"></el-table-column>
+        <el-table-column prop="tableSchema" label="数据库" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
+        <el-table-column prop="createTime" label="创建时间">
+          <template slot-scope="scope">
+            <span>{{ parseTime(scope.row.createTime) }}</span>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-row>
+    <div slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="handleImportTable">确 定</el-button>
+      <el-button @click="visible = false">取 消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { getSchemaTableList, createCodegenListFromDB } from "@/api/tool/codegen";
+export default {
+  data() {
+    return {
+      // 遮罩层
+      visible: false,
+      // 选中数组值
+      tables: [],
+      // 总条数
+      total: 0,
+      // 表数据
+      dbTableList: [],
+      // 查询参数
+      queryParams: {
+        tableName: undefined,
+        tableComment: undefined
+      }
+    };
+  },
+  methods: {
+    // 显示弹框
+    show() {
+      this.getList();
+      this.visible = true;
+    },
+    clickRow(row) {
+      this.$refs.table.toggleRowSelection(row);
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.tables = selection.map(item => item.tableName);
+    },
+    // 查询表数据
+    getList() {
+      getSchemaTableList(this.queryParams).then(res => {
+        this.dbTableList = res.data;
+      });
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 导入按钮操作 */
+    handleImportTable() {
+      createCodegenListFromDB(this.tables.join(",")).then(res => {
+        this.msgSuccess("导入成功");
+        this.visible = false;
+        this.$emit("ok");
+      });
+    }
+  }
+};
+</script>

+ 316 - 228
ruoyi-ui/src/views/tool/gen/index.vue → ruoyi-ui/src/views/tool/codegen/index.vue

@@ -1,228 +1,316 @@
-<template>
-  <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="表名称" prop="tableName">
-        <el-input
-          v-model="queryParams.tableName"
-          placeholder="请输入表名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="表描述" prop="tableComment">
-        <el-input
-          v-model="queryParams.tableComment"
-          placeholder="请输入表描述"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="创建时间">
-        <el-date-picker
-          v-model="dateRange"
-          size="small"
-          style="width: 240px"
-          value-format="yyyy-MM-dd"
-          type="daterange"
-          range-separator="-"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-        ></el-date-picker>
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
-        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
-      </el-form-item>
-    </el-form>
-
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button type="info" plain icon="el-icon-upload" size="mini" @click="openImportTable" v-hasPermi="['tool:gen:import']">导入</el-button>
-      </el-col>
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row>
-
-    <el-table v-loading="loading" :data="tableList">
-      <el-table-column label="表名称" align="center" prop="tableName" :show-overflow-tooltip="true" width="200"/>
-      <el-table-column label="表描述" align="center" prop="tableComment" :show-overflow-tooltip="true" width="120"/>
-      <el-table-column label="实体" align="center" prop="className" :show-overflow-tooltip="true" width="200"/>
-      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
-        <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.createTime) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
-        <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.updateTime) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-        <template slot-scope="scope">
-          <el-button type="text" size="small" icon="el-icon-view" @click="handlePreview(scope.row)" v-hasPermi="['tool:gen:preview']">预览</el-button>
-          <el-button type="text" size="small" icon="el-icon-edit" @click="handleEditTable(scope.row)" v-hasPermi="['tool:gen:edit']">编辑</el-button>
-          <el-button type="text" size="small" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['tool:gen:remove']">删除</el-button>
-          <el-button type="text" size="small" icon="el-icon-refresh" @click="handleSynchDb(scope.row)" v-hasPermi="['tool:gen:edit']">同步</el-button>
-          <el-button type="text" size="small" icon="el-icon-download" @click="handleGenTable(scope.row)" v-hasPermi="['tool:gen:code']">生成代码</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/>
-    <!-- 预览界面 -->
-    <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body>
-      <el-tabs tab-position="left" v-model="preview.activeName">
-        <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" :name="item.filePath" :key="item.filePath">
-          <pre><code class="hljs" v-html="highlightedCode(item)"></code></pre>
-        </el-tab-pane>
-      </el-tabs>
-    </el-dialog>
-    <import-table ref="import" @ok="handleQuery" />
-  </div>
-</template>
-
-<script>
-import { getCodegenTablePage, previewCodegen, downloadCodegen, deleteCodegen, syncCodegen } from "@/api/tool/codegen";
-
-import importTable from "./importTable";
-// 代码高亮插件
-import hljs from "highlight.js/lib/highlight";
-import "highlight.js/styles/github-gist.css";
-hljs.registerLanguage("java", require("highlight.js/lib/languages/java"));
-hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
-hljs.registerLanguage("html", require("highlight.js/lib/languages/xml"));
-hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml"));
-hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript"));
-hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql"));
-
-export default {
-  name: "Gen",
-  components: { importTable },
-  data() {
-    return {
-      // 遮罩层
-      loading: true,
-      // 唯一标识符
-      uniqueId: "",
-      // 选中表数组
-      tableNames: [],
-      // 显示搜索条件
-      showSearch: true,
-      // 总条数
-      total: 0,
-      // 表数据
-      tableList: [],
-      // 日期范围
-      dateRange: "",
-      // 查询参数
-      queryParams: {
-        pageNo: 1,
-        pageSize: 10,
-        tableName: undefined,
-        tableComment: undefined
-      },
-      // 预览参数
-      preview: {
-        open: false,
-        title: "代码预览",
-        data: {},
-        activeName: "domain.java"
-      }
-    };
-  },
-  created() {
-    this.getList();
-  },
-  activated() {
-    const time = this.$route.query.t;
-    if (time != null && time !== this.uniqueId) {
-      this.uniqueId = time;
-      this.resetQuery();
-    }
-  },
-  methods: {
-    /** 查询表集合 */
-    getList() {
-      this.loading = true;
-      getCodegenTablePage(this.addDateRange(this.queryParams, [
-        this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
-        this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
-      ], 'CreateTime')).then(response => {
-            this.tableList = response.data.list;
-            this.total = response.data.total;
-            this.loading = false;
-          }
-      );
-    },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.queryParams.pageNo = 1;
-      this.getList();
-    },
-    /** 生成代码操作 */
-    handleGenTable(row) {
-      downloadCodegen(row.id).then(response => {
-        this.downloadZip(response, 'codegen-' + row.tableName + '.zip');
-      })
-    },
-    /** 同步数据库操作 */
-    handleSynchDb(row) {
-      const tableName = row.tableName;
-      this.$confirm('确认要强制同步"' + tableName + '"表结构吗?', "警告", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }).then(function() {
-          return syncCodegen(row.id);
-      }).then(() => {
-          this.msgSuccess("同步成功");
-      })
-    },
-    /** 打开导入表弹窗 */
-    openImportTable() {
-      this.$refs.import.show();
-    },
-    /** 重置按钮操作 */
-    resetQuery() {
-      this.dateRange = [];
-      this.resetForm("queryForm");
-      this.handleQuery();
-    },
-    /** 预览按钮 */
-    handlePreview(row) {
-      previewCodegen(row.id).then(response => {
-        this.preview.data = response.data;
-        this.preview.activeName = response.data[0].filePath;
-        this.preview.open = true;
-      });
-    },
-    /** 高亮显示 */
-    highlightedCode(item) {
-      // const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm"));
-      // var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length);
-      var language = item.filePath.substring(item.filePath.lastIndexOf(".") + 1);
-      const result = hljs.highlight(language, item.code || "", true);
-      return result.value || '&nbsp;';
-    },
-    /** 修改按钮操作 */
-    handleEditTable(row) {
-      const tableId = row.id;
-      this.$router.push("/gen/edit/" + tableId);
-    },
-    /** 删除按钮操作 */
-    handleDelete(row) {
-      const tableIds = row.id;
-      this.$confirm('是否确认删除表名称为"' + row.tableName + '"的数据项?', "警告", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning"
-      }).then(function() {
-          return deleteCodegen(tableIds);
-      }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-      })
-    }
-  }
-};
-</script>
+<template>
+  <div class="app-container">
+    <!-- 操作工作栏 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="表名称" prop="tableName">
+        <el-input
+          v-model="queryParams.tableName"
+          placeholder="请输入表名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="表描述" prop="tableComment">
+        <el-input
+          v-model="queryParams.tableComment"
+          placeholder="请输入表描述"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker
+          v-model="dateRange"
+          size="small"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        ></el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 操作工作栏 -->
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="info" plain icon="el-icon-upload" size="mini" @click="openImportTable"
+                   v-hasPermi="['tool:codegen:create']">基于 DB 导入</el-button>
+        <el-button type="info" plain icon="el-icon-upload" size="mini" @click="openImportSQL"
+                   v-hasPermi="['tool:codegen:create']">基于 SQL 导入</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <!-- 列表 -->
+    <el-table v-loading="loading" :data="tableList">
+      <el-table-column label="表名称" align="center" prop="tableName" :show-overflow-tooltip="true" width="200"/>
+      <el-table-column label="表描述" align="center" prop="tableComment" :show-overflow-tooltip="true" width="120"/>
+      <el-table-column label="实体" align="center" prop="className" :show-overflow-tooltip="true" width="200"/>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.updateTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" icon="el-icon-view" @click="handlePreview(scope.row)" v-hasPermi="['tool:codegen:preview']">预览</el-button>
+          <el-button type="text" size="small" icon="el-icon-edit" @click="handleEditTable(scope.row)" v-hasPermi="['tool:codegen:update']">编辑</el-button>
+          <el-button type="text" size="small" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['tool:codegen:delete']">删除</el-button>
+          <el-button type="text" size="small" icon="el-icon-refresh" @click="handleSynchDb(scope.row)" v-hasPermi="['tool:codegen:update']">同步</el-button>
+          <el-button type="text" size="small" icon="el-icon-download" @click="handleGenTable(scope.row)" v-hasPermi="['tool:codegen:download']">生成代码</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/>
+
+    <!-- 预览界面 -->
+    <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body>
+      <el-tabs tab-position="left" v-model="preview.activeName">
+        <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)" :name="item.filePath" :key="item.filePath">
+          <pre><code class="hljs" v-html="highlightedCode(item)"></code></pre>
+        </el-tab-pane>
+      </el-tabs>
+    </el-dialog>
+
+    <!-- 基于 DB 导入 -->
+    <import-table ref="import" @ok="handleQuery" />
+
+    <!-- 基于 SQL 导入 -->
+    <el-dialog :title="importSQL.title" :visible.sync="importSQL.open" width="800px" append-to-body>
+      <el-form ref="importSQLForm" :model="importSQL.form" :rules="importSQL.rules" label-width="120px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="建表 SQL 语句" prop="sql">
+              <el-input v-model="importSQL.form.sql" type="textarea" rows="30" style="width: 650px;" placeholder="请输入建 SQL 语句" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitImportSQLForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getCodegenTablePage, previewCodegen, downloadCodegen, deleteCodegen,
+  syncCodegenFromDB, syncCodegenFromSQL, createCodegenListFromSQL } from "@/api/tool/codegen";
+
+import importTable from "./importTable";
+// 代码高亮插件
+import hljs from "highlight.js/lib/highlight";
+import "highlight.js/styles/github-gist.css";
+import {SysCommonStatusEnum} from "@/utils/constants";
+import {createTestDemo, updateTestDemo} from "@/api/tool/testDemo";
+hljs.registerLanguage("java", require("highlight.js/lib/languages/java"));
+hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("html", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml"));
+hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript"));
+hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql"));
+
+export default {
+  name: "Codegen",
+  components: { importTable },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 唯一标识符
+      uniqueId: "",
+      // 选中表数组
+      tableNames: [],
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 表数据
+      tableList: [],
+      // 日期范围
+      dateRange: "",
+      // 查询参数
+      queryParams: {
+        pageNo: 1,
+        pageSize: 10,
+        tableName: undefined,
+        tableComment: undefined
+      },
+      // 预览参数
+      preview: {
+        open: false,
+        title: "代码预览",
+        data: {},
+        activeName: "domain.java"
+      },
+      // 基于 SQL 导入
+      importSQL: {
+        open: false,
+        title: "",
+        form: {
+
+        },
+        rules: {
+          sql: [{ required: true, message: "SQL 不能为空", trigger: "blur" }]
+        }
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  activated() {
+    const time = this.$route.query.t;
+    if (time != null && time !== this.uniqueId) {
+      this.uniqueId = time;
+      this.resetQuery();
+    }
+  },
+  methods: {
+    /** 查询表集合 */
+    getList() {
+      this.loading = true;
+      getCodegenTablePage(this.addDateRange(this.queryParams, [
+        this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined,
+        this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined,
+      ], 'CreateTime')).then(response => {
+            this.tableList = response.data.list;
+            this.total = response.data.total;
+            this.loading = false;
+          }
+      );
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNo = 1;
+      this.getList();
+    },
+    /** 生成代码操作 */
+    handleGenTable(row) {
+      downloadCodegen(row.id).then(response => {
+        this.downloadZip(response, 'codegen-' + row.tableName + '.zip');
+      })
+    },
+    /** 同步数据库操作 */
+    handleSynchDb(row) {
+      // 基于 SQL 同步
+      if (row.importType === 2) {
+        this.importSQL.open = true;
+        this.importSQL.form.tableId = row.id;
+        return;
+      }
+      // 基于 DB 同步
+      const tableName = row.tableName;
+      this.$confirm('确认要强制同步"' + tableName + '"表结构吗?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+          return syncCodegenFromDB(row.id);
+      }).then(() => {
+          this.msgSuccess("同步成功");
+      })
+    },
+    /** 打开导入表弹窗 */
+    openImportTable() {
+      this.$refs.import.show();
+    },
+    /** 打开 SQL 导入的弹窗 **/
+    openImportSQL() {
+      this.importSQL.open = true;
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 预览按钮 */
+    handlePreview(row) {
+      previewCodegen(row.id).then(response => {
+        this.preview.data = response.data;
+        this.preview.activeName = response.data[0].filePath;
+        this.preview.open = true;
+      });
+    },
+    /** 高亮显示 */
+    highlightedCode(item) {
+      // const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm"));
+      // var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length);
+      var language = item.filePath.substring(item.filePath.lastIndexOf(".") + 1);
+      const result = hljs.highlight(language, item.code || "", true);
+      return result.value || '&nbsp;';
+    },
+    /** 修改按钮操作 */
+    handleEditTable(row) {
+      const tableId = row.id;
+      this.$router.push("/codegen/edit/" + tableId);
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const tableIds = row.id;
+      this.$confirm('是否确认删除表名称为"' + row.tableName + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+          return deleteCodegen(tableIds);
+      }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+      })
+    },
+    // 取消按钮
+    cancel() {
+      this.importSQL.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.importSQL.form = {
+        tableId: undefined,
+        sql: undefined,
+      };
+      this.resetForm("importSQLForm");
+    },
+    // 提交 import SQL 表单
+    submitImportSQLForm() {
+      this.$refs["importSQLForm"].validate(valid => {
+        if (!valid) {
+          return;
+        }
+        // 修改的提交
+        let form = this.importSQL.form;
+        if (form.tableId != null) {
+          syncCodegenFromSQL(form.tableId, form.sql).then(response => {
+            this.msgSuccess("同步成功");
+            this.importSQL.open = false;
+            this.getList();
+          });
+          return;
+        }
+        // 添加的提交
+        createCodegenListFromSQL(form).then(response => {
+          this.msgSuccess("导入成功");
+          this.importSQL.open = false;
+          this.getList();
+        });
+      });
+    }
+  }
+};
+</script>

File diff suppressed because it is too large
+ 21 - 11
sql/ruoyi-vue-pro.sql


+ 4 - 7
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java

@@ -56,9 +56,6 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
     @Resource
     private CodegenProperties codegenProperties;
 
-    @Resource
-    private ToolCodegenServiceImpl self;
-
     private Long createCodegen0(ToolCodegenImportTypeEnum importType,
                                 ToolSchemaTableDO schemaTable, List<ToolSchemaColumnDO> schemaColumns) {
         // 校验导入的表和字段非空
@@ -99,7 +96,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
             throw exception(CODEGEN_PARSE_SQL_ERROR);
         }
         // 导入
-        return self.createCodegen0(ToolCodegenImportTypeEnum.SQL, schemaTable, schemaColumns);
+        return this.createCodegen0(ToolCodegenImportTypeEnum.SQL, schemaTable, schemaColumns);
     }
 
     @Override
@@ -108,7 +105,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
         ToolSchemaTableDO schemaTable = schemaTableMapper.selectByTableName(tableName);
         List<ToolSchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableName);
         // 导入
-        return self.createCodegen0(ToolCodegenImportTypeEnum.DB, schemaTable, schemaColumns);
+        return this.createCodegen0(ToolCodegenImportTypeEnum.DB, schemaTable, schemaColumns);
     }
 
     @Override
@@ -147,7 +144,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
         List<ToolSchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(table.getTableName());
 
         // 执行同步
-        self.syncCodegen0(tableId, schemaColumns);
+        this.syncCodegen0(tableId, schemaColumns);
     }
 
     @Override
@@ -167,7 +164,7 @@ public class ToolCodegenServiceImpl implements ToolCodegenService {
         }
 
         // 执行同步
-        self.syncCodegen0(tableId, schemaColumns);
+        this.syncCodegen0(tableId, schemaColumns);
     }
 
     private void syncCodegen0(Long tableId, List<ToolSchemaColumnDO> schemaColumns) {

+ 2 - 2
src/main/resources/codegen/vue/views/index.vue.vm

@@ -268,12 +268,12 @@ export default {
         this.loading = false;
       });
     },
-    // 取消按钮
+    /** 取消按钮 */
     cancel() {
       this.open = false;
       this.reset();
     },
-    // 表单重置
+    /** 表单重置 */
     reset() {
       this.form = {
         #foreach ($column in $columns)

Some files were not shown because too many files changed in this diff