ソースを参照

完善任务模板功能

yangll 3 年 前
コミット
4223027db7
12 ファイル変更1876 行追加17 行削除
  1. 198 0
      tnc-generate/src/main/java/org/jeecg/codegen/generate/impl/CodeGenerateCheck.java
  2. 2 2
      tnc-generate/src/main/java/org/jeecg/codegen/generate/impl/CodeGenerateOne.java
  3. 35 1
      tnc-generate/src/main/java/org/jeecg/codegen/window/JeecgOneUtil.java
  4. 1 1
      tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/entity/${entityName}Task.javai
  5. 422 0
      tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/${entityName}TaskList.vuei
  6. 217 0
      tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskForm.vuei
  7. 70 0
      tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskModal.vuei
  8. 221 12
      tnc-online/src/main/java/org/jeecg/modules/online/cgform/service/impl/OnlCgformHeadServiceImpl.java
  9. 1 1
      tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/entity/${entityName}Task.javai
  10. 422 0
      tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/${entityName}TaskList.vuei
  11. 217 0
      tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskForm.vuei
  12. 70 0
      tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskModal.vuei

+ 198 - 0
tnc-generate/src/main/java/org/jeecg/codegen/generate/impl/CodeGenerateCheck.java

@@ -0,0 +1,198 @@
+package org.jeecg.codegen.generate.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.jeecg.codegen.config.CodeConfigProperties;
+import org.jeecg.codegen.database.DbReadTableUtil;
+import org.jeecg.codegen.generate.IGenerate;
+import org.jeecg.codegen.generate.config.CreateFileConfig;
+import org.jeecg.codegen.generate.impl.base.BaseCodeGenerate;
+import org.jeecg.codegen.generate.pojo.ColumnVo;
+import org.jeecg.codegen.generate.pojo.TableVo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 生成稽核项目的模板
+ */
+@Slf4j
+public class CodeGenerateCheck extends BaseCodeGenerate implements IGenerate {
+
+    private static final Logger logger = LoggerFactory.getLogger(CodeGenerateCheck.class);
+    /** 表配置 */
+    private TableVo tableVo;
+    /** 表中所有字段(排除:主键和隐藏字段) 作用:前端显示字段 */
+    private List<ColumnVo> columns;
+    /** 表中所有字段 作用:后端字段,前端树形相关字段 */
+    private List<ColumnVo> originalColumns;
+    /** 任务所有字段 作用:稽核任务字段 */
+    private List<ColumnVo> taskColumns;
+    /**
+     * 构造函数
+     *
+     * @param tableVo 表信息
+     */
+    public CodeGenerateCheck(TableVo tableVo) {
+        this.tableVo = tableVo;
+    }
+
+    /**
+     * 构造函数
+     *
+     * @param tableVo 表信息
+     * @param columns 表中全部字段(排除:主键和隐藏字段)
+     * @param originalColumns 表中全部字段
+     */
+    public CodeGenerateCheck(TableVo tableVo, List<ColumnVo> columns, List<ColumnVo> originalColumns) {
+        this.tableVo = tableVo;
+        this.columns = columns;
+        this.originalColumns = originalColumns;
+    }
+
+    /**
+     * 前端模板中数据模型
+     *
+     * @return 数据模型
+     * @throws Exception 异常
+     */
+    @Override
+    public Map<String, Object> getDataModel() throws Exception {
+        HashMap<String, Object> dataModel = new HashMap<>();
+        // 根包名
+        dataModel.put("bussiPackage", CodeConfigProperties.businessPackage);
+        // 实体类包名
+        dataModel.put("entityPackage", tableVo.getEntityPackage());
+        // 实体类名
+        dataModel.put("entityName", tableVo.getEntityName());
+        // 表名
+        dataModel.put("tableName", tableVo.getTableName());
+        // 主键
+        dataModel.put("primaryKeyField", CodeConfigProperties.primaryKeyField);
+
+        // 查询字段显示数( 1 表示2个,设计不合理,需要改模板中条件)
+        if (tableVo.getSearchFieldNum() == null) {
+            tableVo.setSearchFieldNum(StringUtils.isNotEmpty(CodeConfigProperties.searchFieldNum)
+                    ? Integer.parseInt(CodeConfigProperties.searchFieldNum) : -1);
+        }
+        // 字段一行显示个数
+        if (tableVo.getFieldRowNum() == null) {
+            tableVo.setFieldRowNum(Integer.parseInt(CodeConfigProperties.fieldRowNum));
+        }
+
+        dataModel.put("tableVo", tableVo);
+
+        try {
+            // 表中所有字段(排除:主键和隐藏字段)
+            if (columns == null || columns.size() == 0) {
+                columns = DbReadTableUtil.readTableColumn(tableVo.getTableName());
+            }
+            dataModel.put("columns", columns);
+
+            // 表中所有字段
+            if (originalColumns == null || originalColumns.size() == 0) {
+                originalColumns = DbReadTableUtil.readOriginalTableColumn(tableVo.getTableName());
+            }
+            dataModel.put("originalColumns", originalColumns);
+
+            // 设置主键策略
+            for (ColumnVo column : originalColumns) {
+                if (column.getFieldName().equalsIgnoreCase(CodeConfigProperties.primaryKeyField)) {
+                    dataModel.put("primaryKeyPolicy", column.getFieldType());
+                }
+            }
+
+            // 稽核任务字段
+            if (taskColumns == null || taskColumns.size() == 0) {
+                taskColumns = new ArrayList<>();
+            }
+            dataModel.put("taskColumns", taskColumns);
+        } catch (Exception e) {
+            throw e;
+        }
+
+        // 实体类的UUID
+        long serialVersionUID = nextLong() + milliseconds();
+        dataModel.put("serialVersionUID", String.valueOf(serialVersionUID));
+        logger.info("load template data model: " + dataModel);
+
+        return dataModel;
+    }
+
+    /**
+     * 生成代码<br>
+     * 指定模板风格路径<br><br>
+     *
+     * 默认项目目录:当前项目类路径<br>
+     * 默认模板目录:jeecg/code-template<br>
+     * 默认模板风格目录:one<br><br>
+     *
+     * @param stylePath 模板风格目录
+     * @return 生成文件路径
+     * @throws Exception 异常
+     */
+    @Override
+    public List<String> generateCodeFile(String stylePath) throws Exception {
+        logger.debug("----Code----Generator----[单表模型:" + tableVo.getTableName() + "]------- 生成中。。。");
+        Map<String, Object> dataModel = getDataModel();
+        // 模板文件配置
+        CreateFileConfig createFileConfig = new CreateFileConfig(CodeConfigProperties.generatePath,
+                CodeConfigProperties.templatePath, stylePath);
+        // 生成代码
+        generate(createFileConfig, dataModel);
+        logger.info(" ----- tnc-boot ---- generate code success =======> 表名:" + tableVo.getTableName() + " ");
+        return genFileList;
+    }
+
+    /**
+     * 生成代码<br>
+     * 使用默认项目路径、模板路径、模板风格路径<br><br>
+     *
+     * 默认项目路径:当前项目类路径<br>
+     * 默认模板路径:jeecg/code-template<br>
+     * 默认模板风格路径:one<br><br>
+     *
+     * @return 生成文件路径
+     * @throws Exception 异常
+     */
+    @Override
+    public List<String> generateCodeFile() throws Exception {
+        return generateCodeFile("");
+    }
+
+    /**
+     * 生成代码<br>
+     * 指定项目路径、模板路径和模板风格路径<br><br>
+     *
+     * @param generatePath 项目路径
+     * @param templatePath 模板路径
+     * @param stylePath 模板风格路径
+     * @return 生成代码文件路径
+     * @throws Exception 异常
+     */
+    @Override
+    public List<String> generateCodeFile(String generatePath, String templatePath, String stylePath) throws Exception {
+        if (generatePath != null && !"".equals(generatePath)) {
+            CodeConfigProperties.setGeneratePath(generatePath);
+        }
+        if (templatePath != null && !"".equals(templatePath)) {
+            CodeConfigProperties.setTemplatePath(templatePath);
+        }
+        generateCodeFile(stylePath);
+        return genFileList;
+    }
+
+    /**
+     * 设置任务字段
+     *
+     * @param taskColumns 任务字段
+     */
+    public void setTaskColumns(List<ColumnVo> taskColumns) {
+        this.taskColumns = taskColumns;
+    }
+
+}

+ 2 - 2
tnc-generate/src/main/java/org/jeecg/codegen/generate/impl/CodeGenerateOne.java

