Browse Source

优化生成树表

SpringSunYY 5 tháng trước cách đây
mục cha
commit
06e22faabd

+ 4 - 0
ruoyi-ui/src/utils/ruoyi.js

@@ -155,6 +155,10 @@ export function mergeRecursive(source, target) {
  * @param {*} children 孩子节点字段 默认 'children'
  * @param {*} children 孩子节点字段 默认 'children'
  */
  */
 export function handleTree(data, id, parentId, children) {
 export function handleTree(data, id, parentId, children) {
+  // 容错:确保可迭代
+  if (!Array.isArray(data)) {
+    data = [];
+  }
   let config = {
   let config = {
     id: id || 'id',
     id: id || 'id',
     parentId: parentId || 'parentId',
     parentId: parentId || 'parentId',

+ 25 - 11
ruoyi_generator/controller/gen.py

@@ -131,7 +131,7 @@ def update_gen_table(dto: GenTablePO):
         if hasattr(gen_table, attr):
         if hasattr(gen_table, attr):
             setattr(gen_table, attr, getattr(dto, attr))
             setattr(gen_table, attr, getattr(dto, attr))
     
     
-    # 处理 options 字段和 parentMenuId
+    # 处理 options 字段(包含树配置与菜单父节点)和 parentMenuId
     import json
     import json
     options_dict = {}
     options_dict = {}
     
     
@@ -146,19 +146,33 @@ def update_gen_table(dto: GenTablePO):
             print(f"解析 options 字段出错: {e}")
             print(f"解析 options 字段出错: {e}")
             options_dict = {}
             options_dict = {}
     
     
-    # 检查 params 中是否有 parentMenuId(前端可能通过 params 传递)
+    # 合并树配置(来自 dto 的 treeCode/treeParentCode/treeName)
+    # 兼容:如果前端把树配置直接放在 dto 顶层,则这里写入 options
+    if getattr(dto, 'tree_code', None):
+        options_dict['treeCode'] = dto.tree_code
+    if getattr(dto, 'tree_parent_code', None):
+        options_dict['treeParentCode'] = dto.tree_parent_code
+    if getattr(dto, 'tree_name', None):
+        options_dict['treeName'] = dto.tree_name
+
+    # 检查 params 中是否有 parentMenuId 或树配置(部分前端可能通过 params 传递)
     if hasattr(dto, 'params') and dto.params:
     if hasattr(dto, 'params') and dto.params:
-        if isinstance(dto.params, dict) and 'parentMenuId' in dto.params:
-            options_dict['parentMenuId'] = dto.params.get('parentMenuId')
+        if isinstance(dto.params, dict):
+            if 'parentMenuId' in dto.params:
+                options_dict['parentMenuId'] = dto.params.get('parentMenuId')
+            if 'treeCode' in dto.params:
+                options_dict['treeCode'] = dto.params.get('treeCode')
+            if 'treeParentCode' in dto.params:
+                options_dict['treeParentCode'] = dto.params.get('treeParentCode')
+            if 'treeName' in dto.params:
+                options_dict['treeName'] = dto.params.get('treeName')
     
     
-    # 如果 options_dict 中有 parentMenuId,更新 options 字段
-    if 'parentMenuId' in options_dict:
-        gen_table.options = json.dumps(options_dict, ensure_ascii=False)
-        gen_table.parent_menu_id = options_dict.get('parentMenuId')
-        print(f"设置 parentMenuId: {options_dict.get('parentMenuId')}, options: {gen_table.options}")
-    elif options_dict:
-        # 即使没有 parentMenuId,也要保存其他 options
+    # 更新 options 字段(无论是否包含 parentMenuId,都要保存)
+    if options_dict is not None:
         gen_table.options = json.dumps(options_dict, ensure_ascii=False)
         gen_table.options = json.dumps(options_dict, ensure_ascii=False)
+        if 'parentMenuId' in options_dict:
+            gen_table.parent_menu_id = options_dict.get('parentMenuId')
+            print(f"设置 parentMenuId: {options_dict.get('parentMenuId')}, options: {gen_table.options}")
 
 
     # 特别处理columns字段
     # 特别处理columns字段
     if hasattr(dto, 'columns') and dto.columns is not None:
     if hasattr(dto, 'columns') and dto.columns is not None:

+ 175 - 10
ruoyi_generator/util.py

@@ -20,11 +20,70 @@ def to_underscore(name: str) -> str:
     Returns:
     Returns:
         str: 下划线命名的字符串
         str: 下划线命名的字符串
     """
     """
+    # 处理 None 或非字符串类型
+    if name is None:
+        return ""
+    if not isinstance(name, str):
+        return str(name)
     # 在大写字母前添加下划线,然后转为小写
     # 在大写字母前添加下划线,然后转为小写
     s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
     s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
 
 
 
 
+def capitalize_first(name: str) -> str:
+    """
+    将字符串首字母大写
+    
+    Args:
+        name (str): 输入字符串
+        
+    Returns:
+        str: 首字母大写的字符串
+    """
+    if name is None or not isinstance(name, str) or len(name) == 0:
+        return ""
+    return name[0].upper() + name[1:] if len(name) > 1 else name.upper()
+
+
+def get_tree_column_index(column, all_columns):
+    """
+    计算树表中列的索引(排除主键列)
+    
+    Args:
+        column: 当前列对象
+        all_columns: 所有列的列表
+        
+    Returns:
+        int: 列在树表中的索引
+    """
+    index = 0
+    for col in all_columns:
+        if col.is_list == '1' and not (col.is_pk == '1'):
+            # 使用 column_id 或 column_name 来比较列对象
+            if hasattr(column, 'column_id') and hasattr(col, 'column_id'):
+                if col.column_id == column.column_id:
+                    return index
+            elif hasattr(column, 'column_name') and hasattr(col, 'column_name'):
+                if col.column_name == column.column_name:
+                    return index
+            index += 1
+    return 0
+
+
+def get_filtered_columns(columns, filter_func):
+    """
+    过滤列并返回过滤后的列表
+    
+    Args:
+        columns: 所有列的列表
+        filter_func: 过滤函数,接受一个列对象,返回True表示保留
+        
+    Returns:
+        list: 过滤后的列列表
+    """
+    return [col for col in columns if filter_func(col)]
+
+
 class GenUtils:
 class GenUtils:
     @staticmethod
     @staticmethod
     def get_file_name(template_file: str, table: GenTable) -> str:
     def get_file_name(template_file: str, table: GenTable) -> str:
@@ -74,7 +133,7 @@ class GenUtils:
             # PO文件放在 domain/po/ 目录下,使用下划线命名法
             # PO文件放在 domain/po/ 目录下,使用下划线命名法
             po_name = f"{to_underscore(table.class_name)}_po"
             po_name = f"{to_underscore(table.class_name)}_po"
             return f"{module_path}/domain/po/{po_name}.py"
             return f"{module_path}/domain/po/{po_name}.py"
-        elif 'vue/index.vue' in template_file or 'vue/index-tree.vue' in template_file:
+        elif 'vue/index.vue' in template_file or 'vue/index-tree.vue' in template_file or 'vue/index-sub.vue' in template_file:
             # 无论是树表还是普通表,Vue文件名都是index.vue
             # 无论是树表还是普通表,Vue文件名都是index.vue
             # 使用数据库中的 module_name(前端模块名)
             # 使用数据库中的 module_name(前端模块名)
             frontend_module = table.module_name if table.module_name else GeneratorConfig.model_name
             frontend_module = table.module_name if table.module_name else GeneratorConfig.model_name
@@ -306,6 +365,8 @@ class GenUtils:
         # 根据表类型添加相应的Vue模板
         # 根据表类型添加相应的Vue模板
         if table.tpl_category == 'tree':
         if table.tpl_category == 'tree':
             core_templates.append('vue/index-tree.vue.vm')
             core_templates.append('vue/index-tree.vue.vm')
+        elif table.tpl_category == 'sub':
+            core_templates.append('vue/index-sub.vue.vm')
         else:
         else:
             core_templates.append('vue/index.vue.vm')
             core_templates.append('vue/index.vue.vm')
         
         
@@ -342,7 +403,8 @@ class GenUtils:
                         'tables': None,  # 单个表生成时,tables 为 None
                         'tables': None,  # 单个表生成时,tables 为 None
                         'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                         'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                         'underscore': to_underscore,
                         'underscore': to_underscore,
-                        'get_import_path': GenUtils.get_import_path
+                        'get_import_path': GenUtils.get_import_path,
+                        'get_tree_column_index': get_tree_column_index
                     }
                     }
                     
                     
                     # 使用Jinja2渲染模板
                     # 使用Jinja2渲染模板
@@ -371,16 +433,46 @@ class GenUtils:
                         # 准备模板上下文
                         # 准备模板上下文
                         # table.module_name 是从数据库读取的前端模块名(真正的模块名,用于权限、前端、SQL)
                         # table.module_name 是从数据库读取的前端模块名(真正的模块名,用于权限、前端、SQL)
                         # GeneratorConfig.python_model_name 是 Python 模块名(只用于 Python 后端代码路径)
                         # GeneratorConfig.python_model_name 是 Python 模块名(只用于 Python 后端代码路径)
+                        # 为树表准备过滤后的列列表
+                        if 'index-tree.vue' in relative_path:
+                            # 过滤出满足条件的列
+                            list_cols = [col for col in table.columns if col.is_list and not (col.is_pk == '1') and getattr(col, 'list_index', None) is not None]
+                            query_cols = [col for col in table.columns if col.is_query]
+                            required_cols = [col for col in table.columns if col.is_required]
+                        else:
+                            list_cols = None
+                            query_cols = None
+                            required_cols = None
+                        
                         context = {
                         context = {
                             'table': table,
                             'table': table,
                             'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                             'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                             'underscore': to_underscore,  # 添加自定义过滤器
                             'underscore': to_underscore,  # 添加自定义过滤器
-                            'get_import_path': GenUtils.get_import_path  # 添加导入路径生成函数
+                            'capitalize_first': capitalize_first,  # 添加首字母大写函数
+                            'get_import_path': GenUtils.get_import_path,  # 添加导入路径生成函数
+                            'get_tree_column_index': get_tree_column_index,  # 添加树表列索引计算函数
+                            'list_cols': list_cols,  # 树表的列表列
+                            'query_cols': query_cols,  # 树表的查询列
+                            'required_cols': required_cols  # 树表的必填列
                         }
                         }
                         
                         
                         # 使用Jinja2渲染模板
                         # 使用Jinja2渲染模板
                         template = Template(template_content)
                         template = Template(template_content)
-                        rendered_content = template.render(**context)
+                        # 如果是树表模板,打印列信息用于调试
+                        if 'index-tree.vue' in relative_path:
+                            print(f"[DEBUG] 渲染树表模板前,列信息:")
+                            for col in table.columns:
+                                list_idx = getattr(col, 'list_index', 'NOT_SET')
+                                print(f"  - {col.column_name}: is_list={col.is_list}, is_pk={col.is_pk}, list_index={list_idx} (type={type(list_idx)})")
+                        try:
+                            rendered_content = template.render(**context)
+                        except Exception as e:
+                            import traceback
+                            error_detail = traceback.format_exc()
+                            print(f"[ERROR] 模板渲染失败: {relative_path}")
+                            print(f"[ERROR] 错误信息: {str(e)}")
+                            print(f"[ERROR] 详细堆栈:\n{error_detail}")
+                            raise
                         
                         
                         # 如果是 SQL 模板,恢复原始 module_name(虽然已经强制设置了,但为了安全)
                         # 如果是 SQL 模板,恢复原始 module_name(虽然已经强制设置了,但为了安全)
                         if 'sql/menu.sql' in relative_path:
                         if 'sql/menu.sql' in relative_path:
@@ -593,7 +685,8 @@ class GenUtils:
                             'tables': tables,  # 传入所有表,用于循环注册所有蓝图
                             'tables': tables,  # 传入所有表,用于循环注册所有蓝图
                             'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                             'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                             'underscore': to_underscore,
                             'underscore': to_underscore,
-                            'get_import_path': GenUtils.get_import_path
+                            'get_import_path': GenUtils.get_import_path,
+                            'get_tree_column_index': get_tree_column_index
                         }
                         }
                         
                         
                         # 使用Jinja2渲染模板
                         # 使用Jinja2渲染模板
@@ -615,6 +708,8 @@ class GenUtils:
                 # 根据表类型添加相应的Vue模板
                 # 根据表类型添加相应的Vue模板
                 if table.tpl_category == 'tree':
                 if table.tpl_category == 'tree':
                     current_templates = core_templates + ['vue/index-tree.vue.vm']
                     current_templates = core_templates + ['vue/index-tree.vue.vm']
+                elif table.tpl_category == 'sub':
+                    current_templates = core_templates + ['vue/index-sub.vue.vm']
                 else:
                 else:
                     current_templates = core_templates + ['vue/index.vue.vm']
                     current_templates = core_templates + ['vue/index.vue.vm']
                 
                 
@@ -634,16 +729,44 @@ class GenUtils:
                             # 准备模板上下文
                             # 准备模板上下文
                             # table.module_name 是从数据库读取的前端模块名(真正的模块名,用于权限、前端、SQL)
                             # table.module_name 是从数据库读取的前端模块名(真正的模块名,用于权限、前端、SQL)
                             # GeneratorConfig.python_model_name 是 Python 模块名(只用于 Python 后端代码路径)
                             # GeneratorConfig.python_model_name 是 Python 模块名(只用于 Python 后端代码路径)
+                            # 为树表准备过滤后的列列表
+                            if 'index-tree.vue' in relative_path:
+                                list_cols = [col for col in table.columns if col.is_list and not (col.is_pk == '1') and getattr(col, 'list_index', None) is not None]
+                                query_cols = [col for col in table.columns if col.is_query]
+                                required_cols = [col for col in table.columns if col.is_required]
+                            else:
+                                list_cols = None
+                                query_cols = None
+                                required_cols = None
+                            
                             context = {
                             context = {
                                 'table': table,
                                 'table': table,
                                 'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                                 'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                                 'underscore': to_underscore,  # 添加自定义过滤器
                                 'underscore': to_underscore,  # 添加自定义过滤器
-                                'get_import_path': GenUtils.get_import_path  # 添加导入路径生成函数
+                                'capitalize_first': capitalize_first,  # 添加首字母大写函数
+                                'get_import_path': GenUtils.get_import_path,  # 添加导入路径生成函数
+                                'list_cols': list_cols,  # 树表的列表列
+                                'query_cols': query_cols,  # 树表的查询列
+                                'required_cols': required_cols  # 树表的必填列
                             }
                             }
                             
                             
                             # 使用Jinja2渲染模板
                             # 使用Jinja2渲染模板
                             template = Template(template_content)
                             template = Template(template_content)
-                            rendered_content = template.render(**context)
+                            # 如果是树表模板,打印列信息用于调试
+                            if 'index-tree.vue' in relative_path:
+                                print(f"[DEBUG] 批量渲染树表模板前,列信息:")
+                                for col in table.columns:
+                                    list_idx = getattr(col, 'list_index', 'NOT_SET')
+                                    print(f"  - {col.column_name}: is_list={col.is_list}, is_pk={col.is_pk}, list_index={list_idx} (type={type(list_idx)})")
+                            try:
+                                rendered_content = template.render(**context)
+                            except Exception as e:
+                                import traceback
+                                error_detail = traceback.format_exc()
+                                print(f"[ERROR] 模板渲染失败: {relative_path} (表: {table.table_name})")
+                                print(f"[ERROR] 错误信息: {str(e)}")
+                                print(f"[ERROR] 详细堆栈:\n{error_detail}")
+                                raise
                             
                             
                             # 生成文件名
                             # 生成文件名
                             output_file_name = GenUtils.get_file_name(relative_path, table)
                             output_file_name = GenUtils.get_file_name(relative_path, table)
@@ -776,12 +899,29 @@ class GenUtils:
         if not table.columns:
         if not table.columns:
             return
             return
         
         
+        # 如果是树表,需要排除主键列
+        is_tree = table.tpl_category == 'tree'
+        print(f"[DEBUG] set_column_list_index: 表类型={table.tpl_category}, 是树表={is_tree}, 列数={len(table.columns)}")
+        
         list_index = 0
         list_index = 0
         for column in table.columns:
         for column in table.columns:
-            if column.is_list == '1':
+            # 对于树表,只处理 is_list='1' 且不是主键的列
+            # 对于普通表,处理所有 is_list='1' 的列
+            if column.is_list == '1' or column.is_list == 1:
+                if is_tree and (column.is_pk == '1' or column.is_pk == 1):
+                    # 树表的主键列不设置 list_index(树表中主键列不显示在列表中)
+                    # 设置为 None,但模板中会通过 not (column.is_pk == '1') 过滤掉
+                    setattr(column, 'list_index', None)
+                    print(f"[DEBUG] 树表主键列: {column.column_name}, is_list={column.is_list}, is_pk={column.is_pk}, list_index=None")
+                    continue
                 # 使用 setattr 动态添加属性
                 # 使用 setattr 动态添加属性
                 setattr(column, 'list_index', list_index)
                 setattr(column, 'list_index', list_index)
+                print(f"[DEBUG] 设置列索引: {column.column_name}, is_list={column.is_list}, is_pk={column.is_pk}, list_index={list_index}")
                 list_index += 1
                 list_index += 1
+            else:
+                # 非列表列也设置 list_index 为 None,保持一致性
+                setattr(column, 'list_index', None)
+                print(f"[DEBUG] 非列表列: {column.column_name}, is_list={column.is_list}, list_index=None")
 
 
     @staticmethod
     @staticmethod
     def preview_code(table: GenTable) -> dict:
     def preview_code(table: GenTable) -> dict:
@@ -862,22 +1002,47 @@ class GenUtils:
                     # 准备模板上下文
                     # 准备模板上下文
                     # table.module_name 是从数据库读取的前端模块名(真正的模块名,用于权限、前端、SQL)
                     # table.module_name 是从数据库读取的前端模块名(真正的模块名,用于权限、前端、SQL)
                     # GeneratorConfig.python_model_name 是 Python 模块名(只用于 Python 后端代码路径)
                     # GeneratorConfig.python_model_name 是 Python 模块名(只用于 Python 后端代码路径)
+                    # 为树表准备过滤后的列列表
+                    if 'index-tree.vue' in relative_path:
+                        list_cols = [col for col in table.columns if col.is_list and not (col.is_pk == '1') and getattr(col, 'list_index', None) is not None]
+                        query_cols = [col for col in table.columns if col.is_query]
+                        required_cols = [col for col in table.columns if col.is_required]
+                    else:
+                        list_cols = None
+                        query_cols = None
+                        required_cols = None
+                    
                     context = {
                     context = {
                         'table': table,
                         'table': table,
                         'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                         'datetime': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                         'underscore': to_underscore,  # 添加自定义过滤器
                         'underscore': to_underscore,  # 添加自定义过滤器
-                        'get_import_path': GenUtils.get_import_path  # 添加导入路径生成函数
+                                'capitalize_first': capitalize_first,  # 添加首字母大写函数
+                        'get_import_path': GenUtils.get_import_path,  # 添加导入路径生成函数
+                        'list_cols': list_cols,  # 树表的列表列
+                        'query_cols': query_cols,  # 树表的查询列
+                        'required_cols': required_cols  # 树表的必填列
                     }
                     }
                     
                     
                     # 使用Jinja2渲染模板
                     # 使用Jinja2渲染模板
                     template = Template(template_content)
                     template = Template(template_content)
+                    # 如果是树表模板,打印列信息用于调试
+                    if 'index-tree.vue' in relative_path:
+                        print(f"[DEBUG] 预览树表模板前,列信息:")
+                        for col in table.columns:
+                            list_idx = getattr(col, 'list_index', 'NOT_SET')
+                            print(f"  - {col.column_name}: is_list={col.is_list}, is_pk={col.is_pk}, list_index={list_idx} (type={type(list_idx)})")
                     rendered_content = template.render(**context)
                     rendered_content = template.render(**context)
                     
                     
                     # 存储渲染后的内容
                     # 存储渲染后的内容
                     preview_data[relative_path] = rendered_content
                     preview_data[relative_path] = rendered_content
                 except Exception as e:
                 except Exception as e:
                     # 如果渲染失败,存储错误信息
                     # 如果渲染失败,存储错误信息
-                    preview_data[relative_path] = f"模板渲染失败: {str(e)}"
+                    import traceback
+                    error_detail = traceback.format_exc()
+                    print(f"[ERROR] 模板渲染失败: {relative_path}")
+                    print(f"[ERROR] 错误信息: {str(e)}")
+                    print(f"[ERROR] 详细堆栈:\n{error_detail}")
+                    preview_data[relative_path] = f"模板渲染失败: {str(e)}\n详细错误:\n{error_detail}"
             else:
             else:
                 preview_data[relative_path] = "模板文件不存在"
                 preview_data[relative_path] = "模板文件不存在"
         
         

+ 326 - 173
ruoyi_generator/vm/vue/index-tree.vue.vm

@@ -1,44 +1,68 @@
-{% macro getColumnDictType(column) -%}
-  {%- if column.dict_type != '' -%}{{ column.dict_type }}
-  {%- else -%}null
-  {%- endif -%}
-{%- endmacro %}
-
 <template>
 <template>
   <div class="app-container">
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
     <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
-{% for column in table.columns %}
-{% if column.is_query %}
-      <el-form-item label="{{ column.column_comment }}" prop="{{ underscore(column.java_field) }}">
-  {% if column.html_type == 'input' %}
+{%- for column in table.columns %}
+{%- if column.is_query %}
+{%- set dict_type = column.dict_type if column.dict_type else '' %}
+{%- set attr_name = capitalize_first(column.java_field) %}
+{%- set comment = column.column_comment %}
+{%- if '(' in comment or '(' in comment %}
+{%- if '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- elif '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- endif %}
+{%- endif %}
+  {%- if column.html_type == 'input' %}
+      <el-form-item label="{{ comment }}" prop="{{ underscore(column.java_field) }}">
         <el-input
         <el-input
           v-model="queryParams.{{ underscore(column.java_field) }}"
           v-model="queryParams.{{ underscore(column.java_field) }}"
-          placeholder="请输入{{ column.column_comment }}"
+          placeholder="请输入{{ comment }}"
           clearable
           clearable
           @keyup.enter.native="handleQuery"
           @keyup.enter.native="handleQuery"
         />
         />
-  {% elif column.html_type == 'select' and column.dict_type != '' %}
-        <el-select v-model="queryParams.{{ underscore(column.java_field) }}" placeholder="请选择{{ column.column_comment }}" clearable>
+      </el-form-item>
+  {%- elif (column.html_type == 'select' or column.html_type == 'radio') and dict_type != '' %}
+      <el-form-item label="{{ comment }}" prop="{{ underscore(column.java_field) }}">
+        <el-select v-model="queryParams.{{ underscore(column.java_field) }}" placeholder="请选择{{ comment }}" clearable>
           <el-option
           <el-option
-            v-for="dict in {{ getColumnDictType(column) }}Options"
+            v-for="dict in dict.type.{{ dict_type }}"
             :key="dict.value"
             :key="dict.value"
             :label="dict.label"
             :label="dict.label"
             :value="dict.value"
             :value="dict.value"
           />
           />
         </el-select>
         </el-select>
-  {% elif column.html_type == 'datetime' %}
+      </el-form-item>
+  {%- elif (column.html_type == 'select' or column.html_type == 'radio') and dict_type == '' %}
+      <el-form-item label="{{ comment }}" prop="{{ underscore(column.java_field) }}">
+        <el-select v-model="queryParams.{{ underscore(column.java_field) }}" placeholder="请选择{{ comment }}" clearable>
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+  {%- elif column.html_type == 'datetime' and column.query_type != 'BETWEEN' %}
+      <el-form-item label="{{ comment }}" prop="{{ underscore(column.java_field) }}">
+        <el-date-picker clearable
+          v-model="queryParams.{{ underscore(column.java_field) }}"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择{{ comment }}">
+        </el-date-picker>
+      </el-form-item>
+  {%- elif column.html_type == 'datetime' and column.query_type == 'BETWEEN' %}
+      <el-form-item label="{{ comment }}">
         <el-date-picker
         <el-date-picker
-          v-model="daterange{{ column.java_field }}"
+          v-model="daterange{{ attr_name }}"
+          style="width: 240px"
           value-format="yyyy-MM-dd"
           value-format="yyyy-MM-dd"
           type="daterange"
           type="daterange"
           range-separator="-"
           range-separator="-"
           start-placeholder="开始日期"
           start-placeholder="开始日期"
           end-placeholder="结束日期"
           end-placeholder="结束日期"
         ></el-date-picker>
         ></el-date-picker>
-  {% endif %}
       </el-form-item>
       </el-form-item>
-{% endif %}
-{% endfor %}
+  {%- endif %}
+{%- endif %}
+{%- endfor %}
       <el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <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-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -72,43 +96,80 @@
       v-if="refreshTable"
       v-if="refreshTable"
       v-loading="loading"
       v-loading="loading"
       :data="{{ table.business_name }}List"
       :data="{{ table.business_name }}List"
-      row-key="{{ table.tree_code }}"
+      row-key="{% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %}"
       :default-expand-all="isExpandAll"
       :default-expand-all="isExpandAll"
       :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
       :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
     >
     >
-{% set index = 0 %}
-{% for column in table.columns %}
-{% if column.is_list %}
-  {% if column.is_pk %}
-  {% elif column.html_type == 'datetime' %}
-      <el-table-column label="{{ column.column_comment }}" align="center" v-if="columns[{{ index }}].visible" prop="{{ underscore(column.java_field) }}" width="180">
+{%- for column in table.columns %}
+{%- set java_field = column.java_field %}
+{%- set comment = column.column_comment %}
+{%- if '(' in comment or '(' in comment %}
+{%- if '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- elif '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- endif %}
+{%- endif %}
+  {%- if column.is_pk == '1' %}
+  {%- elif column.is_list and column.list_index is not none and column.html_type == 'datetime' %}
+      <el-table-column label="{{ comment }}" align="center" v-if="columns[{{ column.list_index }}].visible" prop="{{ underscore(java_field) }}" width="180">
         <template slot-scope="scope">
         <template slot-scope="scope">
-          <span>{{ parseTime(scope.row.{{ underscore(column.java_field) }}, '{y}-{m}-{d}') }}</span>
+          <span>{{ "{{ parseTime(scope.row." }}{{ underscore(java_field) }}{{ ", '{y}-{m}-{d}') }}" }}</span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
-  {% elif column.html_type == 'imageUpload' %}
-      <el-table-column label="{{ column.column_comment }}" align="center" v-if="columns[{{ index }}].visible" prop="{{ underscore(column.java_field) }}" width="100">
+  {%- elif column.is_list and column.list_index is not none and column.html_type == 'imageUpload' %}
+      <el-table-column label="{{ comment }}" align="center" v-if="columns[{{ column.list_index }}].visible" prop="{{ underscore(java_field) }}" width="100">
         <template slot-scope="scope">
         <template slot-scope="scope">
-          <image-preview :src="scope.row.{{ underscore(column.java_field) }}" :width="50" :height="50"/>
+          <image-preview :src="scope.row.{{ underscore(java_field) }}" :width="50" :height="50"/>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
-  {% elif column.dict_type != '' %}
-      <el-table-column label="{{ column.column_comment }}" align="center" v-if="columns[{{ index }}].visible" prop="{{ underscore(column.java_field) }}">
+  {%- elif column.is_list and column.list_index is not none and column.html_type == 'fileUpload' %}
+      <el-table-column label="{{ comment }}" align="center" v-if="columns[{{ column.list_index }}].visible" prop="{{ underscore(java_field) }}" width="100">
         <template slot-scope="scope">
         <template slot-scope="scope">
-    {% if column.html_type == 'checkbox' %}
-          <dict-tag :options="dict.type.{{ getColumnDictType(column) }}" :value="scope.row.{{ underscore(column.java_field) }} ? scope.row.{{ underscore(column.java_field) }}.split(',') : []"/>
-    {% else %}
-          <dict-tag :options="dict.type.{{ getColumnDictType(column) }}" :value="scope.row.{{ underscore(column.java_field) }}"/>
-    {% endif %}
+          <div v-if="scope.row.{{ underscore(java_field) }}">
+            <el-tooltip placement="top" effect="light">
+              <div slot="content">
+                  <div v-for="(file,index) in scope.row.{{ underscore(java_field) }}.split(',')"
+                       :key="index"
+                       style="text-align: left;padding: 5px;">
+                    <el-link
+                       :download="getFileName(file)"
+                       :href="getFilePath(file)"
+                       :underline="false"
+                       target="_blank"
+                       style="font-size: 14px"
+                    >
+                    <span style="cursor: pointer;"> {{ "{{ getFileName(file) }}" }} </span>
+                  </el-link>
+                  </div>
+              </div>
+              <span style="cursor: pointer; color: #409EFF;">查看文件</span>
+            </el-tooltip>
+          </div>
+          <div v-else>
+            -
+          </div>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
-  {% else %}
-      <el-table-column label="{{ column.column_comment }}" align="center" :show-overflow-tooltip="true" v-if="columns[{{ index }}].visible" prop="{{ underscore(column.java_field) }}" />
-  {% endif %}
-  {% set index = index + 1 %}
-{% endif %}
-{% endfor %}
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
+  {%- elif column.is_list and column.list_index is not none and column.dict_type and column.dict_type != '' %}
+      <el-table-column label="{{ comment }}" align="center" v-if="columns[{{ column.list_index }}].visible" prop="{{ underscore(java_field) }}">
+        <template slot-scope="scope">
+  {%- if column.html_type == 'checkbox' %}
+          <dict-tag :options="dict.type.{{ column.dict_type }}" :value="scope.row.{{ underscore(java_field) }} ? scope.row.{{ underscore(java_field) }}.split(',') : []"/>
+  {%- else %}
+          <dict-tag :options="dict.type.{{ column.dict_type }}" :value="scope.row.{{ underscore(java_field) }}"/>
+  {%- endif %}
+        </template>
+      </el-table-column>
+  {%- elif column.is_list and column.list_index is not none and java_field %}
+  {%- if column.list_index == 0 %}
+      <el-table-column label="{{ comment }}" :show-overflow-tooltip="true" v-if="columns[{{ column.list_index }}].visible" prop="{{ underscore(java_field) }}" />
+  {%- else %}
+      <el-table-column label="{{ comment }}" align="center" :show-overflow-tooltip="true" v-if="columns[{{ column.list_index }}].visible" prop="{{ underscore(java_field) }}" />
+  {%- endif %}
+  {%- endif %}
+{%- endfor %}
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
         <template slot-scope="scope">
           <el-button
           <el-button
             size="mini"
             size="mini"
@@ -138,63 +199,112 @@
     <!-- 添加或修改{{ table.function_name }}对话框 -->
     <!-- 添加或修改{{ table.function_name }}对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-{% for column in table.columns %}
-{% if column.is_insert and not column.is_pk %}
-        <el-form-item label="{{ column.column_comment }}" prop="{{ underscore(column.java_field) }}">
-  {% if table.tree_parent_code != '' and column.java_field == table.tree_parent_code %}
-          <treeselect v-model="form.{{ underscore(table.tree_parent_code) }}" :options="{{ table.business_name }}Options" :normalizer="normalizer" placeholder="请选择{{ column.column_comment }}" />
-  {% elif column.html_type == 'input' %}
-          <el-input v-model="form.{{ underscore(column.java_field) }}" placeholder="请输入{{ column.column_comment }}" />
-  {% elif column.html_type == 'textarea' %}
-          <el-input v-model="form.{{ underscore(column.java_field) }}" type="textarea" placeholder="请输入内容" />
-  {% elif column.html_type == 'select' %}
-          <el-select v-model="form.{{ underscore(column.java_field) }}" placeholder="请选择{{ column.column_comment }}">
+{%- for column in table.columns %}
+{%- set field = column.java_field %}
+{%- if column.is_insert and column.is_pk != '1' %}
+{%- set comment = column.column_comment %}
+{%- if '(' in comment or '(' in comment %}
+{%- if '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- elif '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- endif %}
+{%- endif %}
+{%- set dict_type = column.dict_type if column.dict_type else '' %}
+  {%- if table.tree_parent_code and (underscore(column.java_field) == underscore(table.tree_parent_code) or column.java_field == table.tree_parent_code) %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(table.tree_parent_code) }}">
+          <treeselect v-model="form.{{ underscore(table.tree_parent_code) }}" :options="{{ table.business_name }}Options" :normalizer="normalizer" placeholder="请选择{{ comment }}" />
+        </el-form-item>
+  {%- elif column.html_type == 'input' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-input v-model="form.{{ underscore(field) }}" placeholder="请输入{{ comment }}" />
+        </el-form-item>
+  {%- elif column.html_type == 'imageUpload' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <image-upload v-model="form.{{ underscore(field) }}"/>
+        </el-form-item>
+  {%- elif column.html_type == 'fileUpload' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <file-upload v-model="form.{{ underscore(field) }}"/>
+        </el-form-item>
+  {%- elif column.html_type == 'editor' %}
+        <el-form-item label="{{ comment }}">
+          <editor v-model="form.{{ underscore(field) }}" :min-height="192"/>
+        </el-form-item>
+  {%- elif column.html_type == 'select' and dict_type != '' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-select v-model="form.{{ underscore(field) }}" placeholder="请选择{{ comment }}">
             <el-option
             <el-option
-              v-for="dict in {{ getColumnDictType(column) }}Options"
+              v-for="dict in dict.type.{{ dict_type }}"
               :key="dict.value"
               :key="dict.value"
               :label="dict.label"
               :label="dict.label"
-    {% if column.java_type == 'Integer' or column.java_type == 'Long' %}
+  {%- if column.java_type == 'Integer' or column.java_type == 'Long' %}
               :value="parseInt(dict.value)"
               :value="parseInt(dict.value)"
-    {% else %}
+  {%- else %}
               :value="dict.value"
               :value="dict.value"
-    {% endif %}
+  {%- endif %}
             ></el-option>
             ></el-option>
           </el-select>
           </el-select>
-  {% elif column.html_type == 'radio' %}
-          <el-radio-group v-model="form.{{ underscore(column.java_field) }}">
+        </el-form-item>
+  {%- elif column.html_type == 'select' and dict_type == '' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-select v-model="form.{{ underscore(field) }}" placeholder="请选择{{ comment }}">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+  {%- elif column.html_type == 'checkbox' and dict_type != '' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-checkbox-group v-model="form.{{ underscore(field) }}">
+            <el-checkbox
+              v-for="dict in dict.type.{{ dict_type }}"
+              :key="dict.value"
+              :label="dict.value">
+              {{ "{{dict.label}}" }}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+  {%- elif column.html_type == 'checkbox' and dict_type == '' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-checkbox-group v-model="form.{{ underscore(field) }}">
+            <el-checkbox>请选择字典生成</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+  {%- elif column.html_type == 'radio' and dict_type != '' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-radio-group v-model="form.{{ underscore(field) }}">
             <el-radio
             <el-radio
-              v-for="dict in {{ getColumnDictType(column) }}Options"
+              v-for="dict in dict.type.{{ dict_type }}"
               :key="dict.value"
               :key="dict.value"
-    {% if column.java_type == 'Integer' or column.java_type == 'Long' %}
+  {%- if column.java_type == 'Integer' or column.java_type == 'Long' %}
               :label="parseInt(dict.value)"
               :label="parseInt(dict.value)"
-    {% else %}
+  {%- else %}
               :label="dict.value"
               :label="dict.value"
-    {% endif %}
-            >{{ dict.label }}</el-radio>
+  {%- endif %}
+            >{{ "{{dict.label}}" }}</el-radio>
           </el-radio-group>
           </el-radio-group>
-  {% elif column.html_type == 'checkbox' %}
-          <el-checkbox-group v-model="form.{{ underscore(column.java_field) }}">
-            <el-checkbox
-              v-for="dict in {{ getColumnDictType(column) }}Options"
-              :key="dict.value"
-              :label="dict.value"
-            >{{ dict.label }}</el-checkbox>
-          </el-checkbox-group>
-  {% elif column.html_type == 'datetime' %}
+        </el-form-item>
+  {%- elif column.html_type == 'radio' and dict_type == '' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-radio-group v-model="form.{{ underscore(field) }}">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+  {%- elif column.html_type == 'datetime' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
           <el-date-picker clearable
           <el-date-picker clearable
-            v-model="form.{{ underscore(column.java_field) }}"
+            v-model="form.{{ underscore(field) }}"
             type="date"
             type="date"
             value-format="yyyy-MM-dd"
             value-format="yyyy-MM-dd"
-            placeholder="选择{{ column.column_comment }}">
+            placeholder="选择{{ comment }}">
           </el-date-picker>
           </el-date-picker>
-  {% elif column.html_type == 'imageUpload' %}
-          <image-upload v-model="form.{{ underscore(column.java_field) }}"/>
-  {% elif column.html_type == 'fileUpload' %}
-          <file-upload v-model="form.{{ underscore(column.java_field) }}"/>
-  {% endif %}
         </el-form-item>
         </el-form-item>
-{% endif %}
-{% endfor %}
+  {%- elif column.html_type == 'textarea' %}
+        <el-form-item label="{{ comment }}" prop="{{ underscore(field) }}">
+          <el-input v-model="form.{{ underscore(field) }}" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+  {%- endif %}
+{%- endif %}
+{%- endfor %}
       </el-form>
       </el-form>
       <div slot="footer" class="dialog-footer">
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -208,17 +318,50 @@
 import { list{{ table.class_name }}, get{{ table.class_name }}, del{{ table.class_name }}, add{{ table.class_name }}, update{{ table.class_name }} } from "@/api/{{ table.module_name }}/{{ table.business_name }}";
 import { list{{ table.class_name }}, get{{ table.class_name }}, del{{ table.class_name }}, add{{ table.class_name }}, update{{ table.class_name }} } from "@/api/{{ table.module_name }}/{{ table.business_name }}";
 import Treeselect from "@riophae/vue-treeselect";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-
+{%- set has_file_upload = false %}
+{%- for column in table.columns %}
+{%- if column.is_list and column.html_type == 'fileUpload' %}
+{%- set has_file_upload = true %}
+{%- endif %}
+{%- endfor %}
+{%- if has_file_upload %}
+import { getFileName, getFilePath } from '@/utils/ruoyi'
+{%- endif %}
 export default {
 export default {
   name: "{{ table.class_name }}",
   name: "{{ table.class_name }}",
-{% if dicts %}
-  dicts: [{{ dicts }}],
-{% endif %}
+{%- set dicts_list = [] %}
+{%- for column in table.columns %}
+{%- if column.dict_type and column.dict_type != '' %}
+{%- if column.dict_type not in dicts_list %}
+{%- set _ = dicts_list.append(column.dict_type) %}
+{%- endif %}
+{%- endif %}
+{%- endfor %}
+{%- if dicts_list|length > 0 %}
+  dicts: [{%- for dict_type in dicts_list %}'{{ dict_type }}'{%- if not loop.last %}, {% endif %}{%- endfor %}],
+{%- endif %}
   components: {
   components: {
     Treeselect
     Treeselect
   },
   },
   data() {
   data() {
     return {
     return {
+      //表格展示列
+      columns: [
+{%- for column in table.columns %}
+{%- set comment = column.column_comment %}
+{%- if '(' in comment or '(' in comment %}
+{%- if '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- elif '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- endif %}
+{%- endif %}
+  {%- if column.is_pk == '1' %}
+  {%- elif column.is_list and column.list_index is not none %}
+        { key: {{ column.list_index }}, label: '{{ comment }}', visible: true }{% if not loop.last %},{% endif %}
+  {%- endif %}
+{%- endfor %}
+      ],
       // 遮罩层
       // 遮罩层
       loading: true,
       loading: true,
       // 显示搜索条件
       // 显示搜索条件
@@ -235,90 +378,98 @@ export default {
       isExpandAll: true,
       isExpandAll: true,
       // 重新渲染表格状态
       // 重新渲染表格状态
       refreshTable: true,
       refreshTable: true,
-      // 表格列信息
-      columns: [
-{% set index = 0 %}
-{% for column in table.columns %}
-{% if column.is_list and not column.is_pk %}
-        { key: {{ index }}, label: '{{ column.column_comment }}', visible: true },
-  {% set index = index + 1 %}
-{% endif %}
-{% endfor %}
-      ],
-{% for column in table.columns %}
-{% if column.dict_type != '' %}
-      // {{ column.column_comment }}字典
-      {{ getColumnDictType(column) }}Options: [],
-{% endif %}
-{% endfor %}
-{% for column in table.columns %}
-{% if column.html_type == 'datetime' %}
-      // {{ column.column_comment }}时间范围
-      daterange{{ column.java_field }}: [],
-{% endif %}
-{% endfor %}
+{%- for column in table.columns %}
+{%- if column.html_type == 'datetime' and column.query_type == 'BETWEEN' %}
+{%- set attr_name = capitalize_first(column.java_field) %}
+{%- set comment = column.column_comment %}
+{%- if '(' in comment or '(' in comment %}
+{%- if '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- elif '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- endif %}
+{%- endif %}
+      // {{ comment }}时间范围
+      daterange{{ attr_name }}: [],
+{%- endif %}
+{%- endfor %}
       // 查询参数
       // 查询参数
       queryParams: {
       queryParams: {
-{% for column in table.columns %}
-{% if column.is_query %}
-        {{ underscore(column.java_field) }}: null,
-{% endif %}
-{% endfor %}
+{%- set query_cols = [] %}
+{%- for column in table.columns %}
+{%- if column.is_query %}
+{%- set _ = query_cols.append(column) %}
+{%- endif %}
+{%- endfor %}
+{%- for column in query_cols %}
+        {{ underscore(column.java_field) }}: null{% if not loop.last %},{% endif %}
+{%- endfor %}
       },
       },
       // 表单参数
       // 表单参数
       form: {},
       form: {},
       // 表单校验
       // 表单校验
       rules: {
       rules: {
-{% for column in table.columns %}
-{% if column.is_required %}
+{%- set required_cols = [] %}
+{%- for column in table.columns %}
+{%- if column.is_required == '1' %}
+{%- set _ = required_cols.append(column) %}
+{%- endif %}
+{%- endfor %}
+{%- for column in required_cols %}
+{%- set comment = column.column_comment %}
+{%- if '(' in comment or '(' in comment %}
+{%- if '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- elif '(' in comment %}
+{%- set comment = comment.split('(')[0] %}
+{%- endif %}
+{%- endif %}
         {{ underscore(column.java_field) }}: [
         {{ underscore(column.java_field) }}: [
-          { required: true, message: "{{ column.column_comment }}不能为空", trigger: {% if column.html_type == 'select' or column.html_type == 'radio' %}"change"{% else %}"blur"{% endif %} }
-        ],
-{% endif %}
-{% endfor %}
+          { required: true, message: "{{ comment }}不能为空", trigger: {% if column.html_type == 'select' or column.html_type == 'radio' %}"change"{% else %}"blur"{% endif %} }
+        ]{% if not loop.last %},{% endif %}
+{%- endfor %}
       }
       }
     };
     };
   },
   },
   created() {
   created() {
-{% set dictExists = false %}
-{% for column in table.columns %}
-{% if column.dict_type != '' %}
-    {% if not dictExists %}
-    this.getDicts("{{ getColumnDictType(column) }}").then(response => {
-      this.{{ getColumnDictType(column) }}Options = response.data;
-    });
-    {% set dictExists = true %}
-    {% endif %}
-{% endif %}
-{% endfor %}
     this.getList();
     this.getList();
   },
   },
   methods: {
   methods: {
     /** 查询{{ table.function_name }}列表 */
     /** 查询{{ table.function_name }}列表 */
     getList() {
     getList() {
       this.loading = true;
       this.loading = true;
-{% for column in table.columns %}
-{% if column.html_type == 'datetime' %}
+{%- set has_datetime_between = false %}
+{%- for column in table.columns %}
+{%- if column.html_type == 'datetime' and column.query_type == 'BETWEEN' %}
+{%- if not has_datetime_between %}
       this.queryParams.params = {};
       this.queryParams.params = {};
-      if (null != this.daterange{{ column.java_field }} && '' != this.daterange{{ column.java_field }}.toString()) {
-        this.queryParams.params["begin{{ column.java_field }}"] = this.daterange{{ column.java_field }}[0];
-        this.queryParams.params["end{{ column.java_field }}"] = this.daterange{{ column.java_field }}[1];
+{%- set has_datetime_between = true %}
+{%- endif %}
+{%- set attr_name = capitalize_first(column.java_field) %}
+      if (null != this.daterange{{ attr_name }} && '' != this.daterange{{ attr_name }}) {
+        this.queryParams.params["begin{{ attr_name }}"] = this.daterange{{ attr_name }}[0];
+        this.queryParams.params["end{{ attr_name }}"] = this.daterange{{ attr_name }}[1];
       }
       }
-{% endif %}
-{% endfor %}
+{%- endif %}
+{%- endfor %}
       list{{ table.class_name }}(this.queryParams).then(response => {
       list{{ table.class_name }}(this.queryParams).then(response => {
-        this.{{ table.business_name }}List = this.handleTree(response.data, "{{ table.tree_code }}", "{{ table.tree_parent_code }}");
+        const list = Array.isArray(response && response.data) ? response.data : (Array.isArray(response && response.rows) ? response.rows : []);
+        this.{{ table.business_name }}List = this.handleTree(list, "{% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %}", "{% if table.tree_parent_code %}{{ table.tree_parent_code }}{% else %}parent_id{% endif %}");
         this.loading = false;
         this.loading = false;
       });
       });
     },
     },
+{%- if has_file_upload %}
+    getFilePath,
+    getFileName,
+{%- endif %}
     /** 转换{{ table.function_name }}数据结构 */
     /** 转换{{ table.function_name }}数据结构 */
     normalizer(node) {
     normalizer(node) {
       if (node.children && !node.children.length) {
       if (node.children && !node.children.length) {
         delete node.children;
         delete node.children;
       }
       }
       return {
       return {
-        id: node.{{ table.tree_code }},
-        label: node.{{ table.tree_name }},
+        id: node.{% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %},
+        label: node.{% if table.tree_name %}{{ table.tree_name }}{% else %}name{% endif %},
         children: node.children
         children: node.children
       };
       };
     },
     },
@@ -326,8 +477,9 @@ export default {
     getTreeselect() {
     getTreeselect() {
       list{{ table.class_name }}().then(response => {
       list{{ table.class_name }}().then(response => {
         this.{{ table.business_name }}Options = [];
         this.{{ table.business_name }}Options = [];
-        const data = { {{ table.tree_code }}: 0, {{ table.tree_name }}: '顶级节点', children: [] };
-        data.children = this.handleTree(response.data, "{{ table.tree_code }}", "{{ table.tree_parent_code }}");
+        const data = { {% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %}: 0, {% if table.tree_name %}{{ table.tree_name }}{% else %}name{% endif %}: '顶级节点', children: [] };
+        const list = Array.isArray(response && response.data) ? response.data : (Array.isArray(response && response.rows) ? response.rows : []);
+        data.children = this.handleTree(list, "{% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %}", "{% if table.tree_parent_code %}{{ table.tree_parent_code }}{% else %}parent_id{% endif %}");
         this.{{ table.business_name }}Options.push(data);
         this.{{ table.business_name }}Options.push(data);
       });
       });
     },
     },
@@ -339,13 +491,13 @@ export default {
     // 表单重置
     // 表单重置
     reset() {
     reset() {
       this.form = {
       this.form = {
-{% for column in table.columns %}
-  {% if column.html_type == 'checkbox' %}
-        {{ underscore(column.java_field) }}: [],
-  {% else %}
-        {{ underscore(column.java_field) }}: null,
-  {% endif %}
-{% endfor %}
+{%- for column in table.columns %}
+  {%- if column.html_type == 'checkbox' %}
+        {{ underscore(column.java_field) }}: []
+  {%- else %}
+        {{ underscore(column.java_field) }}: null
+  {%- endif %}{% if not loop.last %},{% endif %}
+{%- endfor %}
       };
       };
       this.resetForm("form");
       this.resetForm("form");
     },
     },
@@ -355,11 +507,12 @@ export default {
     },
     },
     /** 重置按钮操作 */
     /** 重置按钮操作 */
     resetQuery() {
     resetQuery() {
-{% for column in table.columns %}
-{% if column.html_type == 'datetime' %}
-      this.daterange{{ column.java_field }} = [];
-{% endif %}
-{% endfor %}
+{%- for column in table.columns %}
+{%- if column.html_type == 'datetime' and column.query_type == 'BETWEEN' %}
+{%- set attr_name = capitalize_first(column.java_field) %}
+      this.daterange{{ attr_name }} = [];
+{%- endif %}
+{%- endfor %}
       this.resetForm("queryForm");
       this.resetForm("queryForm");
       this.handleQuery();
       this.handleQuery();
     },
     },
@@ -367,10 +520,10 @@ export default {
     handleAdd(row) {
     handleAdd(row) {
       this.reset();
       this.reset();
       this.getTreeselect();
       this.getTreeselect();
-      if (row != null && row.{{ table.tree_code }}) {
-        this.form.{{ underscore(table.tree_parent_code) }} = row.{{ table.tree_code }};
+      if (row != null && row.{% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %}) {
+        this.form.{% if table.tree_parent_code %}{{ underscore(table.tree_parent_code) }}{% else %}parent_id{% endif %} = row.{% if table.tree_code %}{{ table.tree_code }}{% else %}id{% endif %};
       } else {
       } else {
-        this.form.{{ underscore(table.tree_parent_code) }} = 0;
+        this.form.{% if table.tree_parent_code %}{{ underscore(table.tree_parent_code) }}{% else %}parent_id{% endif %} = 0;
       }
       }
       this.open = true;
       this.open = true;
       this.title = "添加{{ table.function_name }}";
       this.title = "添加{{ table.function_name }}";
@@ -388,15 +541,15 @@ export default {
       this.reset();
       this.reset();
       this.getTreeselect();
       this.getTreeselect();
       if (row != null) {
       if (row != null) {
-        this.form.{{ underscore(table.tree_parent_code) }} = row.{{ underscore(table.tree_parent_code) }};
+        this.form.{% if table.tree_parent_code %}{{ underscore(table.tree_parent_code) }}{% else %}parent_id{% endif %} = row.{% if table.tree_parent_code %}{{ underscore(table.tree_parent_code) }}{% else %}parent_id{% endif %};
       }
       }
-      get{{ table.class_name }}(row.{{ underscore(table.pk_column.java_field) }}).then(response => {
+      get{{ table.class_name }}(row.{% if table.pk_column %}{{ underscore(table.pk_column.java_field) }}{% else %}id{% endif %}).then(response => {
         this.form = response.data;
         this.form = response.data;
-{% for column in table.columns %}
-{% if column.html_type == 'checkbox' %}
+{%- for column in table.columns %}
+{%- if column.html_type == 'checkbox' %}
         this.form.{{ underscore(column.java_field) }} = this.form.{{ underscore(column.java_field) }}.split(",");
         this.form.{{ underscore(column.java_field) }} = this.form.{{ underscore(column.java_field) }}.split(",");
-{% endif %}
-{% endfor %}
+{%- endif %}
+{%- endfor %}
         this.open = true;
         this.open = true;
         this.title = "修改{{ table.function_name }}";
         this.title = "修改{{ table.function_name }}";
       });
       });
@@ -405,12 +558,12 @@ export default {
     submitForm() {
     submitForm() {
       this.$refs["form"].validate(valid => {
       this.$refs["form"].validate(valid => {
         if (valid) {
         if (valid) {
-{% for column in table.columns %}
-{% if column.html_type == 'checkbox' %}
+{%- for column in table.columns %}
+{%- if column.html_type == 'checkbox' %}
           this.form.{{ underscore(column.java_field) }} = this.form.{{ underscore(column.java_field) }}.join(",");
           this.form.{{ underscore(column.java_field) }} = this.form.{{ underscore(column.java_field) }}.join(",");
-{% endif %}
-{% endfor %}
-          if (this.form.{{ underscore(table.pk_column.java_field) }} != null) {
+{%- endif %}
+{%- endfor %}
+          if (this.form.{% if table.pk_column %}{{ underscore(table.pk_column.java_field) }}{% else %}id{% endif %} != null) {
             update{{ table.class_name }}(this.form).then(response => {
             update{{ table.class_name }}(this.form).then(response => {
               this.$modal.msgSuccess("修改成功");
               this.$modal.msgSuccess("修改成功");
               this.open = false;
               this.open = false;
@@ -428,8 +581,8 @@ export default {
     },
     },
     /** 删除按钮操作 */
     /** 删除按钮操作 */
     handleDelete(row) {
     handleDelete(row) {
-      this.$modal.confirm('是否确认删除{{ table.function_name }}编号为"' + row.{{ underscore(table.pk_column.java_field) }} + '"的数据项?').then(function() {
-        return del{{ table.class_name }}(row.{{ underscore(table.pk_column.java_field) }});
+      this.$modal.confirm('是否确认删除{{ table.function_name }}编号为"' + row.{% if table.pk_column %}{{ underscore(table.pk_column.java_field) }}{% else %}id{% endif %} + '"的数据项?').then(function() {
+        return del{{ table.class_name }}(row.{% if table.pk_column %}{{ underscore(table.pk_column.java_field) }}{% else %}id{% endif %});
       }).then(() => {
       }).then(() => {
         this.getList();
         this.getList();
         this.$modal.msgSuccess("删除成功");
         this.$modal.msgSuccess("删除成功");
@@ -437,4 +590,4 @@ export default {
     }
     }
   }
   }
 };
 };
-</script>
+</script>

+ 568 - 0
ruoyi_generator/参考/index-tree.vue.vm

@@ -0,0 +1,568 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="请输入${comment}"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
+          <el-option
+            v-for="dict in dict.type.${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <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="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="info"
+          plain
+          icon="el-icon-sort"
+          size="mini"
+          @click="toggleExpandAll"
+        >展开/折叠</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+    </el-row>
+
+    <el-table
+      v-if="refreshTable"
+      v-loading="loading"
+      :data="${businessName}List"
+      row-key="${treeCode}"
+      :default-expand-all="isExpandAll"
+      :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+    >
+#set($index = 0)
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && $column.htmlType == "imageUpload")
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" width="100">
+        <template slot-scope="scope">
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && $column.htmlType == "fileUpload")
+  <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" width="100">
+    <template slot-scope="scope">
+      <div v-if="scope.row.${javaField}">
+        <el-tooltip placement="top" effect="light">
+          <div slot="content">
+              <div v-for="(file,index) in scope.row.${javaField}.split(',')"
+                   :key="index"
+                   style="text-align: left;padding: 5px;">
+                <el-link
+                   :download="getFileName(file)"
+                   :href="getFilePath(file)"
+                   :underline="false"
+                   target="_blank"
+                   style="font-size: 14px"
+                >
+                <span style="cursor: pointer;"> {{ getFileName(file) }} </span>
+              </el-link>
+              </div>
+          </div>
+          <span style="cursor: pointer; color: #409EFF;">查看文件</span>
+        </el-tooltip>
+      </div>
+      <div v-else>
+        -
+      </div>
+    </template>
+  </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}">
+        <template slot-scope="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && "" != $javaField)
+#if(${foreach.index} == 1)
+      <el-table-column label="${comment}" :show-overflow-tooltip="true" v-if="columns[${index}].visible" prop="${javaField}" />
+#else
+      <el-table-column label="${comment}" align="center" :show-overflow-tooltip="true" v-if="columns[${index}].visible" prop="${javaField}" />
+#end
+    #set($index = $index + 1)  ## 增加 index 的值
+#end
+#end
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-plus"
+            @click="handleAdd(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:add']"
+          >新增</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 添加或修改${functionName}对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+        <el-form-item label="${comment}" prop="${treeParentCode}">
+          <treeselect v-model="form.${treeParentCode}" :options="${businessName}Options" :normalizer="normalizer" placeholder="请选择${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="请输入${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <image-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <file-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
+            <el-option
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :value="parseInt(dict.value)"
+#else
+              :value="dict.value"
+#end
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>请选择字典生成</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :label="parseInt(dict.value)"
+#else
+              :label="dict.value"
+#end
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable
+            v-model="form.${field}"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+#foreach ($column in $columns)
+#if($column.list && $column.htmlType == "fileUpload")
+import { getFileName, getFilePath } from '@/utils/ruoyi'
+#break
+#end
+#end
+export default {
+  name: "${BusinessName}",
+#if(${dicts} != '')
+  dicts: [${dicts}],
+#end
+  components: {
+    Treeselect
+  },
+  data() {
+    return {
+      //表格展示列
+#set($index = 0)
+      columns: [
+#foreach ($column in $columns)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list)
+          { key: ${index}, label: '${comment}', visible: true },
+#set($index = $index + 1)  ## 增加 index 的值
+#end
+#end
+      ],
+      // 遮罩层
+      loading: true,
+      // 显示搜索条件
+      showSearch: true,
+      // ${functionName}表格数据
+      ${businessName}List: [],
+      // ${functionName}树选项
+      ${businessName}Options: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 是否展开,默认全部展开
+      isExpandAll: true,
+      // 重新渲染表格状态
+      refreshTable: true,
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      // $comment时间范围
+      daterange${AttrName}: [],
+#end
+#end
+      // 查询参数
+      queryParams: {
+#foreach ($column in $columns)
+#if($column.query)
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+        $column.javaField: [
+          { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+        ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询${functionName}列表 */
+    getList() {
+      this.loading = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      this.queryParams.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
+        this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
+        this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
+      }
+#end
+#end
+      list${BusinessName}(this.queryParams).then(response => {
+        this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+        this.loading = false;
+      });
+    },
+#foreach ($column in $columns)
+#if($column.list && $column.htmlType == "fileUpload")
+    getFilePath,
+    getFileName,
+#break
+#end
+#end
+    /** 转换${functionName}数据结构 */
+    normalizer(node) {
+      if (node.children && !node.children.length) {
+        delete node.children;
+      }
+      return {
+        id: node.${treeCode},
+        label: node.${treeName},
+        children: node.children
+      };
+    },
+	/** 查询${functionName}下拉树结构 */
+    getTreeselect() {
+      list${BusinessName}().then(response => {
+        this.${businessName}Options = [];
+        const data = { ${treeCode}: 0, ${treeName}: '顶级节点', children: [] };
+        data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+        this.${businessName}Options.push(data);
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      this.daterange${AttrName} = [];
+#end
+#end
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    /** 新增按钮操作 */
+    handleAdd(row) {
+      this.reset();
+      this.getTreeselect();
+      if (row != null && row.${treeCode}) {
+        this.form.${treeParentCode} = row.${treeCode};
+      } else {
+        this.form.${treeParentCode} = 0;
+      }
+      this.open = true;
+      this.title = "添加${functionName}";
+    },
+    /** 展开/折叠操作 */
+    toggleExpandAll() {
+      this.refreshTable = false;
+      this.isExpandAll = !this.isExpandAll;
+      this.$nextTick(() => {
+        this.refreshTable = true;
+      });
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      this.getTreeselect();
+      if (row != null) {
+        this.form.${treeParentCode} = row.${treeParentCode};
+      }
+      get${BusinessName}(row.${pkColumn.javaField}).then(response => {
+        this.form = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        this.form.$column.javaField = this.form.${column.javaField}.split(",");
+#end
+#end
+        this.open = true;
+        this.title = "修改${functionName}";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.#[[$]]#refs["form"].validate(valid => {
+        if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+          this.form.$column.javaField = this.form.${column.javaField}.join(",");
+#end
+#end
+          if (this.form.${pkColumn.javaField} != null) {
+            update${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            add${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + row.${pkColumn.javaField} + '"的数据项?').then(function() {
+        return del${BusinessName}(row.${pkColumn.javaField});
+      }).then(() => {
+        this.getList();
+        this.#[[$modal]]#.msgSuccess("删除成功");
+      }).catch(() => {});
+    }
+  }
+};
+</script>

+ 665 - 0
ruoyi_generator/参考/index.vue.vm

@@ -0,0 +1,665 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-input
+          v-model="queryParams.${column.javaField}"
+          placeholder="请输入${comment}"
+          clearable
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
+          <el-option
+            v-for="dict in dict.type.${dictType}"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-select v-model="queryParams.${column.javaField}" placeholder="请选择${comment}" clearable>
+          <el-option label="请选择字典生成" value="" />
+        </el-select>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+      <el-form-item label="${comment}" prop="${column.javaField}">
+        <el-date-picker clearable
+          v-model="queryParams.${column.javaField}"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="请选择${comment}">
+        </el-date-picker>
+      </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      <el-form-item label="${comment}">
+        <el-date-picker
+          v-model="daterange${AttrName}"
+          style="width: 240px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        ></el-date-picker>
+      </el-form-item>
+#end
+#end
+#end
+      <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="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['${moduleName}:${businessName}:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['${moduleName}:${businessName}:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['${moduleName}:${businessName}:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['${moduleName}:${businessName}:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+#set($index = 0)
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" />
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && $column.htmlType == "datetime")
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && $column.htmlType == "imageUpload")
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" width="100">
+        <template slot-scope="scope">
+          <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && $column.htmlType == "fileUpload")
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}" width="100">
+        <template slot-scope="scope">
+          <div v-if="scope.row.${javaField}">
+            <el-tooltip placement="top" effect="light">
+              <div slot="content">
+                  <div v-for="(file,index) in scope.row.${javaField}.split(',')"
+                       :key="index"
+                       style="text-align: left;padding: 5px;">
+                    <el-link
+                       :download="getFileName(file)"
+                       :href="getFilePath(file)"
+                       :underline="false"
+                       target="_blank"
+                       style="font-size: 14px"
+                    >
+                    <span style="cursor: pointer;"> {{ getFileName(file) }} </span>
+                  </el-link>
+                  </div>
+              </div>
+              <span style="cursor: pointer; color: #409EFF;">查看文件</span>
+            </el-tooltip>
+          </div>
+          <div v-else>
+            -
+          </div>
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && "" != $column.dictType)
+      <el-table-column label="${comment}" align="center" v-if="columns[${index}].visible" prop="${javaField}">
+        <template slot-scope="scope">
+#if($column.htmlType == "checkbox")
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+          <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+        </template>
+      </el-table-column>
+    #set($index = $index + 1)  ## 增加 index 的值
+#elseif($column.list && "" != $javaField)
+      <el-table-column label="${comment}" :show-overflow-tooltip="true" align="center" v-if="columns[${index}].visible" prop="${javaField}" />
+    #set($index = $index + 1)  ## 增加 index 的值
+#end
+#end
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['${moduleName}:${businessName}:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改${functionName}对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if($column.htmlType == "input")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" placeholder="请输入${comment}" />
+        </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <image-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+        <el-form-item label="${comment}" prop="${field}">
+          <file-upload v-model="form.${field}"/>
+        </el-form-item>
+#elseif($column.htmlType == "editor")
+        <el-form-item label="${comment}">
+          <editor v-model="form.${field}" :min-height="192"/>
+        </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
+            <el-option
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :value="parseInt(dict.value)"
+#else
+              :value="dict.value"
+#end
+            ></el-option>
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-select v-model="form.${field}" placeholder="请选择${comment}">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+              :label="dict.value">
+              {{dict.label}}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-checkbox-group v-model="form.${field}">
+            <el-checkbox>请选择字典生成</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio
+              v-for="dict in dict.type.${dictType}"
+              :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+              :label="parseInt(dict.value)"
+#else
+              :label="dict.value"
+#end
+            >{{dict.label}}</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+        <el-form-item label="${comment}" prop="${field}">
+          <el-radio-group v-model="form.${field}">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+#elseif($column.htmlType == "datetime")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-date-picker clearable
+            v-model="form.${field}"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="请选择${comment}">
+          </el-date-picker>
+        </el-form-item>
+#elseif($column.htmlType == "textarea")
+        <el-form-item label="${comment}" prop="${field}">
+          <el-input v-model="form.${field}" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+#end
+#end
+#end
+#end
+#if($table.sub)
+        <el-divider content-position="center">${subTable.functionName}信息</el-divider>
+        <el-row :gutter="10" class="mb8">
+          <el-col :span="1.5">
+            <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd${subClassName}">添加</el-button>
+          </el-col>
+          <el-col :span="1.5">
+            <el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDelete${subClassName}">删除</el-button>
+          </el-col>
+        </el-row>
+        <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
+          <el-table-column type="selection" width="50" align="center" />
+          <el-table-column label="序号" align="center" prop="index" width="50"/>
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $javaField == ${subTableFkclassName})
+#elseif($column.list && $column.htmlType == "input")
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-input v-model="scope.row.$javaField" placeholder="请输入$comment" />
+            </template>
+          </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+          <el-table-column label="$comment" prop="${javaField}" width="240">
+            <template slot-scope="scope">
+              <el-date-picker clearable v-model="scope.row.$javaField" type="date" value-format="yyyy-MM-dd" placeholder="请选择$comment" />
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
+                <el-option
+                  v-for="dict in dict.type.$column.dictType"
+                  :key="dict.value"
+                  :label="dict.label"
+                  :value="dict.value"
+                ></el-option>
+              </el-select>
+            </template>
+          </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+          <el-table-column label="$comment" prop="${javaField}" width="150">
+            <template slot-scope="scope">
+              <el-select v-model="scope.row.$javaField" placeholder="请选择$comment">
+                <el-option label="请选择字典生成" value="" />
+              </el-select>
+            </template>
+          </el-table-column>
+#end
+#end
+        </el-table>
+#end
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+#foreach ($column in $columns)
+#if($column.list && $column.htmlType == "fileUpload")
+import { getFileName, getFilePath } from '@/utils/ruoyi'
+#break
+#end
+#end
+export default {
+  name: "${BusinessName}",
+#if(${dicts} != '')
+  dicts: [${dicts}],
+#end
+  data() {
+    return {
+      //表格展示列
+#set($index = 0)
+      columns: [
+#foreach ($column in $columns)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $column.list)
+        { key: ${index}, label: '${comment}', visible: true },
+#set($index = $index + 1)  ## 增加 index 的值
+#end
+#end
+      ],
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+#if($table.sub)
+      // 子表选中数据
+      checked${subClassName}: [],
+#end
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // ${functionName}表格数据
+      ${businessName}List: [],
+#if($table.sub)
+      // ${subTable.functionName}表格数据
+      ${subclassName}List: [],
+#end
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      // $comment时间范围
+      daterange${AttrName}: [],
+#end
+#end
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+#foreach ($column in $columns)
+#if($column.query)
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("("))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+        $column.javaField: [
+          { required: true, message: "$comment不能为空", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+        ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询${functionName}列表 */
+    getList() {
+      this.loading = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+      this.queryParams.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
+        this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
+        this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
+      }
+#end
+#end
+      list${BusinessName}(this.queryParams).then(response => {
+        this.${businessName}List = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+#foreach ($column in $columns)
+#if($column.list && $column.htmlType == "fileUpload")
+    getFilePath,
+    getFileName,
+#break
+#end
+#end
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+        $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+      };
+#if($table.sub)
+      this.${subclassName}List = [];
+#end
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+      this.daterange${AttrName} = [];
+#end
+#end
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.${pkColumn.javaField})
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加${functionName}";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
+      get${BusinessName}(${pkColumn.javaField}).then(response => {
+        this.form = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+        this.form.$column.javaField = this.form.${column.javaField}.split(",");
+#end
+#end
+#if($table.sub)
+        this.${subclassName}List = response.data.${subclassName}List;
+#end
+        this.open = true;
+        this.title = "修改${functionName}";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.#[[$]]#refs["form"].validate(valid => {
+        if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+          this.form.$column.javaField = this.form.${column.javaField}.join(",");
+#end
+#end
+#if($table.sub)
+          this.form.${subclassName}List = this.${subclassName}List;
+#end
+          if (this.form.${pkColumn.javaField} != null) {
+            update${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            add${BusinessName}(this.form).then(response => {
+              this.#[[$modal]]#.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
+      this.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() {
+        return del${BusinessName}(${pkColumn.javaField}s);
+      }).then(() => {
+        this.getList();
+        this.#[[$modal]]#.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+#if($table.sub)
+	/** ${subTable.functionName}序号 */
+    row${subClassName}Index({ row, rowIndex }) {
+      row.index = rowIndex + 1;
+    },
+    /** ${subTable.functionName}添加按钮操作 */
+    handleAdd${subClassName}() {
+      let obj = {};
+#foreach($column in $subTable.columns)
+#if($column.pk || $column.javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+      obj.$column.javaField = "";
+#end
+#end
+      this.${subclassName}List.push(obj);
+    },
+    /** ${subTable.functionName}删除按钮操作 */
+    handleDelete${subClassName}() {
+      if (this.checked${subClassName}.length == 0) {
+        this.#[[$modal]]#.msgError("请先选择要删除的${subTable.functionName}数据");
+      } else {
+        const ${subclassName}List = this.${subclassName}List;
+        const checked${subClassName} = this.checked${subClassName};
+        this.${subclassName}List = ${subclassName}List.filter(function(item) {
+          return checked${subClassName}.indexOf(item.index) == -1
+        });
+      }
+    },
+    /** 复选框选中数据 */
+    handle${subClassName}SelectionChange(selection) {
+      this.checked${subClassName} = selection.map(item => item.index)
+    },
+#end
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('${moduleName}/${businessName}/export', {
+        ...this.queryParams
+      }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
+    }
+  }
+};
+</script>