@@ -22,9 +22,9 @@ public class CodeGenerateOne extends BaseCodeGenerate implements IGenerate {
     private static final Logger logger = LoggerFactory.getLogger(CodeGenerateOne.class);
     /** 表配置 */
     private TableVo tableVo;
-    /** 表中所有字段(排除:主键和隐藏字段) */
+    /** 表中所有字段(排除:主键和隐藏字段) 作用:前端显示字段 */
     private List<ColumnVo> columns;
-    /** 表中所有字段 */
+    /** 表中所有字段 作用:后端字段,前端树形相关字段 */
     private List<ColumnVo> originalColumns;
 
     /**

+ 35 - 1
tnc-generate/src/main/java/org/jeecg/codegen/window/JeecgOneUtil.java

@@ -1,6 +1,7 @@
 package org.jeecg.codegen.window;
 
 import lombok.SneakyThrows;
+import org.jeecg.codegen.generate.impl.CodeGenerateCheck;
 import org.jeecg.codegen.generate.impl.CodeGenerateOne;
 import org.jeecg.codegen.generate.pojo.TableVo;
 import org.jeecg.common.constant.enums.CgformEnum;
@@ -20,7 +21,10 @@ public class JeecgOneUtil {
 //        enumGen();
 
         // 自定义配置
-        genTwo();
+//        genTwo();
+
+        // 自定义配置
+        genTwo2();
     }
 
 
@@ -110,4 +114,34 @@ public class JeecgOneUtil {
             System.out.println(fileName);
         }
     }
+
+    /**
+     * 自定义配置生成代码
+     */
+    @SneakyThrows
+    private static void genTwo2(){
+        TableVo tableVo = new TableVo();
+        // 表名
+        tableVo.setTableName("check_sms");
+        // 实体名
+        tableVo.setEntityName("CheckSms");
+        // 包名
+        tableVo.setEntityPackage("checksms");
+        // 描述
+        tableVo.setFtlDescription("短信验证");
+        // 单表代码生成器
+        CodeGenerateCheck generate = new CodeGenerateCheck(tableVo);
+        // 自定义配置 代码生成路径
+        String generateRootPath = "D:\\codeGen";
+        // 模板目录
+        String templatePath = "/jeecg/code-template-online";
+        // 风格目录
+        String stylePath = "default.two";
+
+        List<String> codeFileList = generate.generateCodeFile(generateRootPath,templatePath,stylePath);
+
+        for (String fileName : codeFileList) {
+            System.out.println(fileName);
+        }
+    }
 }

+ 1 - 1
tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/entity/${entityName}Task.javai

@@ -34,7 +34,7 @@ public class ${entityName}Task implements Serializable {
 
 <#-- excel注解 忽略字段 -->
 <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
-<#list originalColumns as po>
+<#list taskColumns as po>
 <#if po.fieldGroup='common'>
   <#-- 生成字典Code -->
   <#assign list_field_dictCode="">

+ 422 - 0
tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/${entityName}TaskList.vuei

@@ -0,0 +1,422 @@
+<#include "/common/utils.ftl">
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+<#t>
+<#-- ============== 变量定义 ============== -->
+<#t>
+<#-- 查询字段显示个数,超过隐藏 -->
+<#assign query_field_no=0>
+<#-- 查询条件是否显示 是:"Y";否:"N" -->
+<#assign query_flag=false>
+<#-- 是否需要,字典 -->
+<#assign list_need_dict=false>
+<#-- 是否需要,种类 -->
+<#assign list_need_category=false>
+<#-- 是否需要,省市区 -->
+<#assign list_need_pca=false>
+<#-- 是否需要,开关  -->
+<#assign list_need_switch=false>
+<#-- 是否需要,缩进  -->
+<#assign indent_flag=false>
+<#-- 缩进宏代码  -->
+<#macro indent>
+<#if indent_flag=true>  </#if><#t>
+</#macro>
+
+<#-- 开始-遍历字段 -->
+<#list taskColumns as po>
+<#if po.isQuery=='Y'>
+<#t>
+<#-- 开始-字段一列 -->
+<#assign query_flag=true>
+  <#-- 超过指定查询字段数,折叠剩余查询字段  -->
+  <#if query_field_no==2>
+    <#assign indent_flag=true>
+          <template v-if="toggleSearchStatus">
+  </#if>
+  <#-- 开始-字段的字典值 -->
+  <#assign query_field_dictCode="">
+  <#if po.dictTable?default("")?trim?length gt 1>
+    <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
+  <#elseif po.dictField?default("")?trim?length gt 1>
+    <#assign query_field_dictCode="${po.dictField}">
+  </#if>
+  <#-- 结束-字段的字典值 -->
+  <#if po.queryMode=='single'>
+          <@indent/><a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <@indent/><a-form-item label="${po.filedComment}">
+            <#if po.classType=='sel_search'>
+              <@indent/><j-search-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}"/>
+            <#elseif po.classType=='sel_user'>
+              <@indent/><j-select-user-by-dep placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
+            <#elseif po.classType=='switch'>
+              <@indent/><j-switch placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> query></j-switch>
+            <#elseif po.classType=='sel_depart'>
+              <@indent/><j-select-depart placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
+            <#elseif po.classType=='list_multi'>
+              <@indent/><j-multi-select-tag placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model="queryParam.${po.fieldName}"/>
+            <#elseif po.classType=='cat_tree'>
+              <@indent/><j-category-select placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}"/>
+            <#elseif po.classType=='date'>
+              <@indent/><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
+            <#elseif po.classType=='datetime'>
+              <@indent/><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
+            <#elseif po.classType=='pca'>
+              <@indent/><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
+            <#elseif po.classType=='popup'>
+              <@indent/><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
+            <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
+              <#--  开始-下拉或是单选 判断数据字典是表字典还是普通字典 -->
+              <#if po.dictTable?default("")?trim?length gt 1>
+              <@indent/><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
+              <#elseif po.dictField?default("")?trim?length gt 1>
+              <@indent/><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
+              <#else>
+              <@indent/><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
+              </#if>
+              <#--  结束-下拉或是单选 判断数据字典是表字典还是普通字典 -->
+            <#else>
+              <@indent/><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
+            </#if>
+            <@indent/></a-form-item>
+          <@indent/></a-col>
+  <#else>
+          <@indent/><a-col :xl="10" :lg="11" :md="12" :sm="24">
+            <@indent/><a-form-item label="${po.filedComment}">
+      <#if po.classType=='date'>
+              <@indent/><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
+              <@indent/><span class="query-group-split-cust"></span>
+              <@indent/><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
+      <#elseif po.classType=='datetime'>
+              <@indent/><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
+              <@indent/><span class="query-group-split-cust"></span>
+              <@indent/><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
+      <#else>
+              <@indent/><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
+              <@indent/><span class="query-group-split-cust"></span>
+              <@indent/><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
+      </#if>
+            <@indent/></a-form-item>
+          <@indent/></a-col>
+  </#if>
+<#assign query_field_no=query_field_no+1>
+</#if>
+<#-- 结束-字段一列 -->
+<#t>
+<#-- 开始-字段字典 -->
+<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
+<#assign list_need_dict=true>
+</#if>
+<#-- 结束-字段字典 -->
+<#-- 开始-字段树形 -->
+<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
+<#assign list_need_category=true>
+</#if>
+<#-- 结束-字段树形 -->
+<#-- 开始-字段省市区 -->
+<#if po.classType=='pca'>
+<#assign list_need_pca=true>
+</#if>
+<#-- 结束-字段省市区 -->
+<#-- 开始-字段开关 -->
+<#if po.classType=='switch'>
+<#assign list_need_switch=true>
+</#if>
+<#-- 结束-字段开关 -->
+</#list>
+<#-- 结束-遍历字段 -->
+<#t>
+
+<#if indent_flag=true>
+          </template>
+</#if>
+<#t>
+<#-- 开始-查询按钮 -->
+<#if query_flag>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+</#if>
+<#-- 结束-查询按钮 -->
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <!-- 高级查询区域 -->
+      <j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        <#if (tableVo.extendParams.scroll)! == '1'>
+        :scroll="{x:true}"
+        </#if>
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        class="j-table-force-nowrap"
+        @change="handleTableChange">
+
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text,record">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
+          <img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <#if list_need_pca>
+        <template slot="pcaSlot" slot-scope="text">
+          <div>{{ getPcaText(text) }}</div>
+        </template>
+        </#if>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="downloadFile(text)">
+            下载
+          </a-button>
+        </template>
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a @click="handleDetail(record)">详情</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <#-- 使用格式化工具类转换 -->
+    <${Format.humpToShortbar(entityName)}-modal ref="modalForm" @ok="modalFormOk"></${Format.humpToShortbar(entityName)}-modal>
+  </a-card>
+</template>
+
+<script>
+
+  import '@/assets/less/TableExpand.less'
+  import { mixinDevice } from '@/utils/mixin'
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import ${entityName}Modal from './modules/${entityName}Modal'
+
+  <#if list_need_category>
+  import { loadCategoryData } from '@/api/api'
+  </#if>
+  <#if list_need_dict>
+  import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
+  </#if>
+  <#if list_need_pca>
+  import Area from '@/components/_util/Area'
+  </#if>
+
+  export default {
+    name: '${entityName}List',
+    mixins:[JeecgListMixin, mixinDevice],
+    components: {
+      ${entityName}Modal
+    },
+    data () {
+      return {
+        description: '${tableVo.ftlDescription}管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+  <#-- 表字段定义 -->
+  <#list taskColumns as po>
+  <#if po.isShowList =='Y' && po.fieldName !='id'>
+          {
+            title:'${po.filedComment}',
+            align:"center",
+            <#-- 排序 -->
+            <#if po.sort=='Y'>
+            sorter: true,
+            </#if>
+            <#if po.classType=='date'>
+            dataIndex: '${po.fieldName}',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+            <#elseif po.fieldDbType=='Blob'>
+            dataIndex: '${po.fieldName}String'
+            <#-- 富文本 -->
+            <#elseif po.classType=='umeditor'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'htmlSlot'}
+            <#elseif po.classType=='pca'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'pcaSlot'}
+            <#elseif po.classType=='file'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'fileSlot'}
+            <#elseif po.classType=='image'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'imgSlot'}
+            <#elseif po.classType=='switch'>
+            dataIndex: '${po.fieldName}',
+            customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : ''),
+            <#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
+            dataIndex: '${po.fieldName}_dictText'
+            <#elseif po.classType=='cat_tree'>
+            <#if list_need_category>
+            dataIndex: '${po.fieldName}',
+            customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : '')
+            <#else>
+            dataIndex: '${po.fieldName}',
+            customRender: (text, record) => (text ? record['${dashedToCamel(po.dictText)}'] : '')
+            </#if>
+      <#else>
+            dataIndex: '${po.fieldName}'
+      </#if>
+          },
+     </#if>
+     </#list>
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            <#if (tableVo.extendParams.scroll)! == '1'>
+            fixed:"right",
+            width:147,
+            </#if>
+            scopedSlots: { customRender: 'action' }
+          }
+        ],
+        url: {
+          list: "/${entityPackage}/${entityName?uncap_first}/list",
+          delete: "/${entityPackage}/${entityName?uncap_first}/delete",
+          deleteBatch: "/${entityPackage}/${entityName?uncap_first}/deleteBatch",
+          exportXlsUrl: "/${entityPackage}/${entityName?uncap_first}/exportXls",
+          importExcelUrl: "${entityPackage}/${entityName?uncap_first}/importExcel",
+        },
+        dictOptions:{},
+        <#-- 省市区 -->
+        <#if list_need_pca>
+        pcaData:'',
+        </#if>
+        superFieldList:[],
+      }
+    },
+    created() {
+    <#if list_need_pca>
+      this.pcaData = new Area()
+    </#if>
+    <#if list_need_switch>
+    <#list taskColumns as po>
+    <#if po.classType=='switch'>
+      <#assign switch_extend_arr=['Y','N']>
+      <#if po.dictField?default("")?contains("[")>
+        <#assign switch_extend_arr=po.dictField?eval>
+      </#if>
+      <#list switch_extend_arr as a>
+       <#if a_index == 0>
+       <#assign switch_extend_arr1=a>
+       <#else>
+       <#assign switch_extend_arr2=a>
+       </#if>
+      </#list>
+      this.$set(this.dictOptions, '${po.fieldName}', [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
+    </#if>
+    </#list>
+    </#if>
+    this.getSuperFieldList();
+    },
+    computed: {
+      importExcelUrl: function(){
+        <#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
+      },
+    },
+    methods: {
+    <#if list_need_pca>
+      getPcaText(code){
+        return this.pcaData.getText(code);
+      },
+    </#if>
+      initDictConfig(){
+      <#list taskColumns as po>
+      <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
+        <#if po.classType=='cat_tree' && list_need_category==true>
+        loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
+          if (res.success) {
+            this.$set(this.dictOptions, '${po.fieldName}', res.result)
+          }
+        })
+        </#if>
+      </#if>
+      </#list>
+      },
+      <#-- 高级查询 -->
+      getSuperFieldList(){
+        let fieldList=[];
+         <#list taskColumns as po>
+        fieldList.push(${superQueryFieldList(po)})
+         </#list>
+        this.superFieldList = fieldList
+      }
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>

+ 217 - 0
tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskForm.vuei

@@ -0,0 +1,217 @@
+
+<#include "/common/utils.ftl">
+<template>
+  <a-spin :spinning="confirmLoading">
+    <j-form-container :disabled="formDisabled">
+      <a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
+        <a-row>
+<#-- Popup弹框 -->
+<#assign form_popup = false>
+<#-- 分类字典树 -->
+<#assign form_cat_tree = false>
+<#assign form_cat_back = "">
+<#t>
+<#-- 一行一列 字段所占区域 -->
+<#assign form_span = 24>
+<#if tableVo.fieldRowNum==2>
+<#assign form_span = 12>
+<#elseif tableVo.fieldRowNum==3>
+<#assign form_span = 8>
+<#elseif tableVo.fieldRowNum==4>
+<#assign form_span = 6>
+</#if>
+<#-- 开始-遍历字段 -->
+<#list taskColumns as po>
+<#t>
+<#if po.isShow =='Y' && po.fieldName != 'id'>
+  <#assign form_field_dictCode="">
+  <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
+    <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
+  <#elseif po.dictField?default("")?trim?length gt 1>
+    <#assign form_field_dictCode="${po.dictField}">
+  </#if>
+          <a-col :span="${form_span}">
+            <a-form-model-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="${autoStringSuffixForModel(po)}">
+  <#if po.classType =='date'>
+              <j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}"  style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='datetime'>
+              <j-date placeholder="请选择${po.filedComment}"  v-model="model.${po.fieldName}" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='time'>
+              <j-time placeholder="请选择${po.filedComment}"  v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='popup'>
+      <#assign form_popup=true>
+              <j-popup
+                v-model="model.${po.fieldName}"
+                field="${po.fieldName}"
+                org-fields="${po.dictField}"
+                dest-fields="${Format.underlineToHump(po.dictText)}"
+                code="${po.dictTable}"
+                :multi="${po.extendParams.popupMulti?c}"
+                @input="popupCallback"
+                <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='sel_depart'>
+              <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if> />
+  <#elseif po.classType =='switch'>
+              <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
+  <#elseif po.classType =='pca'>
+             <j-area-linkage type="cascader" v-model="model.${po.fieldName}" placeholder="请输入省市区" <#if po.readonly=='Y'>disabled</#if> />
+  <#elseif po.classType =='markdown'>
+              <j-markdown-editor v-model="model.${autoStringSuffixForModel(po)}" id="${po.fieldName}"></j-markdown-editor>
+  <#elseif po.classType =='password'>
+              <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='sel_user'>
+              <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='textarea'>
+              <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='list' || po.classType=='radio'>
+              <j-dict-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
+              <j-multi-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='sel_search'>
+              <j-search-select-tag v-model="model.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> />
+  <#elseif po.classType=='cat_tree'>
+      <#assign form_cat_tree = true>
+              <j-category-select v-model="model.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}" @change="handleCategoryChange"</#if> <#if po.readonly=='Y'>disabled</#if>/>
+      <#if po.dictText?default("")?trim?length gt 1>
+        <#assign form_cat_back = "${po.dictText}">
+      </#if>
+  <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
+              <a-input-number v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='file'>
+              <j-upload v-model="model.${po.fieldName}"  <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:number=${po.uploadnum}</#if>></j-upload>
+  <#elseif po.classType=='image'>
+              <j-image-upload isMultiple <#if po.uploadnum??>:number=${po.uploadnum}</#if> v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
+  <#elseif po.classType=='umeditor'>
+              <j-editor v-model="model.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.fieldDbType=='Blob'>
+              <a-input v-model="model.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
+  <#elseif po.classType == 'sel_tree'>
+              <j-tree-select
+                ref="treeSelect"
+                placeholder="请选择${po.filedComment}"
+                v-model="model.${po.fieldName}"
+                <#if po.dictText??>
+                <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
+                dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
+                <#elseif po.dictText?split(',')[1]??>
+                pidField="${po.dictText?split(',')[1]}"
+                <#elseif po.dictText?split(',')[3]??>
+                hasChildField="${po.dictText?split(',')[3]}"
+                </#if>
+                </#if>
+                pidValue="${po.dictField}"
+                <#if po.readonly=='Y'>disabled</#if>>
+              </j-tree-select>
+  <#else>
+              <a-input v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> ></a-input>
+  </#if>
+            </a-form-model-item>
+          </a-col>
+</#if>
+</#list>
+<#-- 结束-遍历字段 -->
+        </a-row>
+      </a-form-model>
+    </j-form-container>
+  </a-spin>
+</template>
+
+<script>
+
+  import { httpAction, getAction } from '@/api/manage'
+  import { validateDuplicateValue } from '@/utils/util'
+
+  export default {
+    name: '${entityName}TaskForm',
+    components: {
+    },
+    props: {
+      //表单禁用
+      disabled: {
+        type: Boolean,
+        default: false,
+        required: false
+      }
+    },
+    data () {
+      return {
+        model:{
+            <#include "/common/init/initValue.ftl">
+         },
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 },
+        },
+        confirmLoading: false,
+        <#include "/common/validatorRulesTemplate/main.ftl">
+        url: {
+          add: "/${entityPackage}/${entityName?uncap_first}/add",
+          edit: "/${entityPackage}/${entityName?uncap_first}/edit",
+          queryById: "/${entityPackage}/${entityName?uncap_first}/queryById"
+        }
+      }
+    },
+    computed: {
+      formDisabled(){
+        return this.disabled
+      },
+
+    },
+    created () {
+       //备份model原始值
+      this.modelDefault = JSON.parse(JSON.stringify(this.model));
+    },
+    methods: {
+      add () {
+        this.edit(this.modelDefault);
+      },
+      edit (record) {
+        this.model = Object.assign({}, record);
+        this.visible = true;
+      },
+      submitForm () {
+        const that = this;
+        // 触发表单验证
+        this.$refs.form.validate(valid => {
+          if (valid) {
+            that.confirmLoading = true;
+            let httpurl = '';
+            let method = '';
+            if(!this.model.id){
+              httpurl+=this.url.add;
+              method = 'post';
+            }else{
+              httpurl+=this.url.edit;
+               method = 'put';
+            }
+            httpAction(httpurl,this.model,method).then((res)=>{
+              if(res.success){
+                that.$message.success(res.message);
+                that.$emit('ok');
+              }else{
+                that.$message.warning(res.message);
+              }
+            }).finally(() => {
+              that.confirmLoading = false;
+            })
+          }
+         
+        })
+      },
+       <#if form_popup>
+      popupCallback(value,row){
+         this.model = Object.assign(this.model, row);
+      },
+       </#if>
+      <#if form_cat_tree>
+      handleCategoryChange(value,backObj){
+         this.model = Object.assign(this.model, backObj);
+      }
+      </#if>
+    }
+  }
+</script>

+ 70 - 0
tnc-generate/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskModal.vuei

@@ -0,0 +1,70 @@
+
+<#include "/common/utils.ftl">
+<#assign modal_width = 800>
+<#if tableVo.fieldRowNum==2>
+  <#assign modal_width = 896>
+<#elseif tableVo.fieldRowNum==3>
+  <#assign modal_width = 1024>
+<#elseif tableVo.fieldRowNum==4>
+  <#assign modal_width = 1280>
+</#if>
+<template>
+  <j-modal
+    :title="title"
+    :width="width"
+    :visible="visible"
+    switchFullscreen
+    @ok="handleOk"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    @cancel="handleCancel"
+    cancelText="关闭">
+    <${Format.humpToShortbar(entityName)}-task-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></${Format.humpToShortbar(entityName)}-task-form>
+  </j-modal>
+</template>
+
+<script>
+
+  import ${entityName}TaskForm from './${entityName}TaskForm'
+  export default {
+    name: '${entityName}TaskModal',
+    components: {
+      ${entityName}TaskForm
+    },
+    data () {
+      return {
+        title:'',
+        width:${modal_width},
+        visible: false,
+        disableSubmit: false
+      }
+    },
+    methods: {
+      add () {
+        this.visible=true
+        this.$nextTick(()=>{
+          this.$refs.realForm.add();
+        })
+      },
+      edit (record) {
+        this.visible=true
+        this.$nextTick(()=>{
+          this.$refs.realForm.edit(record);
+        })
+      },
+      close () {
+        this.$emit('close');
+        this.visible = false;
+      },
+      handleOk () {
+        this.$refs.realForm.submitForm();
+      },
+      submitCallback(){
+        this.$emit('ok');
+        this.visible = false;
+      },
+      handleCancel () {
+        this.close()
+      }
+    }
+  }
+</script>

+ 221 - 12
tnc-online/src/main/java/org/jeecg/modules/online/cgform/service/impl/OnlCgformHeadServiceImpl.java

@@ -11,7 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.commons.lang.StringUtils;
-import org.jeecg.codegen.generate.impl.CodeGenerateOneToMany;
+import org.jeecg.codegen.generate.impl.CodeGenerateCheck;
 import org.jeecg.codegen.generate.pojo.onetomany.SubTableVo;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.aspect.annotation.AutoLowApp;
@@ -1504,8 +1504,14 @@ public class OnlCgformHeadServiceImpl extends ServiceImpl<OnlCgformHeadMapper, O
         tableVo.setExtendParams(extendParams);
         // 代码生成风格 (模板目录,模板风格目录)
         CgformEnum cgformEnum = CgformEnum.getCgformEnumByConfig(model.getJspMode());
-        List<String> fileList = new CodeGenerateOne(tableVo, columns, originalColumns)
-                .generateCodeFile(model.getProjectPath(), cgformEnum.getTemplatePath(), cgformEnum.getStylePath());
+//        List<String> fileList = new CodeGenerateOne(tableVo, columns, originalColumns)
+//                .generateCodeFile(model.getProjectPath(), cgformEnum.getTemplatePath(), cgformEnum.getStylePath());
+
+        List<ColumnVo> taskColumns = getTaskColumns(model.getCode());
+        CodeGenerateCheck generate = new CodeGenerateCheck(tableVo, columns, originalColumns);
+        generate.setTaskColumns(taskColumns);
+        List<String> fileList = generate.generateCodeFile(model.getProjectPath(), cgformEnum.getTemplatePath(), cgformEnum.getStylePath());
+
         if (fileList == null || fileList.size() == 0) {
             fileList = new ArrayList<>();
             fileList.add(" :::::: 生成失败ERROR提示 :::::: ");
@@ -1516,6 +1522,106 @@ public class OnlCgformHeadServiceImpl extends ServiceImpl<OnlCgformHeadMapper, O
         return fileList;
     }
 
+    /**
+     * 获取任务字段
+     *
+     * @param headId 表id
+     * @return 任务相关字段
+     */
+    private List<ColumnVo> getTaskColumns(String headId) {
+        LambdaQueryWrapper<OnlCgformField> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(OnlCgformField::getCgformHeadId, headId);
+        queryWrapper.in(OnlCgformField::getFieldGroup, "common", "task");
+        queryWrapper.orderByAsc(OnlCgformField::getOrderNum);
+        List<OnlCgformField> dbFormFieldList = fieldService.list(queryWrapper);
+        List<ColumnVo> columnList = new ArrayList<>();
+        for (OnlCgformField dbFormField : dbFormFieldList) {
+            ColumnVo columnVo = new ColumnVo();
+            columnVo.setFieldLength(dbFormField.getFieldLength());
+            columnVo.setFieldHref(dbFormField.getFieldHref());
+            columnVo.setFieldValidType(dbFormField.getFieldValidType());
+            columnVo.setFieldDefault(dbFormField.getDbDefaultVal());
+            columnVo.setFieldShowType(dbFormField.getFieldShowType());
+            columnVo.setFieldOrderNum(dbFormField.getOrderNum());
+            columnVo.setIsKey(dbFormField.getDbIsKey() == 1 ? "Y" : "N");
+            columnVo.setIsShow(dbFormField.getIsShowForm() == 1 ? "Y" : "N");
+            columnVo.setIsShowList(dbFormField.getIsShowList() == 1 ? "Y" : "N");
+            columnVo.setIsQuery(dbFormField.getIsQuery() == 1 ? "Y" : "N");
+            columnVo.setQueryMode(dbFormField.getQueryMode());
+            columnVo.setDictField(dbFormField.getDictField());
+            columnVo.setDictTable(dbFormField.getDictTable());
+            columnVo.setDictText(dbFormField.getDictText());
+            columnVo.setFieldDbName(dbFormField.getDbFieldName());
+            columnVo.setFieldName(oConvertUtils.camelName(dbFormField.getDbFieldName()));
+            columnVo.setFiledComment(dbFormField.getDbFieldTxt());
+            columnVo.setFieldDbType(dbFormField.getDbType());
+            columnVo.setFieldType(this.convertType(dbFormField.getDbType()));
+            columnVo.setClassType(dbFormField.getFieldShowType());
+            columnVo.setClassType_row(dbFormField.getFieldShowType());
+            // 字段是否为空
+            if (dbFormField.getDbIsNull() != 0 && !"*".equals(dbFormField.getFieldValidType()) && !"1".equals(dbFormField.getFieldMustInput())) {
+                columnVo.setNullable("Y");
+            } else {
+                columnVo.setNullable("N");
+            }
+
+            if ("switch".equals(dbFormField.getFieldShowType())) {
+                if (oConvertUtils.isNotEmpty(dbFormField.getFieldExtendJson())) {
+                    columnVo.setDictField(dbFormField.getFieldExtendJson());
+                } else {
+                    columnVo.setDictField("is_open");
+                }
+            }
+
+            Map<String,Object> extendParams = new HashMap<>();
+            JSONObject jsonObject;
+            if (StringUtils.isNotBlank(dbFormField.getFieldExtendJson())) {
+                try {
+                    jsonObject = JSONObject.parseObject(dbFormField.getFieldExtendJson());
+                    if (jsonObject != null) {
+                        extendParams.putAll(jsonObject.getInnerMap());
+                    }
+                } catch (JSONException e) {
+                }
+            }
+
+            columnVo.setExtendParams(extendParams);
+
+            if ("popup".equals(dbFormField.getFieldShowType())) {
+                boolean popupMulti = true;
+                Object flag = extendParams.get("popupMulti");
+                if (flag != null) {
+                    popupMulti = (boolean)flag;
+                }
+
+                extendParams.put("popupMulti", popupMulti);
+            }
+
+            columnVo.setSort("1".equals(dbFormField.getSortFlag()) ? "Y" : "N");
+            columnVo.setReadonly(Integer.valueOf(1).equals(dbFormField.getIsReadOnly()) ? "Y" : "N");
+
+            if (oConvertUtils.isNotEmpty(dbFormField.getFieldDefaultValue()) &&
+                    !dbFormField.getFieldDefaultValue().trim().startsWith("${") &&
+                    !dbFormField.getFieldDefaultValue().trim().startsWith("#{") &&
+                    !dbFormField.getFieldDefaultValue().trim().startsWith("{{")) {
+                columnVo.setDefaultVal(dbFormField.getFieldDefaultValue());
+            }
+
+            if (("file".equals(dbFormField.getFieldShowType()) ||
+                    "image".equals(dbFormField.getFieldShowType())) &&
+                    oConvertUtils.isNotEmpty(dbFormField.getFieldExtendJson())) {
+                jsonObject = JSONObject.parseObject(dbFormField.getFieldExtendJson());
+                if (oConvertUtils.isNotEmpty(jsonObject.getString("uploadnum"))) {
+                    columnVo.setUploadnum(jsonObject.getString("uploadnum"));
+                }
+            }
+            columnList.add(columnVo);
+        }
+
+
+        return columnList;
+    }
+
     @Override
     public List<String> generateOneToMany(OnlGenerateModel model) throws Exception {
         MainTableVo mainTableVo = new MainTableVo();
@@ -1531,11 +1637,11 @@ public class OnlCgformHeadServiceImpl extends ServiceImpl<OnlCgformHeadMapper, O
             mainTableVo.setFieldRowNum(Integer.parseInt(formTemplate));
         }
 
-        List<ColumnVo> columns = new ArrayList();
-        List<ColumnVo> originalColumns = new ArrayList();
+        List<ColumnVo> columns = new ArrayList<>();
+        List<ColumnVo> originalColumns = new ArrayList<>();
         this.getFieldByTableName(model.getCode(), columns, originalColumns);
         List<OnlGenerateModel> generateModelList = model.getSubList();
-        List<SubTableVo> subTableVoList = new ArrayList();
+        List<SubTableVo> subTableVoList = new ArrayList<>();
 
         for (OnlGenerateModel generateModel : generateModelList) {
             OnlCgformHead cgformHead = this.baseMapper.selectOne(new LambdaQueryWrapper<OnlCgformHead>()
@@ -1548,12 +1654,12 @@ public class OnlCgformHeadServiceImpl extends ServiceImpl<OnlCgformHeadMapper, O
                 subTableVo.setFtlDescription(generateModel.getFtlDescription());
                 Integer relationType = cgformHead.getRelationType();
                 subTableVo.setForeignRelationType(relationType == 1 ? "1" : "0");
-                List<ColumnVo> columnList = new ArrayList();
-                List<ColumnVo> OriginalColumnList = new ArrayList();
-                OnlCgformField var16 = this.getFieldByTableName(cgformHead.getId(), columnList, OriginalColumnList);
-                if (var16 != null) {
-                    subTableVo.setOriginalForeignKeys(new String[]{var16.getDbFieldName()});
-                    subTableVo.setForeignKeys(new String[]{var16.getDbFieldName()});
+                List<ColumnVo> columnList = new ArrayList<>();
+                List<ColumnVo> OriginalColumnList = new ArrayList<>();
+                OnlCgformField cgformField = this.getFieldByTableName(cgformHead.getId(), columnList, OriginalColumnList);
+                if (cgformField != null) {
+                    subTableVo.setOriginalForeignKeys(new String[]{cgformField.getDbFieldName()});
+                    subTableVo.setForeignKeys(new String[]{cgformField.getDbFieldName()});
                     subTableVo.setColums(columnList);
                     subTableVo.setOriginalColumns(OriginalColumnList);
                     subTableVoList.add(subTableVo);
@@ -1679,6 +1785,109 @@ public class OnlCgformHeadServiceImpl extends ServiceImpl<OnlCgformHeadMapper, O
             columns.add(columnVo);
         }
     }
+
+    private OnlCgformField getFieldByTableName2(String tableName, List<ColumnVo> columns, List<ColumnVo> originalColumns) {
+        // 获取表下的字段
+        LambdaQueryWrapper<OnlCgformField> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(OnlCgformField::getCgformHeadId, tableName);
+        queryWrapper.orderByAsc(OnlCgformField::getOrderNum);
+        List<OnlCgformField> dbFormFieldList = fieldService.list(queryWrapper);
+
+        OnlCgformField formField = null;
+        for (OnlCgformField dbFormField : dbFormFieldList) {
+
+            ColumnVo columnVo = new ColumnVo();
+            if (oConvertUtils.isNotEmpty(dbFormField.getMainTable())) {
+                formField = dbFormField;
+            }
+
+            columnVo.setFieldLength(dbFormField.getFieldLength());
+            columnVo.setFieldHref(dbFormField.getFieldHref());
+            columnVo.setFieldValidType(dbFormField.getFieldValidType());
+            columnVo.setFieldDefault(dbFormField.getDbDefaultVal());
+            columnVo.setFieldShowType(dbFormField.getFieldShowType());
+            columnVo.setFieldOrderNum(dbFormField.getOrderNum());
+            columnVo.setIsKey(dbFormField.getDbIsKey() == 1 ? "Y" : "N");
+            columnVo.setIsShow(dbFormField.getIsShowForm() == 1 ? "Y" : "N");
+            columnVo.setIsShowList(dbFormField.getIsShowList() == 1 ? "Y" : "N");
+            columnVo.setIsQuery(dbFormField.getIsQuery() == 1 ? "Y" : "N");
+            columnVo.setQueryMode(dbFormField.getQueryMode());
+            columnVo.setDictField(dbFormField.getDictField());
+            columnVo.setDictTable(dbFormField.getDictTable());
+            columnVo.setDictText(dbFormField.getDictText());
+            columnVo.setFieldDbName(dbFormField.getDbFieldName());
+            columnVo.setFieldName(oConvertUtils.camelName(dbFormField.getDbFieldName()));
+            columnVo.setFiledComment(dbFormField.getDbFieldTxt());
+            columnVo.setFieldDbType(dbFormField.getDbType());
+            columnVo.setFieldType(this.convertType(dbFormField.getDbType()));
+            columnVo.setClassType(dbFormField.getFieldShowType());
+            columnVo.setClassType_row(dbFormField.getFieldShowType());
+            // 字段是否为空
+            if (dbFormField.getDbIsNull() != 0 && !"*".equals(dbFormField.getFieldValidType()) && !"1".equals(dbFormField.getFieldMustInput())) {
+                columnVo.setNullable("Y");
+            } else {
+                columnVo.setNullable("N");
+            }
+
+            if ("switch".equals(dbFormField.getFieldShowType())) {
+                if (oConvertUtils.isNotEmpty(dbFormField.getFieldExtendJson())) {
+                    columnVo.setDictField(dbFormField.getFieldExtendJson());
+                } else {
+                    columnVo.setDictField("is_open");
+                }
+            }
+
+            Map<String,Object> extendParams = new HashMap<>();
+            JSONObject jsonObject;
+            if (StringUtils.isNotBlank(dbFormField.getFieldExtendJson())) {
+                try {
+                    jsonObject = JSONObject.parseObject(dbFormField.getFieldExtendJson());
+                    if (jsonObject != null) {
+                        extendParams.putAll(jsonObject.getInnerMap());
+                    }
+                } catch (JSONException e) {
+                }
+            }
+
+            columnVo.setExtendParams(extendParams);
+
+            if ("popup".equals(dbFormField.getFieldShowType())) {
+                boolean popupMulti = true;
+                Object flag = extendParams.get("popupMulti");
+                if (flag != null) {
+                    popupMulti = (boolean)flag;
+                }
+
+                extendParams.put("popupMulti", popupMulti);
+            }
+
+            columnVo.setSort("1".equals(dbFormField.getSortFlag()) ? "Y" : "N");
+            columnVo.setReadonly(Integer.valueOf(1).equals(dbFormField.getIsReadOnly()) ? "Y" : "N");
+
+            if (oConvertUtils.isNotEmpty(dbFormField.getFieldDefaultValue()) &&
+                    !dbFormField.getFieldDefaultValue().trim().startsWith("${") &&
+                    !dbFormField.getFieldDefaultValue().trim().startsWith("#{") &&
+                    !dbFormField.getFieldDefaultValue().trim().startsWith("{{")) {
+                columnVo.setDefaultVal(dbFormField.getFieldDefaultValue());
+            }
+
+            if (("file".equals(dbFormField.getFieldShowType()) ||
+                    "image".equals(dbFormField.getFieldShowType())) &&
+                    oConvertUtils.isNotEmpty(dbFormField.getFieldExtendJson())) {
+                jsonObject = JSONObject.parseObject(dbFormField.getFieldExtendJson());
+                if (oConvertUtils.isNotEmpty(jsonObject.getString("uploadnum"))) {
+                    columnVo.setUploadnum(jsonObject.getString("uploadnum"));
+                }
+            }
+
+            originalColumns.add(columnVo);
+            boolean isShow = dbFormField.getIsShowForm() == 1 && dbFormField.getIsShowList() == 1 && dbFormField.getIsQuery() == 1;
+            if (isShow) {
+                columns.add(columnVo);
+            }
+        }
+        return formField;
+    }
     //endregion
 
     private String convertType(String type) {

+ 1 - 1
tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/entity/${entityName}Task.javai

@@ -34,7 +34,7 @@ public class ${entityName}Task implements Serializable {
 
 <#-- excel注解 忽略字段 -->
 <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']>
-<#list originalColumns as po>
+<#list taskColumns as po>
 <#if po.fieldGroup='common'>
   <#-- 生成字典Code -->
   <#assign list_field_dictCode="">

+ 422 - 0
tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/${entityName}TaskList.vuei

@@ -0,0 +1,422 @@
+<#include "/common/utils.ftl">
+<template>
+  <a-card :bordered="false">
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+<#t>
+<#-- ============== 变量定义 ============== -->
+<#t>
+<#-- 查询字段显示个数,超过隐藏 -->
+<#assign query_field_no=0>
+<#-- 查询条件是否显示 是:"Y";否:"N" -->
+<#assign query_flag=false>
+<#-- 是否需要,字典 -->
+<#assign list_need_dict=false>
+<#-- 是否需要,种类 -->
+<#assign list_need_category=false>
+<#-- 是否需要,省市区 -->
+<#assign list_need_pca=false>
+<#-- 是否需要,开关  -->
+<#assign list_need_switch=false>
+<#-- 是否需要,缩进  -->
+<#assign indent_flag=false>
+<#-- 缩进宏代码  -->
+<#macro indent>
+<#if indent_flag=true>  </#if><#t>
+</#macro>
+
+<#-- 开始-遍历字段 -->
+<#list taskColumns as po>
+<#if po.isQuery=='Y'>
+<#t>
+<#-- 开始-字段一列 -->
+<#assign query_flag=true>
+  <#-- 超过指定查询字段数,折叠剩余查询字段  -->
+  <#if query_field_no==2>
+    <#assign indent_flag=true>
+          <template v-if="toggleSearchStatus">
+  </#if>
+  <#-- 开始-字段的字典值 -->
+  <#assign query_field_dictCode="">
+  <#if po.dictTable?default("")?trim?length gt 1>
+    <#assign query_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
+  <#elseif po.dictField?default("")?trim?length gt 1>
+    <#assign query_field_dictCode="${po.dictField}">
+  </#if>
+  <#-- 结束-字段的字典值 -->
+  <#if po.queryMode=='single'>
+          <@indent/><a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <@indent/><a-form-item label="${po.filedComment}">
+            <#if po.classType=='sel_search'>
+              <@indent/><j-search-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dict="${po.dictTable},${po.dictText},${po.dictField}"/>
+            <#elseif po.classType=='sel_user'>
+              <@indent/><j-select-user-by-dep placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
+            <#elseif po.classType=='switch'>
+              <@indent/><j-switch placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" <#if po.dictField!= 'is_open'>:options="${po.dictField}"</#if> query></j-switch>
+            <#elseif po.classType=='sel_depart'>
+              <@indent/><j-select-depart placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"/>
+            <#elseif po.classType=='list_multi'>
+              <@indent/><j-multi-select-tag placeholder="请选择${po.filedComment}" dictCode="${query_field_dictCode?default("")}" v-model="queryParam.${po.fieldName}"/>
+            <#elseif po.classType=='cat_tree'>
+              <@indent/><j-category-select placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" pcode="${po.dictField?default("")}"/>
+            <#elseif po.classType=='date'>
+              <@indent/><j-date placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
+            <#elseif po.classType=='datetime'>
+              <@indent/><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}"></j-date>
+            <#elseif po.classType=='pca'>
+              <@indent/><j-area-linkage type="cascader" v-model="queryParam.${po.fieldName}" placeholder="请选择省市区"/>
+            <#elseif po.classType=='popup'>
+              <@indent/><j-popup placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" code="${po.dictTable}" org-fields="${po.dictField}" dest-fields="${po.dictText}" :field="getPopupField('${po.dictText}')" :multi="${po.extendParams.popupMulti?c}"/>
+            <#elseif po.classType=='list' || po.classType=='radio' || po.classType=='checkbox'>
+              <#--  开始-下拉或是单选 判断数据字典是表字典还是普通字典 -->
+              <#if po.dictTable?default("")?trim?length gt 1>
+              <@indent/><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictTable},${po.dictText},${po.dictField}"/>
+              <#elseif po.dictField?default("")?trim?length gt 1>
+              <@indent/><j-dict-select-tag placeholder="请选择${po.filedComment}" v-model="queryParam.${po.fieldName}" dictCode="${po.dictField}"/>
+              <#else>
+              <@indent/><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
+              </#if>
+              <#--  结束-下拉或是单选 判断数据字典是表字典还是普通字典 -->
+            <#else>
+              <@indent/><a-input placeholder="请输入${po.filedComment}" v-model="queryParam.${po.fieldName}"></a-input>
+            </#if>
+            <@indent/></a-form-item>
+          <@indent/></a-col>
+  <#else>
+          <@indent/><a-col :xl="10" :lg="11" :md="12" :sm="24">
+            <@indent/><a-form-item label="${po.filedComment}">
+      <#if po.classType=='date'>
+              <@indent/><j-date placeholder="请选择开始日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
+              <@indent/><span class="query-group-split-cust"></span>
+              <@indent/><j-date placeholder="请选择结束日期" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
+      <#elseif po.classType=='datetime'>
+              <@indent/><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></j-date>
+              <@indent/><span class="query-group-split-cust"></span>
+              <@indent/><j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></j-date>
+      <#else>
+              <@indent/><a-input placeholder="请输入最小值" class="query-group-cust" v-model="queryParam.${po.fieldName}_begin"></a-input>
+              <@indent/><span class="query-group-split-cust"></span>
+              <@indent/><a-input placeholder="请输入最大值" class="query-group-cust" v-model="queryParam.${po.fieldName}_end"></a-input>
+      </#if>
+            <@indent/></a-form-item>
+          <@indent/></a-col>
+  </#if>
+<#assign query_field_no=query_field_no+1>
+</#if>
+<#-- 结束-字段一列 -->
+<#t>
+<#-- 开始-字段字典 -->
+<#if !list_need_dict && po.fieldShowType!='popup' && po.dictField?default("")?trim?length gt 1>
+<#assign list_need_dict=true>
+</#if>
+<#-- 结束-字段字典 -->
+<#-- 开始-字段树形 -->
+<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
+<#assign list_need_category=true>
+</#if>
+<#-- 结束-字段树形 -->
+<#-- 开始-字段省市区 -->
+<#if po.classType=='pca'>
+<#assign list_need_pca=true>
+</#if>
+<#-- 结束-字段省市区 -->
+<#-- 开始-字段开关 -->
+<#if po.classType=='switch'>
+<#assign list_need_switch=true>
+</#if>
+<#-- 结束-字段开关 -->
+</#list>
+<#-- 结束-遍历字段 -->
+<#t>
+
+<#if indent_flag=true>
+          </template>
+</#if>
+<#t>
+<#-- 开始-查询按钮 -->
+<#if query_flag>
+          <a-col :xl="6" :lg="7" :md="8" :sm="24">
+            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
+              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
+              <a @click="handleToggleSearch" style="margin-left: 8px">
+                {{ toggleSearchStatus ? '收起' : '展开' }}
+                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
+              </a>
+            </span>
+          </a-col>
+</#if>
+<#-- 结束-查询按钮 -->
+        </a-row>
+      </a-form>
+    </div>
+    <!-- 查询区域-END -->
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator">
+      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('${tableVo.ftlDescription}')">导出</a-button>
+      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+      <!-- 高级查询区域 -->
+      <j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        <#if (tableVo.extendParams.scroll)! == '1'>
+        :scroll="{x:true}"
+        </#if>
+        bordered
+        rowKey="id"
+        :columns="columns"
+        :dataSource="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        class="j-table-force-nowrap"
+        @change="handleTableChange">
+
+        <template slot="htmlSlot" slot-scope="text">
+          <div v-html="text"></div>
+        </template>
+        <template slot="imgSlot" slot-scope="text,record">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
+          <img v-else :src="getImgView(text)" :preview="record.id" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
+        </template>
+        <#if list_need_pca>
+        <template slot="pcaSlot" slot-scope="text">
+          <div>{{ getPcaText(text) }}</div>
+        </template>
+        </#if>
+        <template slot="fileSlot" slot-scope="text">
+          <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
+          <a-button
+            v-else
+            :ghost="true"
+            type="primary"
+            icon="download"
+            size="small"
+            @click="downloadFile(text)">
+            下载
+          </a-button>
+        </template>
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a @click="handleDetail(record)">详情</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+
+      </a-table>
+    </div>
+    <#-- 使用格式化工具类转换 -->
+    <${Format.humpToShortbar(entityName)}-modal ref="modalForm" @ok="modalFormOk"></${Format.humpToShortbar(entityName)}-modal>
+  </a-card>
+</template>
+
+<script>
+
+  import '@/assets/less/TableExpand.less'
+  import { mixinDevice } from '@/utils/mixin'
+  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+  import ${entityName}Modal from './modules/${entityName}Modal'
+
+  <#if list_need_category>
+  import { loadCategoryData } from '@/api/api'
+  </#if>
+  <#if list_need_dict>
+  import {filterMultiDictText} from '@/components/dict/JDictSelectUtil'
+  </#if>
+  <#if list_need_pca>
+  import Area from '@/components/_util/Area'
+  </#if>
+
+  export default {
+    name: '${entityName}List',
+    mixins:[JeecgListMixin, mixinDevice],
+    components: {
+      ${entityName}Modal
+    },
+    data () {
+      return {
+        description: '${tableVo.ftlDescription}管理页面',
+        // 表头
+        columns: [
+          {
+            title: '#',
+            dataIndex: '',
+            key:'rowIndex',
+            width:60,
+            align:"center",
+            customRender:function (t,r,index) {
+              return parseInt(index)+1;
+            }
+          },
+  <#-- 表字段定义 -->
+  <#list taskColumns as po>
+  <#if po.isShowList =='Y' && po.fieldName !='id'>
+          {
+            title:'${po.filedComment}',
+            align:"center",
+            <#-- 排序 -->
+            <#if po.sort=='Y'>
+            sorter: true,
+            </#if>
+            <#if po.classType=='date'>
+            dataIndex: '${po.fieldName}',
+            customRender:function (text) {
+              return !text?"":(text.length>10?text.substr(0,10):text)
+            }
+            <#elseif po.fieldDbType=='Blob'>
+            dataIndex: '${po.fieldName}String'
+            <#-- 富文本 -->
+            <#elseif po.classType=='umeditor'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'htmlSlot'}
+            <#elseif po.classType=='pca'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'pcaSlot'}
+            <#elseif po.classType=='file'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'fileSlot'}
+            <#elseif po.classType=='image'>
+            dataIndex: '${po.fieldName}',
+            scopedSlots: {customRender: 'imgSlot'}
+            <#elseif po.classType=='switch'>
+            dataIndex: '${po.fieldName}',
+            customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : ''),
+            <#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user'>
+            dataIndex: '${po.fieldName}_dictText'
+            <#elseif po.classType=='cat_tree'>
+            <#if list_need_category>
+            dataIndex: '${po.fieldName}',
+            customRender: (text) => (text ? filterMultiDictText(this.dictOptions['${po.fieldName}'], text) : '')
+            <#else>
+            dataIndex: '${po.fieldName}',
+            customRender: (text, record) => (text ? record['${dashedToCamel(po.dictText)}'] : '')
+            </#if>
+      <#else>
+            dataIndex: '${po.fieldName}'
+      </#if>
+          },
+     </#if>
+     </#list>
+          {
+            title: '操作',
+            dataIndex: 'action',
+            align:"center",
+            <#if (tableVo.extendParams.scroll)! == '1'>
+            fixed:"right",
+            width:147,
+            </#if>
+            scopedSlots: { customRender: 'action' }
+          }
+        ],
+        url: {
+          list: "/${entityPackage}/${entityName?uncap_first}/list",
+          delete: "/${entityPackage}/${entityName?uncap_first}/delete",
+          deleteBatch: "/${entityPackage}/${entityName?uncap_first}/deleteBatch",
+          exportXlsUrl: "/${entityPackage}/${entityName?uncap_first}/exportXls",
+          importExcelUrl: "${entityPackage}/${entityName?uncap_first}/importExcel",
+        },
+        dictOptions:{},
+        <#-- 省市区 -->
+        <#if list_need_pca>
+        pcaData:'',
+        </#if>
+        superFieldList:[],
+      }
+    },
+    created() {
+    <#if list_need_pca>
+      this.pcaData = new Area()
+    </#if>
+    <#if list_need_switch>
+    <#list taskColumns as po>
+    <#if po.classType=='switch'>
+      <#assign switch_extend_arr=['Y','N']>
+      <#if po.dictField?default("")?contains("[")>
+        <#assign switch_extend_arr=po.dictField?eval>
+      </#if>
+      <#list switch_extend_arr as a>
+       <#if a_index == 0>
+       <#assign switch_extend_arr1=a>
+       <#else>
+       <#assign switch_extend_arr2=a>
+       </#if>
+      </#list>
+      this.$set(this.dictOptions, '${po.fieldName}', [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
+    </#if>
+    </#list>
+    </#if>
+    this.getSuperFieldList();
+    },
+    computed: {
+      importExcelUrl: function(){
+        <#noparse>return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;</#noparse>
+      },
+    },
+    methods: {
+    <#if list_need_pca>
+      getPcaText(code){
+        return this.pcaData.getText(code);
+      },
+    </#if>
+      initDictConfig(){
+      <#list taskColumns as po>
+      <#if (po.isQuery=='Y' || po.isShowList=='Y') && po.classType!='popup'>
+        <#if po.classType=='cat_tree' && list_need_category==true>
+        loadCategoryData({code:'${po.dictField?default("")}'}).then((res) => {
+          if (res.success) {
+            this.$set(this.dictOptions, '${po.fieldName}', res.result)
+          }
+        })
+        </#if>
+      </#if>
+      </#list>
+      },
+      <#-- 高级查询 -->
+      getSuperFieldList(){
+        let fieldList=[];
+         <#list taskColumns as po>
+        fieldList.push(${superQueryFieldList(po)})
+         </#list>
+        this.superFieldList = fieldList
+      }
+    }
+  }
+</script>
+<style scoped>
+  @import '~@assets/less/common.less';
+</style>

+ 217 - 0
tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskForm.vuei

@@ -0,0 +1,217 @@
+
+<#include "/common/utils.ftl">
+<template>
+  <a-spin :spinning="confirmLoading">
+    <j-form-container :disabled="formDisabled">
+      <a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
+        <a-row>
+<#-- Popup弹框 -->
+<#assign form_popup = false>
+<#-- 分类字典树 -->
+<#assign form_cat_tree = false>
+<#assign form_cat_back = "">
+<#t>
+<#-- 一行一列 字段所占区域 -->
+<#assign form_span = 24>
+<#if tableVo.fieldRowNum==2>
+<#assign form_span = 12>
+<#elseif tableVo.fieldRowNum==3>
+<#assign form_span = 8>
+<#elseif tableVo.fieldRowNum==4>
+<#assign form_span = 6>
+</#if>
+<#-- 开始-遍历字段 -->
+<#list taskColumns as po>
+<#t>
+<#if po.isShow =='Y' && po.fieldName != 'id'>
+  <#assign form_field_dictCode="">
+  <#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
+    <#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
+  <#elseif po.dictField?default("")?trim?length gt 1>
+    <#assign form_field_dictCode="${po.dictField}">
+  </#if>
+          <a-col :span="${form_span}">
+            <a-form-model-item label="${po.filedComment}" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="${autoStringSuffixForModel(po)}">
+  <#if po.classType =='date'>
+              <j-date placeholder="请选择${po.filedComment}" v-model="model.${po.fieldName}"  style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='datetime'>
+              <j-date placeholder="请选择${po.filedComment}"  v-model="model.${po.fieldName}" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='time'>
+              <j-time placeholder="请选择${po.filedComment}"  v-model="model.${po.fieldName}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='popup'>
+      <#assign form_popup=true>
+              <j-popup
+                v-model="model.${po.fieldName}"
+                field="${po.fieldName}"
+                org-fields="${po.dictField}"
+                dest-fields="${Format.underlineToHump(po.dictText)}"
+                code="${po.dictTable}"
+                :multi="${po.extendParams.popupMulti?c}"
+                @input="popupCallback"
+                <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='sel_depart'>
+              <j-select-depart v-model="model.${po.fieldName}" multi <#if po.readonly=='Y'>disabled</#if> />
+  <#elseif po.classType =='switch'>
+              <j-switch v-model="model.${po.fieldName}" <#if po.dictField != 'is_open'>:options="${po.dictField}"</#if> <#if po.readonly=='Y'>disabled</#if>></j-switch>
+  <#elseif po.classType =='pca'>
+             <j-area-linkage type="cascader" v-model="model.${po.fieldName}" placeholder="请输入省市区" <#if po.readonly=='Y'>disabled</#if> />
+  <#elseif po.classType =='markdown'>
+              <j-markdown-editor v-model="model.${autoStringSuffixForModel(po)}" id="${po.fieldName}"></j-markdown-editor>
+  <#elseif po.classType =='password'>
+              <a-input-password v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='sel_user'>
+              <j-select-user-by-dep v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType =='textarea'>
+              <a-textarea v-model="model.${autoStringSuffixForModel(po)}" rows="4" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='list' || po.classType=='radio'>
+              <j-dict-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='list_multi' || po.classType=='checkbox'>
+              <j-multi-select-tag type="${po.classType}" v-model="model.${po.fieldName}" dictCode="${form_field_dictCode}" placeholder="请选择${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='sel_search'>
+              <j-search-select-tag v-model="model.${po.fieldName}" dict="${form_field_dictCode}" <#if po.readonly=='Y'>disabled</#if> />
+  <#elseif po.classType=='cat_tree'>
+      <#assign form_cat_tree = true>
+              <j-category-select v-model="model.${po.fieldName}" pcode="${po.dictField?default("")}" placeholder="请选择${po.filedComment}" <#if po.dictText?default("")?trim?length gt 1>back="${dashedToCamel(po.dictText)}" @change="handleCategoryChange"</#if> <#if po.readonly=='Y'>disabled</#if>/>
+      <#if po.dictText?default("")?trim?length gt 1>
+        <#assign form_cat_back = "${po.dictText}">
+      </#if>
+  <#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
+              <a-input-number v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" style="width: 100%" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.classType=='file'>
+              <j-upload v-model="model.${po.fieldName}"  <#if po.readonly=='Y'>disabled</#if> <#if po.uploadnum??>:number=${po.uploadnum}</#if>></j-upload>
+  <#elseif po.classType=='image'>
+              <j-image-upload isMultiple <#if po.uploadnum??>:number=${po.uploadnum}</#if> v-model="model.${po.fieldName}" <#if po.readonly=='Y'>disabled</#if>></j-image-upload>
+  <#elseif po.classType=='umeditor'>
+              <j-editor v-model="model.${autoStringSuffixForModel(po)}" <#if po.readonly=='Y'>disabled</#if>/>
+  <#elseif po.fieldDbType=='Blob'>
+              <a-input v-model="model.${autoStringSuffixForModel(po)}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if>></a-input>
+  <#elseif po.classType == 'sel_tree'>
+              <j-tree-select
+                ref="treeSelect"
+                placeholder="请选择${po.filedComment}"
+                v-model="model.${po.fieldName}"
+                <#if po.dictText??>
+                <#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
+                dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
+                <#elseif po.dictText?split(',')[1]??>
+                pidField="${po.dictText?split(',')[1]}"
+                <#elseif po.dictText?split(',')[3]??>
+                hasChildField="${po.dictText?split(',')[3]}"
+                </#if>
+                </#if>
+                pidValue="${po.dictField}"
+                <#if po.readonly=='Y'>disabled</#if>>
+              </j-tree-select>
+  <#else>
+              <a-input v-model="model.${po.fieldName}" placeholder="请输入${po.filedComment}" <#if po.readonly=='Y'>disabled</#if> ></a-input>
+  </#if>
+            </a-form-model-item>
+          </a-col>
+</#if>
+</#list>
+<#-- 结束-遍历字段 -->
+        </a-row>
+      </a-form-model>
+    </j-form-container>
+  </a-spin>
+</template>
+
+<script>
+
+  import { httpAction, getAction } from '@/api/manage'
+  import { validateDuplicateValue } from '@/utils/util'
+
+  export default {
+    name: '${entityName}TaskForm',
+    components: {
+    },
+    props: {
+      //表单禁用
+      disabled: {
+        type: Boolean,
+        default: false,
+        required: false
+      }
+    },
+    data () {
+      return {
+        model:{
+            <#include "/common/init/initValue.ftl">
+         },
+        labelCol: {
+          xs: { span: 24 },
+          sm: { span: 5 },
+        },
+        wrapperCol: {
+          xs: { span: 24 },
+          sm: { span: 16 },
+        },
+        confirmLoading: false,
+        <#include "/common/validatorRulesTemplate/main.ftl">
+        url: {
+          add: "/${entityPackage}/${entityName?uncap_first}/add",
+          edit: "/${entityPackage}/${entityName?uncap_first}/edit",
+          queryById: "/${entityPackage}/${entityName?uncap_first}/queryById"
+        }
+      }
+    },
+    computed: {
+      formDisabled(){
+        return this.disabled
+      },
+
+    },
+    created () {
+       //备份model原始值
+      this.modelDefault = JSON.parse(JSON.stringify(this.model));
+    },
+    methods: {
+      add () {
+        this.edit(this.modelDefault);
+      },
+      edit (record) {
+        this.model = Object.assign({}, record);
+        this.visible = true;
+      },
+      submitForm () {
+        const that = this;
+        // 触发表单验证
+        this.$refs.form.validate(valid => {
+          if (valid) {
+            that.confirmLoading = true;
+            let httpurl = '';
+            let method = '';
+            if(!this.model.id){
+              httpurl+=this.url.add;
+              method = 'post';
+            }else{
+              httpurl+=this.url.edit;
+               method = 'put';
+            }
+            httpAction(httpurl,this.model,method).then((res)=>{
+              if(res.success){
+                that.$message.success(res.message);
+                that.$emit('ok');
+              }else{
+                that.$message.warning(res.message);
+              }
+            }).finally(() => {
+              that.confirmLoading = false;
+            })
+          }
+         
+        })
+      },
+       <#if form_popup>
+      popupCallback(value,row){
+         this.model = Object.assign(this.model, row);
+      },
+       </#if>
+      <#if form_cat_tree>
+      handleCategoryChange(value,backObj){
+         this.model = Object.assign(this.model, backObj);
+      }
+      </#if>
+    }
+  }
+</script>

+ 70 - 0
tnc-system/src/main/resources/jeecg/code-template-online/default/two/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}TaskModal.vuei

@@ -0,0 +1,70 @@
+
+<#include "/common/utils.ftl">
+<#assign modal_width = 800>
+<#if tableVo.fieldRowNum==2>
+  <#assign modal_width = 896>
+<#elseif tableVo.fieldRowNum==3>
+  <#assign modal_width = 1024>
+<#elseif tableVo.fieldRowNum==4>
+  <#assign modal_width = 1280>
+</#if>
+<template>
+  <j-modal
+    :title="title"
+    :width="width"
+    :visible="visible"
+    switchFullscreen
+    @ok="handleOk"
+    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
+    @cancel="handleCancel"
+    cancelText="关闭">
+    <${Format.humpToShortbar(entityName)}-task-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></${Format.humpToShortbar(entityName)}-task-form>
+  </j-modal>
+</template>
+
+<script>
+
+  import ${entityName}TaskForm from './${entityName}TaskForm'
+  export default {
+    name: '${entityName}TaskModal',
+    components: {
+      ${entityName}TaskForm
+    },
+    data () {
+      return {
+        title:'',
+        width:${modal_width},
+        visible: false,
+        disableSubmit: false
+      }
+    },
+    methods: {
+      add () {
+        this.visible=true
+        this.$nextTick(()=>{
+          this.$refs.realForm.add();
+        })
+      },
+      edit (record) {
+        this.visible=true
+        this.$nextTick(()=>{
+          this.$refs.realForm.edit(record);
+        })
+      },
+      close () {
+        this.$emit('close');
+        this.visible = false;
+      },
+      handleOk () {
+        this.$refs.realForm.submitForm();
+      },
+      submitCallback(){
+        this.$emit('ok');
+        this.visible = false;
+      },
+      handleCancel () {
+        this.close()
+      }
+    }
+  }
+</script>