Easycode模板,基于官方提供的Mybatis-plus模板改造

本文介绍了一种名为Easycode的模板,它简化了从前端到后端的开发过程,支持单表增删改查操作,接口类自动继承实体类,提供日期验证、批量插入更新等功能,并包含强大的导入导出解决方案,包括容错处理和前端可视化操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Easycode模板,逆向工程,单表增删改查,从前端到后端不需要任何一点代码

目录结构 

 模板亮点

1、接口类默认继承实体类

实体类不做任何修改保证类与表统一

2、实体类涵盖多种注解

日期格式编码、Long类型转String、字段自动填充、validate校验

3、自带insertOrUpdateBatch方法

4、自动生成前端的增删改查页面 

字符限制

5、牛逼的导入导出解决方案

支持导出模板、导出数据

支持导入校验,字符长度校验,日期类型校验,布尔类型校验,小数精度校验

上传文件,如果异常会返回批改后的文件(红色字体批注)

容错导入,正常数据会自动导入,异常数据会批改后返回

直接导入(如果有错,会批改导入文件,并下载出来)

允许容错

正确的数据会导入成功并删除,错误的数据会留下并下载出来

使用方式

部分代码需要下载资源,自己改造也可以

{
  "author" : "Wsong",
  "version" : "1.2.8",
  "userSecure" : "",
  "currTypeMapperGroupName" : "Default",
  "currTemplateGroupName" : "ShuRong",
  "currColumnConfigGroupName" : "Default",
  "currGlobalConfigGroupName" : "Default",
  "typeMapper" : {
    "Default" : {
      "name" : "Default",
      "elementList" : [ {
        "matchType" : "REGEX",
        "columnType" : "varchar(\\(\\d+\\))?",
        "javaType" : "java.lang.String"
      }, {
        "matchType" : "REGEX",
        "columnType" : "char(\\(\\d+\\))?",
        "javaType" : "java.lang.String"
      }, {
        "matchType" : "REGEX",
        "columnType" : "(tiny|medium|long)*text",
        "javaType" : "java.lang.String"
      }, {
        "matchType" : "REGEX",
        "columnType" : "decimal(\\(\\d+,\\d+\\))?",
        "javaType" : "java.lang.Double"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "integer",
        "javaType" : "java.lang.Integer"
      }, {
        "matchType" : "REGEX",
        "columnType" : "(tiny|small|medium)*int(\\(\\d+\\))?",
        "javaType" : "java.lang.Integer"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "int4",
        "javaType" : "java.lang.Integer"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "int8",
        "javaType" : "java.lang.Long"
      }, {
        "matchType" : "REGEX",
        "columnType" : "bigint(\\(\\d+\\))?",
        "javaType" : "java.lang.Long"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "date",
        "javaType" : "java.time.LocalDate"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "datetime",
        "javaType" : "java.time.LocalDateTime"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "timestamp",
        "javaType" : "java.time.LocalDateTime"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "time",
        "javaType" : "java.time.LocalTime"
      }, {
        "matchType" : "ORDINARY",
        "columnType" : "boolean",
        "javaType" : "java.lang.Boolean"
      } ]
    }
  },
  "template" : {
    "ShuRong" : {
      "name" : "ShuRong",
      "elementList" : [ {
        "name" : "controller.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n\n##设置表后缀(宏定义)\n#setTableSuffix(\"Controller\")\n\n##保存文件(宏定义)\n#save(\"/controller\", \"Controller.java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"controller\")\n\n##定义服务名\n#set($serviceName = $!tool.append($!tool.firstLowerCase($!tableInfo.name), \"Service\"))\n\n##定义实体对象名\n#set($entityName = $!tool.firstLowerCase($!tableInfo.name))\n\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n\nimport cn.dmp.common.easycode.EasyValidateGroup;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport com.baomidou.mybatisplus.extension.api.ApiController;\nimport com.baomidou.mybatisplus.extension.api.R;\nimport $!{tableInfo.savePackageName}.entity.$!tableInfo.name;\nimport $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;\nimport org.springframework.web.bind.annotation.*;\nimport org.springframework.web.multipart.MultipartFile;\nimport org.springframework.validation.annotation.Validated;\n\nimport javax.servlet.http.HttpServletResponse;\nimport javax.annotation.Resource;\nimport java.io.Serializable;\nimport java.util.List;\n\n##表注释(宏定义)\n#tableComment(\"表控制层\")\n@RestController\n@RequestMapping(\"$!tool.firstLowerCase($!tableInfo.name)\")\npublic class $!{tableName} extends ApiController {\n    /**\n     * 服务对象\n     */\n    @Resource\n    private $!{tableInfo.name}Service $!{serviceName};\n\n   \n    #if($tree)\n    \n    /**\n     * 树\n     * @param $!entityName 查询实体\n     * @return 所有数据\n     */\n    @GetMapping(\"tree\")\n    public R<List<$!tableInfo.name>> tree($!tableInfo.name $!entityName) {\n\n        return success(this.$!{serviceName}.tree($!entityName));\n    }\n    /**\n     * 懒加载树\n     * @param $!entityName 查询实体\n     * @return 所有数据\n     */\n    @GetMapping(\"treeLazy\")\n    public R<List<$!tableInfo.name>> treeLazy($!tableInfo.name $!entityName) {\n\n        return success(this.$!{serviceName}.treeLazy($!entityName));\n    }\n    #end\n\n    /**\n     * 分页查询所有数据\n     *\n     * @param page 分页对象\n     * @param $!entityName 查询实体\n     * @return 所有数据\n     */\n    @GetMapping(\"page\")\n    public R<Page<$!tableInfo.name>> selectAll(Page<$!tableInfo.name> page, $!tableInfo.name $!entityName) {\n        return success(this.$!{serviceName}.pagem(page, $!entityName));\n    }\n    /**\n     * 查询所有数据\n     *\n     * @param $!entityName 查询实体\n     * @return 所有数据\n     */\n    @GetMapping(\"list\")\n    public R<List<$!tableInfo.name>> list($!tableInfo.name $!entityName) {\n        return success(this.$!{serviceName}.listm($!entityName));\n    }\n    /**\n     * 通过主键查询单条数据\n     *\n     * @param id 主键\n     * @return 单条数据\n     */\n    @GetMapping(\"get/{id}\")\n    public R<$!tableInfo.name> selectOne(@PathVariable Long id) {\n        return success(this.$!{serviceName}.getById(id));\n    }\n\n    /**\n     * 新增数据\n     *\n     * @param $!entityName 实体对象\n     * @return 新增结果\n     */\n    @PostMapping\n    public R<Boolean> insert(@RequestBody @Validated(EasyValidateGroup.AddGroup.class) $!tableInfo.name $!entityName) {\n        return success(this.$!{serviceName}.savem($!entityName));\n    }\n\n    /**\n     * 修改数据\n     *\n     * @param $!entityName 实体对象\n     * @return 修改结果\n     */\n    @PutMapping\n    public R<Boolean> update(@RequestBody @Validated(EasyValidateGroup.UpdGroup.class) $!tableInfo.name $!entityName) {\n        return success(this.$!{serviceName}.updatem($!entityName));\n    }\n\n    /**\n     * 删除数据\n     *\n     * @param idList 主键结合\n     * @return 删除结果\n     */\n    @DeleteMapping\n    public R<Boolean> delete(@RequestParam(\"idList\") List<Long> idList) {\n        return success(this.$!{serviceName}.removem(idList));\n    }\n    \n        /**\n     * 模板导出\n     *\n     * @param response excel文件\n     * @return\n     * @throws Exception\n     */\n    @GetMapping(\"export/template\")\n    public void exportTemplate(HttpServletResponse response) throws Exception {\n        this.$!{serviceName}.exportTemplate(response);\n    }\n\n\n    /**\n     * 数据导出\n     *\n     * @param response excel文件\n     * @return\n     * @throws Exception\n     */\n    @GetMapping(\"export/data\")\n    public void exportData(HttpServletResponse response,Page<$!tableInfo.name> page, $!tableInfo.name $!entityName) throws Exception {\n        this.$!{serviceName}.exportData(page,$!entityName,response);\n    }\n    \n       \n    /**\n    * 指标类型导入\n    *\n    * @param file    文件\n    */\n    @PostMapping(\"import/data/{allError}\")\n    public void importData(HttpServletResponse response,@RequestParam(\"file\") MultipartFile file,@PathVariable String allError) {\n        this.$!{serviceName}.importData(response,file,allError);\n    }\n}\n"
      }, {
        "name" : "service.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n\n##设置表后缀(宏定义)\n#setTableSuffix(\"Service\")\n\n##保存文件(宏定义)\n#save(\"/service\", \"Service.java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"service\")\n\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n\n##定义实体对象名\n#set($entityName = $!tool.firstLowerCase($!tableInfo.name))\n\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport com.baomidou.mybatisplus.extension.service.IService;\nimport $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.List;\n\n##表注释(宏定义)\n#tableComment(\"表服务接口\")\npublic interface $!{tableName} extends IService<$!{tableInfo.name}> {\n    #if($tree)\n    List<$!{tableInfo.name}> tree($!{tableInfo.name} $!tool.firstLowerCase($!tableInfo.name));\n\n    List<$!{tableInfo.name}> treeLazy($!{tableInfo.name} $!tool.firstLowerCase($!tableInfo.name));\n    #end\n    \n    Page<$!tableInfo.name> pagem(Page<$!tableInfo.name> page, $!tableInfo.name $!entityName);\n    \n    List<$!tableInfo.name> listm($!tableInfo.name $!entityName);\n    \n    Boolean savem($!tableInfo.name $!entityName);\n    \n    Boolean updatem($!tableInfo.name $!entityName);\n    \n    Boolean removem(List<Long> idList);\n    \n    void exportTemplate(HttpServletResponse response);\n\n    void exportData(Page<$!tableInfo.name> page, $!tableInfo.name $!entityName, HttpServletResponse response);\n    \n    void importData(HttpServletResponse response, MultipartFile file,String allError);\n}\n"
      }, {
        "name" : "serviceImpl.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n##引入mybatis支持\n$!{mybatisSupport.vm}\n\n##设置表后缀(宏定义)\n#setTableSuffix(\"ServiceImpl\")\n\n##保存文件(宏定义)\n#save(\"/service/impl\", \"ServiceImpl.java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"service.impl\")\n##定义实体对象名\n#set($entityName = $!tool.firstLowerCase($!tableInfo.name))\n\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n\nimport cn.hutool.core.bean.BeanUtil;\nimport cn.hutool.core.util.ObjectUtil;\nimport cn.hutool.poi.excel.ExcelReader;\nimport cn.hutool.poi.excel.ExcelUtil;\nimport cn.hutool.poi.excel.ExcelWriter;\nimport com.baomidou.mybatisplus.extension.plugins.pagination.Page;\nimport com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;\nimport $!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper;\nimport $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};\nimport $!{tableInfo.savePackageName}.excel.$!{tableInfo.name}Excel;\nimport $!{tableInfo.savePackageName}.service.$!{tableInfo.name}Service;\nimport org.apache.commons.lang3.StringUtils;\nimport org.apache.poi.ss.usermodel.*;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport lombok.extern.slf4j.Slf4j;\n\nimport java.io.IOException;\nimport java.util.*;\nimport java.util.stream.Collectors;\n\nimport com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletResponse;\n\nimport cn.dmp.common.easycode.EasyCodeResult;\nimport static cn.dmp.common.easycode.EasyCodeUtils.*;\n\n#if($tree)\nimport java.util.stream.Collectors;\nimport java.util.Optional;\n#end\n\n##表注释(宏定义)\n#tableComment(\"表服务实现类\")\n@Slf4j\n@Service(\"$!{entityName}Service\")\npublic class $!{tableName} extends ServiceImpl<$!{tableInfo.name}Mapper, $!{tableInfo.name}> implements $!{tableInfo.name}Service {\n    \n#if($tree)\n    @Override\n    public List<$!{tableInfo.name}> tree($!{tableInfo.name} $!{entityName}) {\n        QueryWrapper<$!{tableInfo.name}> wrapper = new QueryWrapper<>($!{entityName});\n        List<$!{tableInfo.name}> list = this.list(wrapper);\n        List<Long> ids = list.stream().map($!{tableInfo.name}::getId).collect(Collectors.toList());\n        for ($!{tableInfo.name} di : list) {\n             List<$!{tableInfo.name}> child = list.stream().filter(a -> Objects.equals(a.getPid(), di.getId())).collect(Collectors.toList());\n             di.setChildren(Optional.of(child).orElse(new ArrayList<>()));\n        }\n        return list.stream().filter(a -> !ids.contains(a.getPid())).collect(Collectors.toList());\n    }\n\n    @Override\n    public List<$!{tableInfo.name}> treeLazy($!{tableInfo.name} $!{entityName}) {\n        QueryWrapper<$!{tableInfo.name}> wrapper = new QueryWrapper<>($!{entityName});\n        if( $!{entityName}.getId()!=null&& $!{entityName}.getId()!=0){\n            wrapper.notInSql(\"pid\",\"select id from $!{tableInfo.obj.name}\");\n        }else{\n            wrapper.eq(\"pid\",  $!{entityName}.getId());\n        }\n        return this.list(wrapper);\n    }\n#end\n\n    @Override\n    public Page<$!tableInfo.name> pagem(Page<$!tableInfo.name> page, $!tableInfo.name $!entityName){\n    \n        QueryWrapper<$!tableInfo.name> wrapper = new QueryWrapper<>();\n        #foreach($column in $tableInfo.fullColumn)\n        #if($column.type == \"java.lang.String\" && \"create_user\" != $!column.obj.name && \"update_user\" != $!column.obj.name)\n        if(StringUtils.isNotBlank($!{entityName}.get$tool.firstUpperCase($!{column.name})())){\n            wrapper.like(\"$column.obj.name\",$!{entityName}.get$tool.firstUpperCase($!{column.name})());\n        }\n        #end\n        #end\n       return this.page(page, wrapper);\n    }\n    \n    @Override\n    public List<$!tableInfo.name> listm($!tableInfo.name $!entityName){\n       return this.list(new QueryWrapper<>($!entityName));\n    }\n    \n    @Override\n    public Boolean savem($!tableInfo.name $!entityName){\n       return this.save($!entityName);\n    }\n    \n    @Override\n    public Boolean updatem($!tableInfo.name $!entityName){\n       return this.updateById($!entityName);\n    }\n        \n    @Override\n    public Boolean removem(List<Long> idList){\n       return this.removeByIds(idList);\n    }\n    \n    @Override\n    public void exportTemplate(HttpServletResponse response) {\n        try {\n            easyTemplateExport(response, ${tableInfo.name}Excel.class);\n        } catch (IOException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n\n    @Override\n    public void exportData(Page<$!tableInfo.name> page, $!tableInfo.name $!entityName, HttpServletResponse response) {\n        \n        try {\n            Page<$!tableInfo.name> pg = this.pagem(page,$!entityName);\n            List<$!tableInfo.name> records = pg.getRecords();\n            // 修改collect数据,控制导出的内容\n            List<Map<String, Object>> collect = records.stream().map(BeanUtil::beanToMap).collect(Collectors.toList());\n            List<${tableInfo.name}Excel> list = easyMap2Bean(collect, ${tableInfo.name}Excel.#[[class]]#);\n            easyDataExport(list,response, ${tableInfo.name}Excel.#[[class]]#);\n        } catch (IOException e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    \n    @Override\n    @Transactional\n    public void importData(HttpServletResponse response, MultipartFile file,String allError) {\n        if (file == null) {\n            throw new RuntimeException(\"导入文件为空!\");\n        }\n        try {\n            ExcelReader reader = ExcelUtil.getReader(file.getInputStream());\n            Workbook workbook = reader.getWorkbook();\n            Sheet sheet = workbook.getSheetAt(0);\n            EasyCodeResult result = easyDataHandel(sheet, ${tableInfo.name}Excel.#[[class]]#);\n            dataCheck(result);\n            List<Map<String,Object>> data = result.getData();\n            Map<String, String> errMaps = result.getErrMaps();\n            result.setSuccessCount(data.size());\n            if (StringUtils.equalsIgnoreCase(allError, ALLOW_ERR) || errMaps.isEmpty()) {\n                // 如果允许容错才写部分的错误数据\n                List<${tableInfo.name}>  dataBeans = easyMap2Bean(data, ${tableInfo.name}.#[[class]]#);\n                this.saveBatch(dataBeans);\n            }\n\n            if (!errMaps.isEmpty()) {\n                ExcelWriter errs = easyWriteError(sheet, allError, errMaps);\n                errs.flush(response.getOutputStream());\n                errs.close();\n            }\n\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n     /**\n     * 修改data数据,控制写入内容\n     * 修改errMaps数据,控制批改数据,errMaps的key为excel的xy坐标,value为写出的批改数据\n     * 已知错误数据如何获取错误数据的坐标?\n     * x坐标从result.getHeaderIndex中通过字段名获取\n     * y坐标从result.getData.get(i).get(\"excelIndex\")获取\n     * errMaps.put(\"1,1\",\"张三\"),导出的excel中第二行第二列(2,B),会红色字体显示张三\n     * 见下方实例代码\n     */\n    private static void dataCheck(EasyCodeResult result) {\n        // List<Map<String, Object>> data = result.getData();\n        // List<Map<String, Object>> newData = new ArrayList<>();\n        // Map<String, String> errMaps = result.getErrMaps();\n        // Map<String, Integer> headers = result.getHeaderIndex();\n        // List<String> itemName = new ArrayList<>();\n        // for (Map<String, Object> row : data) {\n        //     Object className = row.get(\"className\");\n        //     // 通过类名称获取id\n        //     row.put(\"classId\", className);\n        //     // 去重\n        //     Object title = row.get(\"itemName\");\n        //     if (itemName.contains((String) title)) {\n        //         errMaps.put(row.get(\"excelIndex\") + \",\" + headers.get(\"itemName\"), title + \"【指标名称已存在】\");\n        //     } else {\n        //         itemName.add((String) title);\n        //         newData.add(row);\n        //     }\n        // }\n        // result.setData(newData);\n    }\n}\n"
      }, {
        "name" : "mapper.xml.vm",
        "code" : "##引入mybatis支持\n$!{mybatisSupport.vm}\n\n\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append($!{tableInfo.name}, \"Mapper.xml\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/mapper/\"))\n\n\n##拿到主键\n#if(!$tableInfo.pkColumn.isEmpty())\n    #set($pk = $tableInfo.pkColumn.get(0))\n#end\n\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"$!{tableInfo.savePackageName}.mapper.$!{tableInfo.name}Mapper\">\n\n    <resultMap id=\"BaseResultMap\" type=\"$!{tableInfo.savePackageName}.entity.$!{tableInfo.name}\">\n        <!--@Table $!{tableInfo.obj.name}-->\n#foreach($column in $tableInfo.fullColumn)\n        <result property=\"$!column.name\" column=\"$!column.obj.name\" jdbcType=\"$!column.ext.jdbcType\"/>\n#end\n    </resultMap>\n<!-- 批量插入 -->\n    <insert id=\"insertBatch\" keyProperty=\"$!pk.name\" useGeneratedKeys=\"true\">\n        insert into $!{tableInfo.obj.name}(#foreach($column in $tableInfo.fullColumn)$!column.obj.name#if( $foreach.hasNext ),#end#end)\n        values\n        <foreach collection=\"entities\" item=\"entity\" separator=\",\">\n        (#foreach($column in $tableInfo.fullColumn)#{entity.$!{column.name}}#if( $foreach.hasNext ),#end#end)\n        </foreach>\n    </insert>\n    <!-- 批量插入或按主键更新 -->\n    <insert id=\"insertOrUpdateBatch\" keyProperty=\"$!pk.name\" useGeneratedKeys=\"true\">\n     \n        insert into $!{tableInfo.obj.name}(#foreach($column in $tableInfo.fullColumn)$!column.obj.name#if( $foreach.hasNext ),#end#end)\n        values\n        <foreach collection=\"entities\" item=\"entity\" separator=\",\">\n            (#foreach($column in $tableInfo.fullColumn)#{entity.$!{column.name}}#if( $foreach.hasNext ),#end#end)\n        </foreach>\n        on duplicate key update\n         #foreach($column in $tableInfo.fullColumn)$!column.obj.name = values($!column.name)#if( $foreach.hasNext ),#end#end\n    </insert>\n\n</mapper>\n"
      }, {
        "name" : "mapper.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n\n##设置表后缀(宏定义)\n#setTableSuffix(\"Mapper\")\n\n##保存文件(宏定义)\n#save(\"/mapper\", \"Mapper.java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"mapper\")\n\nimport org.apache.ibatis.annotations.Mapper;\nimport com.baomidou.mybatisplus.core.mapper.BaseMapper;\nimport $!{tableInfo.savePackageName}.entity.$!{tableInfo.name};\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n##表注释(宏定义)\n#tableComment(\"表数据库访问层\")\n@Mapper\npublic interface $!{tableName} extends BaseMapper<$!{tableInfo.name}> {\n/**\n* 批量新增数据(MyBatis原生foreach方法)\n*\n* @param entities List<$!{tableInfo.name}> 实例对象列表\n* @return 影响行数\n*/\nint insertBatch(@Param(\"entities\") List<$!{tableInfo.name}> entities);\n\n/**\n* 批量新增或按主键更新数据(MyBatis原生foreach方法)\n*\n* @param entities List<$!{tableInfo.name}> 实例对象列表\n* @return 影响行数\n* @throws org.springframework.jdbc.BadSqlGrammarException 入参是空List的时候会抛SQL语句错误的异常,请自行校验入参\n*/\nint insertOrUpdateBatch(@Param(\"entities\") List<$!{tableInfo.name}> entities);\n\n}\n"
      }, {
        "name" : "entity.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n\n##保存文件(宏定义)\n#save(\"/entity\", \".java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"entity\")\n\n$!callback.setFileName($tool.append($!{tableInfo.name}, \"Entity.java\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/entity/\"))\n\n##自动导入包(全局变量)\n$!{autoImport.vm}\nimport com.baomidou.mybatisplus.annotation.FieldFill;\nimport com.baomidou.mybatisplus.annotation.IdType;\nimport com.baomidou.mybatisplus.annotation.TableField;\nimport com.baomidou.mybatisplus.annotation.TableId;\nimport com.baomidou.mybatisplus.extension.activerecord.Model;\nimport com.fasterxml.jackson.annotation.JsonFormat;\nimport org.springframework.format.annotation.DateTimeFormat;\nimport com.fasterxml.jackson.databind.annotation.JsonSerialize;\nimport com.fasterxml.jackson.databind.ser.std.ToStringSerializer;\nimport java.io.Serializable;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport cn.dmp.common.easycode.EasyValidateGroup;\nimport org.springframework.validation.annotation.Validated;\nimport javax.validation.constraints.NotNull;\nimport javax.validation.constraints.Size;\n\n##表注释(宏定义)\n#tableComment(\"表实体类\")\n@EqualsAndHashCode(callSuper = true)\n@Data\npublic class $!{tableInfo.name}Entity extends Model<$!{tableInfo.name}Entity> {\n#foreach($column in $tableInfo.fullColumn)\n    \n    #if(${column.comment})    // ${column.comment}#end\n    \n    #if($column.type == \"java.time.LocalDateTime\")    @DateTimeFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")\n    @JsonFormat(pattern = \"yyyy-MM-dd HH:mm:ss\")#end\n    #if($column.type == \"java.time.LocalDate\")    @DateTimeFormat(pattern = \"yyyy-MM-dd\")\n    @JsonFormat(pattern = \"yyyy-MM-dd\")#end\n    #if($column.type == \"java.time.LocalTime\")    @DateTimeFormat(pattern = \"HH:mm:ss\")\n    @JsonFormat(pattern = \"HH:mm:ss\")#end\n    #if($column.type == \"java.lang.Long\")    @JsonSerialize(using= ToStringSerializer.class)#end\n    #if($column.name == \"createUser\")    @TableField(fill = FieldFill.INSERT)#end\n    #if($column.name == \"createTime\")    @TableField(fill = FieldFill.INSERT)#end\n    #if($column.name == \"updateUser\")    @TableField(fill = FieldFill.INSERT_UPDATE)#end\n    #if($column.name == \"updateTime\")    @TableField(fill = FieldFill.INSERT_UPDATE)#end\n    #if($column.name == \"id\")    @TableId(type = IdType.ASSIGN_ID)#end\n    #if($!column.name!=\"id\"&&$!column.name!=\"createTime\"&&$!column.name!=\"createUser\"&&$!column.name!=\"updateTime\"&&$!column.name!=\"updateUser\"&&$!column.name!=\"isDeleted\")\n    #if(${column.obj.notNull})\n    @NotNull(message = \"${column.comment}不能为空\",groups = {EasyValidateGroup.AddGroup.class,EasyValidateGroup.UpdGroup.class})\n    #end\n    #if($column.obj.dataType.length > 0 && $column.ext.sqlType=='varchar')\n    @Size( max = $column.obj.dataType.length, message = \"${column.comment}必须小于${column.obj.dataType.length}字符\", groups = {EasyValidateGroup.AddGroup.class,EasyValidateGroup.UpdGroup.class})\n    #end\n    #end\n    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};\n    \n#end\n\n\n#foreach($column in $tableInfo.pkColumn)\n    /**\n     * 获取主键值\n     *\n     * @return 主键值\n     */\n    @Override\n    protected Serializable pkVal() {\n        return this.$!column.name;\n    }\n    #break\n#end\n}\n"
      }, {
        "name" : "dto.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n##引入mybatis支持\n$!{mybatisSupport.vm}\n\n##保存文件(宏定义)\n#save(\"/entity\", \".java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"entity\")\n\n##自动导入包(全局变量)\nimport com.alibaba.fastjson.annotation.JSONField;\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n#if($tree)\n\nimport com.baomidou.mybatisplus.annotation.TableField;\nimport java.util.List;\n#end\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * $!{tableInfo.comment}($!{tableInfo.name})交互类\n * 字段需要添加 @TableField(exist = false)\n * @author $!author\n * @since $!time.currTime()\n */\n@EqualsAndHashCode(callSuper = true)\n@Data\npublic class $!{tableInfo.name} extends $!{tableInfo.name}Entity {\n\n    // 如何控制,不反给前端某些字段 @JSONField(serialize = false)\n\n    // 如何控制,不被数据库表识别 @TableField(exist = false)\n\n\n    #if($tree)\n    // 因为检测到pid,因此创建树结构的children字段\n    @TableField(exist = false)\n    private List<$!{tableInfo.name}> children;\n    #end\n}\n"
      }, {
        "name" : "addorupdate.vue.vm",
        "code" : "##引入mybatis支持\n$!{mybatisSupport.vm}\n\n\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append('add-or-update', \".vue\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/vue/\",$tableInfo.name))\n\n##拿到主键\n#if(!$tableInfo.pkColumn.isEmpty())\n    #set($pk = $tableInfo.pkColumn.get(0))\n#end\n\n#set($size = $tableInfo.fullColumn.size())\n#set($inputs = $tool.newArrayList())\n#set($areas = $tool.newArrayList())\n#foreach($column in $tableInfo.fullColumn)   \n\n\n#if ($column.ext.sqlType == \"text\"||($column.obj.dataType.length>1000&&$column.ext.sqlType == \"varchar\"))\n#set($xx = $areas.add($column))\n#elseif($column.name != \"projectCode\" && $column.name != \"id\" &&  $column.name != \"updateUser\" && $column.name != \"updateTime\" &&  $column.name != \"createTime\" && $column.name != \"createUser\" && $column.name != \"isDeleted\" && $column.name != \"orderId\" )\n#set($xx = $inputs.add($column))\n#end\n#end\n\n#set($cols = ($inputs.size()+$areas.size())/7+1)\n#if($cols>3)\n#set($cols = 3)\n#end\n\n#set($span = 24/$cols)\n\n#if($cols==3)\n#set($width = 75)\n#elseif($cols==2)\n#set($width = 50)\n#elseif($cols==1)\n#set($width = 30)\n#end\n\n<template>\n  <div>\n    <el-dialog :title=\"title\" width=\"$width%\" :visible.sync=\"visible\" :close-on-click-modal=\"false\" @close=\"close\">\n      <el-form :model=\"dataForm\" :rules=\"dataRule\" @keyup.enter.native=\"dataFormSubmitHandle()\" @submit.native.prevent label-width=\"120px\" size=\"small\" ref=\"dataForm\">\n         \n            #foreach($column in $inputs)\n            #if(($foreach.index % (24/$span)) == 0)\n            <el-row>\n            #end\n            <el-col :span=\"$span\">\n            #if($column.ext.sqlType== \"int\"||$column.ext.sqlType== \"bigint\")\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-input-number :controls=\"false\" v-model=\"dataForm.${column.name}\" style=\"width: 100%\"/>\n            </el-form-item>\n            #elseif($column.ext.sqlType== \"date\")\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-date-picker style=\"width: 100%\" placeholder=\"${column.comment}\" v-model=\"dataForm.${column.name}\" value-format=\"yyyy-MM-dd\" format=\"yyyy-MM-dd\"></el-date-picker>\n            </el-form-item>\n            #elseif($column.ext.sqlType== \"datetime\"||$column.ext.sqlType== \"timestamp\")\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-date-picker style=\"width: 100%\" placeholder=\"${column.comment}\" v-model=\"dataForm.${column.name}\" value-format=\"yyyy-MM-dd HH:mm:ss\" format=\"yyyy-MM-dd HH:mm:ss\"></el-date-picker>\n            </el-form-item>\n            #elseif($column.ext.sqlType== \"tinyint\")\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-select style=\"width: 100%\" placeholder=\"${column.comment}\" v-model=\"dataForm.${column.name}\">\n                    <el-option label=\"是\" :value=\"1\"></el-option>\n                    <el-option label=\"否\" :value=\"0\"></el-option>\n                </el-select>\n            </el-form-item>\n            #elseif($column.ext.sqlType== \"decimal\")\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-input-number style=\"width: 100%\" placeholder=\"${column.comment}\" v-model=\"dataForm.${column.name}\" :controls=\"false\" precision=\"$column.obj.dataType.scale\" />\n            </el-form-item>\n            #else\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-input placeholder=\"${column.comment}\" v-model=\"dataForm.${column.name}\" clearable show-word-limit maxlength=\"$column.obj.dataType.length\"></el-input>         \n            </el-form-item>\n            #end\n            </el-col>\n            #if((($foreach.index+1) % (24/$span)) == 0)\n            </el-row>\n            #end\n            #end\n            \n            #foreach($column in $areas)\n            <el-row>\n            <el-col :span=\"24\">\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <el-input type=\"textarea\" placeholder=\"${column.comment}\" v-model=\"dataForm.${column.name}\" clearable show-word-limit maxlength=\"#if($column.obj.dataType.length<0)65535#else$column.obj.dataType.length#end\"></el-input>         \n            </el-form-item>\n            </el-col>\n            </el-row>\n            #end\n      </el-form>\n      <template slot=\"footer\">\n        <el-button @click=\"handleClose\" size=\"mini\">关闭</el-button>\n        <el-button :disabled=\"!visible||loading\" @click=\"dataFormSubmitHandle()\" size=\"mini\" type=\"primary\">确认</el-button>\n      </template>\n    </el-dialog>\n  </div>\n</template>\n\n<script>\n  import * as api from './api'\n\n  export default {\n    data() {\n      return {\n        visible: false,\n        dataForm: {\n#foreach($column in $tableInfo.fullColumn)\n    #if ($column.name != \"id\" &&  $column.name != \"updateUser\" && $column.name != \"updateTime\" &&  $column.name != \"createTime\" && $column.name != \"createUser\" && $column.name != \"isDeleted\" && $column.name != \"orderId\" )\n          ${column.name}: null #if( $foreach.hasNext ),#end\n    #end      \n#end\n        },\n        title: '',\n        loading: false\n      }\n    },\n    computed: {\n      dataRule() {\n        return {\n#foreach($column in $tableInfo.fullColumn)\n##使用的代码id\n#set($require=false)\n#if ($column.ext.require && $column.name != \"id\" &&  $column.name != \"updateUser\" && $column.name != \"updateTime\" &&  $column.name != \"createTime\" && $column.name != \"createUser\" && $column.name != \"isDeleted\" && $column.name != \"orderId\" )\n#set($require=$column.ext.require)\n#end\n##主键输入\n#set($pkinput=false)\n#if ($column.ext.pkinput)\n#set($pkinput=true)\n#end\n#if((${column.obj.isNotNull()} || $require) && ($column.name != $pkColumn.name || $pkinput) && $column.name != \"createUser\" && $column.name != \"createTime\" && $column.name != \"updateUser\" && $column.name != \"updateTime\"&& $column.name != \"id\" ) \n          ${column.name}: [{ required: true, message: \"$column.comment是必填项!\" , trigger: 'blur' }],\n#end \n#end           \n        }\n      }\n    },\n    methods: {\n      init() {\n        this.title = !this.dataForm.$!{pk.name} ? '新增' : '修改'\n        this.visible = true\n        this.#[[$]]#nextTick(() => {\n          if (this.dataForm.id) this.getInfo()\n        })\n      },\n      handleClose() {\n        let field = Object.keys(this.dataForm).filter(s => this.dataForm[s] || this.dataForm[s] === 0);\n        if (field.length === 0) {\n          this.visible = false\n          return;\n        }\n        this.$confirm(`确认关闭?`, '提示', {\n          confirmButtonText: '确认',\n          cancelButtonText: '取消',\n          type: 'warning'\n        }).then(() => {\n          this.close()\n        }).catch((err) => {\n        })\n      },\n      // 获取信息\n      getInfo() {\n        api.info(this.dataForm.id).then(data => {\n          this.dataForm = data.data\n        })\n      },\n      // 表单提交\n      async dataFormSubmitHandle() {\n        let valid = await this.#[[$]]#refs.dataForm.validate().catch(() => {\n          this.#[[$]]#message.error('校验错误')\n        })\n        if (!valid) return\n        this.loading = true\n        if (this.dataForm.id) {\n          await api.update(this.dataForm).then(res=>{\n            this.$message.success('保存成功')\n          }).catch((err) => {\n            this.loading = false\n            throw err\n          })\n        } else {\n          await api.save(this.dataForm).then(res=>{\n            this.$message.success('保存成功')\n          }).catch((err) => {\n            this.loading = false\n            throw err\n          })\n        }\n\n        this.visible = false\n        this.#[[$]]#emit('refreshDataList', this.dataForm)\n        this.close()\n      },\n      close() {\n        Object.keys(this.dataForm).forEach(k => this.dataForm[k] = null)\n        this.visible = false\n      }\n    },\n    watch: {\n    }\n  }\n</script>\n<style scoped>\n::v-deep .el-row {\n  padding-top:25px;\n}\n::v-deep .el-input-number.is-without-controls .el-input__inner{\n  text-align: left;\n}\n::v-deep .el-input-number.is-without-controls .el-input__inner{\n  text-align: left;\n}\n::v-deep .el-dialog {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  left: 50%;\n  top: 40%;\n  transform: translate(-50%, -40%);\n  margin: 0px !important;\n  max-height:calc(100% - 30px);\n}\n::v-deep  .el-dialog .el-dialog__body{\n  padding-right: 40px;\n  flex:1;\n  overflow-y: auto;\n  padding-bottom: 20px;\n}\n</style>\n"
      }, {
        "name" : "api.js.vm",
        "code" : "##引入mybatis支持\n$!{mybatisSupport.vm}\n\n\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append('api', \".js\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/vue/\",$tableInfo.name))\n\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n\n##拿到主键\n#if(!$tableInfo.pkColumn.isEmpty())\n    #set($pk = $tableInfo.pkColumn.get(0))\n#end\nimport io from '@/module/io'\n\n/** 树查询 */\nexport function tree(payload) {\n  return io.get(`$!tool.firstLowerCase($!tableInfo.name)/tree`, payload, () => {}, () => {}, { emulateJSON: false, contentType: 'application/json'})\n}\n\n/** 树懒加载树查询 */\nexport function treeLazy(payload) {\n  return io.get(`$!tool.firstLowerCase($!tableInfo.name)/treeLazy`, payload, () => {}, () => {}, { emulateJSON: false, contentType: 'application/json'})\n}\n\n/** 分页查询 */\nexport function page(payload) {\n  return io.get(`$!tool.firstLowerCase($!tableInfo.name)/page`, payload, () => {}, () => {}, { emulateJSON: false, contentType: 'application/json'})\n}\n\n/** 列表查询 */\nexport function list() {\n  return io.get(`$!tool.firstLowerCase($!tableInfo.name)/list`)\n}\n\n/** 单条查询 */\nexport function info(id) {\n  return io.get(`$!tool.firstLowerCase($!tableInfo.name)/get/#[[$]]#{id}`)\n}\n\n/** 新增 */\nexport function save(payload) {\n  return io.post(`$!tool.firstLowerCase($!tableInfo.name)`, payload, () => {}, () => {}, { emulateJSON: false, contentType: 'application/json'})\n}\n\n/** 更新 */\nexport function update(payload) {\n  return io.put(`$!tool.firstLowerCase($!tableInfo.name)`, payload, () => {}, () => {}, { emulateJSON: false, contentType: 'application/json'})\n}\n\n/** 删除 */\nexport function remove(payload) {\n  return io.delete(`$!tool.firstLowerCase($!tableInfo.name)?idList=#[[$]]#{payload}`)\n}\n\n/** 导出表模板 */\nexport function exportTemplate(){\n  return new Promise((resolve, reject) => {\n    io.get(`$!tool.firstLowerCase($!tableInfo.name)/export/template`,{},res => {\n      resolve(res)\n    }, e => {\n      reject(e)\n    }, \n    { emulateJSON: false, contentType: \"application/json\",responseType:'blob' }\n  )\n    })\n}\n\n/** 导出表数据 */\nexport function exportData(params){\n  return new Promise((resolve, reject) => {\n    io.get(`$!tool.firstLowerCase($!tableInfo.name)/export/data`,params,res => {\n      resolve(res)\n    }, e => {\n      reject(e)\n    }, \n    { emulateJSON: false, contentType: \"application/json\",responseType:'blob' }\n  )\n    })\n}\n\nexport function importData (params,allowError){\n  return new Promise((resolve, reject) => {\n    io.post(`$!tool.firstLowerCase($!tableInfo.name)/import/data/#[[$]]#{allowError}`, res => {\n      resolve(res)\n    }, e => {\n      reject(e)\n    }, {\n      data: params,\n      responseType:'blob',\n      emulateJSON: false,\n      onUploadProgress(e){}\n      })\n    })\n}\n"
      }, {
        "name" : "tree.vue.vm",
        "code" : "##引入mybatis支持\n$!{mybatisSupport.vm}\n\n\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append('tree', \".vue\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/vue/\",$tableInfo.name))\n\n\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n\n\n#foreach($item in $tableInfo.fullColumn)\n#if($item.name.contains(\"Name\")||$item.name.contains(\"Title\")||$item.name.contains(\"Label\"))\n#set($label = $item.name)\n#break\n#end\n#end\n\n#if($tree)\n<template>\n\n\n  <div style=\"height: 100%\">\n    <div style=\"min-height:45px\">\n        <el-input v-model=\"filterText\" style=\"width: 160px;margin-bottom: 15px;\" size=\"mini\"\n                placeholder=\"输入关键字过滤\" prefix-icon=\"el-icon-search\" clearable></el-input>\n         <span class=\"tree-button\">\n            <el-button  @click=\"addHandle()\" size=\"mini\">新增</el-button>\n          </span>\n    </div>\n\n    <el-tree v-loading=\"treeLoading\" node-key=\"id\" class=\"filter-tree\" :data=\"dictTree\"\n             :default-expanded-keys=\"defaultExpandIds\"\n             :props=\"defaultProps\"\n             :style=\"{'height':heightY-topY + 10 +'px'}\"\n             @node-click=\"handleNodeClick\"\n             @node-contextmenu=\"rightClickOption\"\n             :filter-node-method=\"filterNode\"\n             @node-expand=\"handleNodeExpand\"\n             @node-collapse=\"handleNodeCollapse\"\n             ref=\"classTree\">\n\n    </el-tree>\n\n    <div v-show=\"optionCardShow\" id=\"option-button-group\"\n         :style=\"`left:#[[$]]#{optionCardX}px;top:#[[$]]#{optionCardY}px;`\">\n      <el-button @click=\"addHandle(node)\" class=\"option-card-button\">新增\n      </el-button>\n      <el-button @click=\"updateHandle(node)\" class=\"option-card-button\">编辑\n      </el-button>\n      <el-button @click=\"getTreeData()\" class=\"option-card-button\">刷新\n      </el-button>\n      <el-button @click=\"deleteHandle([node.id])\" class=\"option-card-button\">删除\n      </el-button>\n    </div>\n\n    <add-or-update @refreshDataList=\"getTreeData\" ref=\"addOrUpdate\" v-show=\"addOrUpdateVisible\"></add-or-update>\n\n  </div>\n</template>\n<script>\nimport * as api from './api'\nimport AddOrUpdate from './add-or-update'\n\nexport default {\n  name: 'vue_dmpt_indi_class',\n  components: {\n    AddOrUpdate\n  },\n  data() {\n    return {\n      topY: 285,\n      heightY: document.documentElement.clientHeight,\n      treeLoading: false,\n      addOrUpdateVisible: false,\n      dictTree: [],\n      defaultProps: {\n        children: 'children',\n        label: '${label}'\n      },\n      filterText: '',\n      defaultExpandIds: [],\n      optionCardX: \"\", // 让右键菜单出现在鼠标右键的位置\n      optionCardY: \"\",\n      node: {}, // 将当前节点保存\n      optionCardShow: false, // 控制右键菜单的显示与隐藏\n      treeLevel: null, // 记录当前树层级\n      parentId: null, // 记录当前树层级\n    }\n  },\n  mounted() {\n    window.addEventListener(\"click\", this.handleClickDoc);\n    window.onresize = () => {\n      return (() => {\n        if (typeof (this.onResize) === 'function') {\n          this.onResize({\n            w: document.body.clientWidth,\n            h: document.body.clientHeight\n          })\n        }\n      })()\n    }\n    this.getTreeData()\n  },\n  methods: {\n    onResize(e) {\n      if (e.h >= 400) {\n        this.heightY = e.h\n      }\n    },\n    init() {\n\n    },\n    getTreeData(id) {\n      this.treeLoading = true\n      api.tree({})\n        .then(res => {\n          this.dictTree = res.data\n          if (id) {\n            this.#[[$]]#nextTick(() => {\n              this.#[[$]]#refs.classTree.store.nodesMap[id].expanded = true;\n              this.defaultExpandIds.push(id)\n            })\n          }\n        }).catch(err => {\n        err.msg ? this.#[[$]]#message.error(err.msg) : \"\";\n      }).finally(() => {\n        this.treeLoading = false\n      })\n    },\n\n    // 树节点展开\n    handleNodeExpand(data) {\n      // 保存当前展开的节点\n      let flag = false\n      this.defaultExpandIds.some(item => {\n        if (item === data.id) { // 判断当前节点是否存在, 存在不做处理\n          flag = true\n          return true\n        }\n      })\n      if (!flag) { // 不存在则存到数组里\n        this.defaultExpandIds.push(data.id)\n      }\n    },\n    // 树节点关闭\n    handleNodeCollapse(data) {\n      // 删除当前关闭的节点\n      this.defaultExpandIds.some((item, i) => {\n        if (item === data.id) {\n          this.defaultExpandIds.splice(i, 1)\n        }\n      })\n      this.removeChildrenIds(data) // 这里主要针对多级树状结构,当关闭父节点时,递归删除父节点下的所有子节点\n    },\n    // 删除树子节点\n    removeChildrenIds(data) {\n      const ts = this\n      if (data.children) {\n        data.children.forEach(function (item) {\n          const index = ts.defaultExpandIds.indexOf(item.id)\n          if (index > 0) {\n            ts.defaultExpandIds.splice(index, 1)\n          }\n          ts.removeChildrenIds(item)\n        })\n      }\n    },\n    //过滤树节点\n    filterNode(value, data) {\n      if (!value) return true;\n      return data.className.toLowerCase().indexOf(value.toLowerCase()) !== -1;\n    },\n    //点击树节点触发事件\n    handleNodeClick(data) {\n      this.parentId = data.id\n      this.optionCardShow = false\n      this.#[[$]]#emit(\"node-click\", data)\n    },\n    // 点击鼠标右键触发事件\n    rightClickOption(e, data, n, t) {\n      this.treeLevel = n.level;\n      this.optionCardShow = false;\n      this.optionCardX = e.x; // 让菜单出现在鼠标右键的位置\n      if (n.data.id == 1) {\n        this.optionCardY = e.y;\n      } else {\n        this.optionCardY = e.y - 100;\n      }\n      //cloneObj(n.data)\n      this.node = JSON.parse(JSON.stringify(n.data)); // 将当前节点保存\n      this.optionCardShow = true; // 展示右键菜单\n    },\n    // 点击到树节点以外的区域,隐藏右键菜单\n    handleClickDoc() {\n      this.optionCardShow = false;\n    },\n    addHandle(node) {\n      this.optionCardShow = false\n      this.addOrUpdateVisible = true\n      this.#[[$]]#nextTick(() => {\n        if(!node){\n          node = {}\n          node.id = -1\n          node[this.defaultProps.label]= '根节点'\n        }\n        this.#[[$]]#refs.addOrUpdate.dataForm.pid = node.id\n        this.#[[$]]#refs.addOrUpdate.dataForm.pidName = node[this.defaultProps.label]\n        this.#[[$]]#refs.addOrUpdate.init()\n      })\n    },\n    updateHandle(node) {\n      this.optionCardShow = false\n      this.addOrUpdateVisible = true\n      this.#[[$]]#nextTick(() => {\n        this.#[[$]]#refs.addOrUpdate.dataForm.id = node.id\n        this.#[[$]]#refs.addOrUpdate.init()\n      })\n    },\n    async deleteHandle() {\n      this.optionCardShow = false\n      if(this.node.children.length>0){\n        this.#[[$]]#message.warning('请先删除下级节点!')\n        return\n      }\n      this.#[[$]]#confirm(`是否确定删除选择的项目?`, '提示', {\n        confirmButtonText: '确定',\n        cancelButtonText: '取消',\n        type: 'warning'\n      }).then(() => {\n        let data = [this.node.id]\n        api.remove(data).then(res=>{\n          this.getTreeData()\n        }).catch((err)=>{\n          err.msg ? this.#[[$]]#message.error(err.msg) : '';\n        })\n      }).catch((err) => {\n        this.dataListLoading = false\n        err.msg ? this.#[[$]]#message.error(err.msg) : '';\n      })\n    }\n  },\n  watch: {\n    filterText(val) {//监听树组件搜索关键字变化\n      this.#[[$]]#refs.classTree.filter(val);\n      if (val == '') {\n        this.defaultExpandIds.splice(0, this.defaultExpandIds.length, []);\n        this.getTreeData();\n      }\n    }\n  }\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.dep-card {\n  height: 99%;\n}\n\n.openclassifyManage {\n  margin: 10px 0;\n}\n\n.tree-button {\n  .el-button {\n    margin-bottom: 15px;\n  }\n}\n\n.filter-tree {\n  overflow: hidden;\n  height: 90%;\n  overflow-y: auto;\n  flex: 1;\n\n  .comp-tr-node {\n    display: inline-block;\n    width: 210px;\n\n    span {\n      width: 100%;\n      display: inline-block;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n      overflow: hidden;\n      height: 30px;\n      line-height: 30px;\n    }\n  }\n}\n#option-button-group {\n  z-index: 9999;\n  position: fixed;\n  width: 100px;\n  background: white;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);\n\n  .option-card-button {\n    width: 100%;\n    margin-left: 0;\n    font-size: 10.5px;\n    border-radius: 0;\n    border: 0;\n    background-color: #f5f5f5\n  }\n}\n\n.option-card-button:hover {\n  background-color: #006f4f44\n}\n\n//tree滚动条\n.el-tree:hover::-webkit-scrollbar-thumb {\n  background: #2A455B;\n  min-width: 200px;\n}\n\n.el-tree::-webkit-scrollbar {\n  width: 5px;\n  height: 10px;\n}\n\n.el-tree::-webkit-scrollbar-track {\n  background: transparent;\n  border-radius: 5px;\n  margin: 4px 0;\n}\n\n.el-tree::-webkit-scrollbar-thumb {\n  background: #2A455B;\n  border-radius: 5px;\n}\n.el-tree.scrollbar-show::-webkit-scrollbar-thumb {\n  background: #2A455B;\n}\n\n</style>\n#end"
      }, {
        "name" : "index.vue.vm",
        "code" : "##引入mybatis支持\n$!{mybatisSupport.vm}\n\n\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append('index', \".vue\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/vue/\",$tableInfo.name))\n\n##拿到主键\n#if(!$tableInfo.pkColumn.isEmpty())\n    #set($pk = $tableInfo.pkColumn.get(0))\n#end\n\n#set($tree = $tool.toJson($tableInfo.fullColumn).contains('\"name\":\"pid\"')&&$tool.toJson($tableInfo.fullColumn).contains('\"name\":\"id\"'))\n\n#set($search = $tool.newArrayList())\n\n#foreach($column in $tableInfo.fullColumn)   \n#if($column.name.contains(\"name\")||$column.name.contains(\"Name\")||$column.name.contains(\"title\")||$column.name.contains(\"Title\"))\n#set($xx = $search.add($column))\n#end\n#if($search.index>=4)\n#break\n#end\n#end\n\n#if($search.size()==0)\n#foreach($column in $tableInfo.fullColumn)   \n#set($xx = $search.add($column))\n#if($search.index>=2)\n#break\n#end\n#end\n#end\n\n\n<template>\n  <m-list-construction :hasRouteTitle=\"false\" :customTitle=\"pageTitle\" :isFill=\"true\"\n                       v-loading=\"dataListLoading\" >\n    <template slot=\"content\">\n#if($tree)\n      <div class=\"openclassifyManage\" style=\"height:100%\">\n      <split-pane :min-percent=\"10\" :max-percent=\"30\" :default-percent=\"16.85\" split=\"vertical\">\n          <template slot=\"paneL\">\n            <el-card class=\"dep-card\" style=\"margin-right:10px;\" shadow=\"never\">\n              <mtree @node-click=\"nodeClickHandel\"></mtree>\n            </el-card>\n          </template>\n           <template slot=\"paneR\">\n              <el-card class=\"dep-card\" style=\"margin-left:10px;\" shadow=\"never\">\n#end              \n                <div class=\"button-box\">\n                <div class=\"nav-button-box\">\n                  <el-button @click=\"addOrUpdateHandle()\" size=\"mini\">新增\n                  </el-button>\n                  <el-button @click=\"importHandle()\" size=\"mini\">导入\n                  </el-button>\n                  <el-button @click=\"exportHandle()\" size=\"mini\">导出\n                  </el-button>\n                  <el-button @click=\"deleteHandle()\" size=\"mini\">批量删除\n                  </el-button>\n                </div>\n              \n                    <el-form ref=\"searchForm\" :inline=\"true\" @keyup.enter.native=\"searchHandel()\" @submit.native.prevent  size=\"mini\">\n                        #foreach($column in $search)\n                        <el-form-item>\n                          <el-input clearable placeholder=\"$!column.comment\" v-model=\"dataForm.$!column.name\"></el-input>\n                        </el-form-item>\n                        #end\n                        <el-form-item>\n                           <el-button icon=\"el-icon-search\" @click=\"searchHandel()\" size=\"mini\"></el-button>\n                           <el-button @click=\"resetSearch\" icon=\"el-icon-refresh-right\" size=\"mini\"></el-button>\n                        </el-form-item>\n                   </el-form>\n                </div>\n               \n                <template v-if=\"dataList.length === 0\">\n                <m-no-data></m-no-data>\n              </template>\n              <template v-else>\n                  \n                  <el-table\n                    ref=\"listTable\"\n                    :data=\"dataList\"\n                    @selection-change=\"dataListSelectionChangeHandle\"\n                    @sort-change=\"dataListSortChangeHandle\"\n                    highlight-current-row\n                    :height=\"heightY-topY+'px'\"\n                    style=\"width: 100%;\"\n                    size=\"mini\"\n                    v-loading=\"dataListLoading\">\n                    <el-table-column align=\"center\" header-align=\"center\" type=\"index\" width=\"50\"></el-table-column>\n                    <el-table-column align=\"center\" header-align=\"center\" type=\"selection\" width=\"50\" ></el-table-column>\n                    #foreach($column in $tableInfo.fullColumn)\n                    #if ($column.name == \"projectCode\" ||$column.name == \"id\" ||  $column.name == \"updateUser\" || $column.name == \"updateTime\" || $column.name == \"createUser\" ||$column.name == \"isDeleted\" || $column.name == \"orderId\" )\n                    #elseif($column.ext.sqlType== \"int\"||$column.ext.sqlType== \"bigint\"||$column.ext.sqlType== \"date\"||$column.ext.sqlType== \"datetime\"||$column.ext.sqlType== \"timestamp\"||$column.ext.sqlType== \"decimal\")\n                    <el-table-column prop=\"$!{column.name}\" :sortable=\"true\" label=\"$!{column.comment}\" min-width=\"150\" show-overflow-tooltip align=\"center\"></el-table-column>\n                    #elseif($column.ext.sqlType== \"tinyint\")\n                    <el-table-column prop=\"$!{column.name}\" :sortable=\"true\" label=\"$!{column.comment}\" min-width=\"150\" show-overflow-tooltip align=\"center\">\n                        <template slot-scope=\"scope\">\n                          {{scope.row.${column.name}===1?'是':'否'}}\n                        </template>\n                    </el-table-column>\n                    #elseif($column.ext.sqlType== \"text\")\n                    <el-table-column prop=\"$!{column.name}\" label=\"$!{column.comment}\" min-width=\"250\" show-overflow-tooltip align=\"left\"></el-table-column>\n                    #else\n                    <el-table-column prop=\"$!{column.name}\" label=\"$!{column.comment}\" min-width=\"150\" show-overflow-tooltip align=\"center\"></el-table-column>\n                    #end\n                    #end\n                    <el-table-column align=\"center\" fixed=\"right\" header-align=\"center\" label=\"操作\" width=\"150\">\n                      <template slot-scope=\"scope\">\n                        <el-button @click=\"detailHandle(scope.row.$!pk.name)\" size=\"mini\" type=\"text\">查看\n                        </el-button>\n                        <el-button @click=\"addOrUpdateHandle(scope.row.$!pk.name)\" size=\"mini\" type=\"text\">修改\n                        </el-button>\n                        <el-button @click=\"deleteHandle(scope.row.$!pk.name)\" size=\"mini\" type=\"text\">删除\n                        </el-button>\n                      </template>\n                    </el-table-column>\n                  </el-table>\n                  <div class=\"pagination-box\">\n                      <el-pagination :current-page=\"current\"\n                                     :page-size=\"size\"\n                                     :page-sizes=\"[10, 20, 50, 100]\"\n                                     :total=\"total\"\n                                     @current-change=\"pageCurrentChangeHandle\"\n                                     @size-change=\"pageSizeChangeHandle\"\n                                     layout=\"->,total, sizes, prev, pager, next, jumper\">\n                      </el-pagination>\n                    </div>\n                  \n              </template>\n                  \n                  #if($tree)\n              </el-card>\n           </template>\n      </split-pane>\n       </div>\n      #end\n       \n      <!-- 弹窗, 新增 / 修改 -->\n      <add-or-update @refreshDataList=\"getDataList\" ref=\"addOrUpdate\" v-show=\"addOrUpdateVisible\"></add-or-update>\n      <!-- 弹窗, 详情 -->\n      <detail-dialog ref=\"detail\" v-show=\"detailVisible\"></detail-dialog>\n      <!-- 弹窗, 上传 -->\n      <import-dialog @close=\"getDataList\" ref=\"import\" v-show=\"importVisible\"></import-dialog>\n    </template>\n  </m-list-construction>\n</template>\n\n<script>\n  import mNoData from \"@/module/components/noData/noData\";\n  import mListConstruction from \"@/module/components/listConstruction/listConstruction\";\n  import { fileDownloadEasycode } from '@/module/util'\n  import * as api from './api'\n  \n  import AddOrUpdate from './add-or-update'\n  import detailDialog from './detail'\n  import importDialog from './import'\n  import mtree from './tree.vue'\n  \n  export default {\n    name: 'vue_$tableInfo.obj.name',\n    components: {\n      detailDialog,\n      importDialog,\n      mtree,\n      mNoData,\n      mListConstruction,\n      AddOrUpdate\n    },\n    data() {\n      return {\n        topY: #if($tree)270#else 240 #end,\n        heightY: document.documentElement.clientHeight,\n        pageTitle: '$tableInfo.comment',\n        dataForm: {\n        #foreach($column in $tableInfo.fullColumn)\n        #if($column.type == \"java.lang.String\" && \"create_user\" != $!column.obj.name && \"update_user\" != $!column.obj.name)\n          $!column.name: null,\n        #end\n        #end\n        },\n        dataList: [],// 数据\n        orders: [\n          // isEnable设置为true,前端控制数据排序\n          {column: 'createTime', column_table: 'create_time', asc: false, isEnable: true},\n#foreach($column in $tableInfo.fullColumn)\n#if (($column.shortType ==\"Integer\"||$column.shortType ==\"Long\"||$column.ext.sqlType.contains(\"date\"))&&\n     !($column.name == \"id\" ||  $column.name == \"updateUser\" || $column.name == \"updateTime\" || $column.name == \"createTime\" || $column.name == \"createUser\" ||$column.name == \"isDeleted\" || $column.name == \"orderId\"))\n          {column: '$column.name', column_table: '$column.obj.name', asc: false, isEnable: false},\n#end\n#end\n        ],\n        current: 1, // 当前页码\n        size: 10, // 每页数 size 不会与字段重复\n        total: 0, // 总条数\n        dataListLoading: false,\n        searchShow: false,\n        dataListSelections: [], // 数据列表,多选项\n        addOrUpdateVisible: false,// 新增/更新,弹窗visible状态\n        detailVisible: false,// 详情,弹窗visible状态\n        importVisible: false// 上传,弹窗visible状态\n      }\n    },\n    mounted() {\n      window.onresize = () => {\n        return (() => {\n          if (typeof (this.onResize) === 'function') {\n            this.onResize({\n              w: document.body.clientWidth,\n              h: document.body.clientHeight\n            })\n          }\n        })()\n      }\n      this.getDataList()\n    },\n    methods: {\n      onResize (e) {\n        if (e.h >= 400) {\n          this.heightY = e.h\n        }\n      },\n      init() {\n\n      },\n      searchHandel() {\n        this.current = 1\n        this.getDataList()\n      },\n      resetSearch() {\n       this.$refs['searchForm'].resetFields()\n       this.searchHandel()\n     },\n      getDataList() {\n        let params = {\n          current: this.current,\n          size: this.size,\n          ...this.orders,\n          ...this.dataForm\n        }\n        this.dataSortParam(params)\n        this.dataListLoading = true\n        api.page(params).then((data) => {\n          this.dataList = data.data.records\n          this.total = data.data.total * 1\n        }).catch((err) => {\n          this.dataListLoading = false\n          err.msg ? this.#[[$]]#message.error(err.msg) : '';\n        })\n        this.dataListLoading = false\n      },\n      dataListSelectionChangeHandle(val) {\n        this.dataListSelections = val\n      },\n      // 排序参数设置\n      dataSortParam(params) {\n        let ors = this.orders.filter(s => s.isEnable);\n        for (let i = 0; i < ors.length; i++) {\n          params[\"orders[\" + i + \"].column\"] = ors[i].column_table\n          params[\"orders[\" + i + \"].asc\"] = ors[i].asc\n        }\n      },\n      // 排序\n      dataListSortChangeHandle(data) {\n        this.orders.forEach(s => {\n          if (s.column === data.prop) {\n            s.isEnable = (data.order != null)\n            s.asc = data.order === \"ascending\"\n          }\n        })\n        this.getDataList()\n      },\n      addOrUpdateHandle(id) {\n        this.addOrUpdateVisible = true\n        this.#[[$]]#nextTick(() => {\n          this.#[[$]]#refs.addOrUpdate.dataForm.id = id\n          this.#[[$]]#refs.addOrUpdate.init()\n        })\n      },\n      detailHandle(id) {\n        this.detailVisible = true\n        this.#[[$]]#nextTick(() => {\n          this.#[[$]]#refs.detail.dataForm.id = id\n          this.#[[$]]#refs.detail.init()\n        })\n      },\n      async exportHandle() {\n        if (this.dataList.length > 0) {\n           let params = {\n             current: this.current,\n             size: this.size,\n             ...this.dataForm\n           }\n           this.$message.success('已收到下载请求,正在组装数据,请稍等!')\n           const res = await api.exportData(params);\n           fileDownloadEasycode(res, '下载文件').then(res => {\n            if(res.code === 1){\n              this.#[[$]]#message.error(`暂无数据!`)\n            }\n          }).catch(res => {\n            this.#[[$]]#message.error(res.msg)\n          })\n        \n        }\n      },\n       importHandle() {\n        this.importVisible = true\n        this.#[[$]]#nextTick(() => {\n          this.#[[$]]#refs.import.init()\n        })\n       },\n       deleteHandle (id) {      \n        this.$confirm(`是否确定删除选择的项目?`, '提示', {\n          confirmButtonText: '确定',\n          cancelButtonText: '取消',\n          type: 'warning'\n        }).then(() => {\n          let data = id ? [id] : this.dataListSelections.map(item => item.$!pk.name )\n          this.$message.success('删除成功')\n          api.remove(data).then(res=>{\n            this.getDataList()\n          })\n        }).catch((err) => {\n          this.dataListLoading = false\n          err.msg ? this.#[[$]]#message.error(err.msg) : '';\n        })      \n      },\n      // 分页, 每页条数\n      pageSizeChangeHandle(val) {\n        this.current = 1\n        this.size = val\n        this.getDataList()\n      },\n      // 分页, 当前页\n      pageCurrentChangeHandle(val) {\n        this.current = val\n        this.getDataList()\n      },\n      #if($tree)\n      nodeClickHandel(data){\n        this.#[[$]]#message.warning('//TODO vue_$tableInfo.obj.name点击事件,待处理')\n      }\n      #end\n    }\n  }\n</script>\n\n\n<style lang=\"scss\" scoped>\n #if($tree)\n ::v-deep .splitter-pane-resizer {\n  background: #888;\n  width: 2px !important;\n  margin: 0;\n  margin-left: 0 !important;\n  border: none !important;\n  height: 15px !important;\n  top: calc((100% - 20px) / 2);\n}\n\n::v-deep .splitter-pane-resizer:before {\n  content: \"\";\n  display: block;\n  width: 2px;\n  height: 8px;\n  border-radius: 10px;\n  line-height: 100%;\n  top: calc((100% - 8px) / 2);\n  position: absolute;\n  left: -4px;\n  background: #888;\n}\n\n::v-deep .splitter-pane-resizer:after {\n  content: \"\";\n  display: block;\n  width: 2px;\n  height: 8px;\n  border-radius: 10px;\n  line-height: 100%;\n  top: calc((100% - 8px) / 2);\n  position: absolute;\n  right: -4px;\n  background: #888;\n}\n \n.dep-card {\n  height: 99%;\n}\n\n.openclassifyManage {\n  margin: 10px 0;\n}\n\n.tree-button {\n  .el-button {\n    margin-bottom: 15px;\n  }\n}\n\n.filter-tree {\n  overflow: hidden;\n  height: 90%;\n  overflow-y: auto;\n  flex: 1;\n\n  .comp-tr-node {\n    display: inline-block;\n    width: 210px;\n\n    span {\n      width: 100%;\n      display: inline-block;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n      overflow: hidden;\n      height: 30px;\n      line-height: 30px;\n    }\n  }\n}\n\n::v-deep .splitter-pane-resizer {\n  background: #888;\n  width: 2px !important;\n  margin: 0;\n  margin-left: 0 !important;\n  border: none !important;\n  height: 15px !important;\n  top: calc((100% - 20px) / 2);\n}\n\n::v-deep .splitter-pane-resizer:before {\n  content: \"\";\n  display: block;\n  width: 2px;\n  height: 8px;\n  border-radius: 10px;\n  line-height: 100%;\n  top: calc((100% - 8px) / 2);\n  position: absolute;\n  left: -4px;\n  background: #888;\n}\n\n::v-deep .splitter-pane-resizer:after {\n  content: \"\";\n  display: block;\n  width: 2px;\n  height: 8px;\n  border-radius: 10px;\n  line-height: 100%;\n  top: calc((100% - 8px) / 2);\n  position: absolute;\n  right: -4px;\n  background: #888;\n}\n\n#end\n.button-box{\n  position: relative;\n  width: 100%;\n  display: flex;\n  align-items: flex-start;\n  justify-content: space-between;\n  #if(!$tree)margin-top: 15px;#end\n}\n.pagination-box{\n  position: relative;\n  height: 50px;\n  display: flex;\n  align-items: center;\n  justify-content: flex-end;\n}\n::v-deep .el-form-item{\n  margin-bottom: 15px;\n}\n</style>"
      }, {
        "name" : "import.vue.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n##引入mybatis支持\n$!{mybatisSupport.vm}\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append('import', \".vue\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/vue/\",$tableInfo.name))\n\n\n<template>\n  <div>\n    <el-dialog title=\"导入\" :visible.sync=\"visible\"\n               width=\"450px\" :close-on-click-modal=\"false\" @close=\"close\">\n      <template>\n        <div class=\"import_file_box\">\n          <el-upload style=\"width: 100%\" drag ref=\"upload\" :multiple=\"false\"\n                     :http-request=\"()=>{}\" :before-upload=\"beforeFileUpload\" :on-remove=\"handleRemove\"\n                     :file-list=\"fileList\" :limit=\"1\" :on-exceed=\"handleExceed\" accept=\".xlsx,.xls\">\n            <em class=\"el-icon-upload\"></em>\n            <div class=\"el-upload__text\">将文件拖到此处,或<em>点击上传</em></div>\n          </el-upload>\n\n          <div class=\"import_file_text\">* 仅允许导入xls、xIsx格式文件。<span @click=\"downloadTemplate\"\n                                                                           class=\"download_block\">下载模板</span>\n          </div>\n          <div class=\"import_file_text\">* 数据量与错误数据量,会影响导入效率。\n          </div>\n        </div>\n      </template>\n      <template slot=\"footer\" class=\"dialog-footer\">\n        <div class=\"switch-box\">\n          <el-switch v-model=\"allowError\" size=\"mini\" active-text=\"允许容错\" active-value=\"1\"\n                     inactive-value=\"2\">\n          </el-switch>\n          <el-tooltip effect=\"dark\" placement=\"top\">\n            <div slot=\"content\">\n              允许容错:忽略异常数据,其他正常数据可导入;\n              <br/>\n              不允许容错:不忽略异常数据,数据中任一条异常都会导致所有数据无法导入。\n            </div>\n            <i class=\"el-icon-warning-outline\"></i>\n          </el-tooltip>\n        </div>\n        <el-button @click=\"close\">取 消</el-button>\n        <el-button type=\"primary\" :loading=\"loading\" @click=\"submitImport\">确 定</el-button>\n      </template>\n    </el-dialog>\n  </div>\n</template>\n\n<script>\nimport * as api from './api'\nimport { Message } from 'element-ui';\nimport { fileDownloadEasycode } from '@/module/util'\n\nexport default {\n  data() {\n    return {\n      loading: false,\n      allowError: '2',\n      formData: {},\n      //导入新增\n      fileList: [],\n      form: {\n        fileName: \"\",\n        upFile: \"\",\n        suffix: \"\",\n        fileSize: \"\",\n      },\n      visible:false\n    }\n  },\n  props: {\n  },\n  components: {\n  },\n\n  methods: {\n    init() {\n      this.title = '导入'\n      this.visible = true\n    },\n    handleExceed() {\n      if (this.form.upFile !== null) {\n        this.#[[$]]#message.warning('请先删除已上传文件')\n        return\n      }\n    },\n    beforeFileUpload(file) {//文件校验\n      if (file) {\n        let acceptList = [\"xlsx\", \"xls\"]\n        // 根据文件名获取文件的后缀名\n        let fileType = file.name.split('.').pop().toLowerCase()\n        // 判断文件格式是否符合要求\n        if (acceptList.indexOf(fileType) === -1) {\n          this.#[[$]]#message.error('只能上传 xlsx/xls 格式的文件 !');\n          return false\n        }\n        this.form.fileName = file.name\n        this.form.upFile = file\n        this.form.suffix = file.name.split('.')[1]\n        this.form.fileSize = file.size\n      } else {\n        return\n      }\n    },\n    handleRemove() {\n      this.form = this.$options.data().form\n    },\n    async downloadTemplate() {//下载模板文件\n      let url = ''\n      const res = await api.exportTemplate();\n      fileDownloadEasycode(res, '模板文件').then(res => {\n        if (res.code === 2) {\n          this.#[[$]]#message.success(`下载成功文件!`)\n        }else if(res.code === 1){\n          this.#[[$]]#message.error(`暂无数据!`)\n        }\n        this.loading = false\n      }).catch(res => {\n        this.#[[$]]#message.error(res.msg)\n        this.loading = false\n      })\n    },\n    async submitImport() {//点击确认上传\n      const {upFile} = this.form;\n      if (upFile) {\n        this.loading = true\n        const formData = new FormData();\n        formData.append('file', upFile);\n        let res = await api.importData(formData, this.allowError);\n        fileDownloadEasycode(res, '错误信息').then(res => {\n          if (res.code === 2) {\n            this.#[[$]]#message.success(`错误数据详情,请关注下载文件!`)\n          } else if (res.code === 1) {\n            this.#[[$]]#message.success(`导入成功`)\n            this.close()\n          }\n          this.loading = false\n        }).catch(res => {\n          this.#[[$]]#message.error(res.msg)\n          this.loading = false\n        })\n      } else {\n        this.#[[$]]#message.warning('请选择导入文件!')\n      }\n    },\n    close() {\n      this.visible = false\n      this.fileList = this.$options.data().fileList\n      this.form = this.$options.data().form\n      this.#[[$]]#emit('close')\n    }\n  },\n\n}\n</script>\n\n<style lang=\"scss\" scoped>\n::v-deep .el-upload__input {\n  display: none !important;\n}\n\n::v-deep .el-upload {\n  width: 100%\n}\n\n::v-deep .el-upload-dragger {\n  width: 100%;\n}\n\n.import_file_text {\n  text-align: left;\n  font-size: 13px;\n  color: gray;\n  margin-top: 10px;\n  .download_block {\n    color: #1890ff;\n    cursor: pointer;\n  }\n}\n\n.el-icon-upload {\n  color: #c4e0ff;\n}\n\n.switch-box {\n  position: absolute;\n  left: 15px;\n  margin-top: 10px;\n}\n\n.el-dialog__footer {\n  padding: 10px 20px 20px;\n  text-align: right;\n  box-sizing: border-box;\n  align-items: center;\n  display: flex;\n  justify-content: flex-end;\n}\n::v-deep .el-message__content{\n  line-height: 18px;\n}\n//容错报错弹窗\n.content-error-box{\n  padding: 10px;\n}\n.error-arr-box{\n  position: relative;\n  width: 100%;\n  max-height: 200px;\n  overflow-y: auto;\n  border-radius: 8px;\n  background-color: #fafafa;\n  padding: 10px;\n  font-size: 12px;\n  font-weight: normal;\n  line-height: 20px;\n  color: #666;\n  margin-top: 8px;\n\n}\n.error-arr-box:hover::-webkit-scrollbar-thumb {\n  background: #2A455B;\n  min-width: 200px;\n}\n\n.error-arr-box::-webkit-scrollbar {\n  width: 5px;\n  height: 10px;\n}\n\n.error-arr-box::-webkit-scrollbar-track {\n  background: transparent;\n  border-radius: 5px;\n  margin: 4px 0;\n}\n\n.error-arr-box::-webkit-scrollbar-thumb {\n  background: #2A455B;\n  border-radius: 5px;\n}\n.error-arr-box.scrollbar-show::-webkit-scrollbar-thumb {\n  background: #2A455B;\n}\n.error-arr-title{\n  position: relative;\n  font-weight: 400;\n  margin-top: 16px;\n}\n.error-arr-title-icon{\n  width: 10px;\n  height: 10px;\n  background: #006f4f;\n  border-radius: 50%;\n  position: relative;\n  display: inline-block;\n  margin-right: 3px;\n}\n</style>\n"
      }, {
        "name" : "detail.vue.vm",
        "code" : "##引入mybatis支持\n$!{mybatisSupport.vm}\n\n##设置保存名称与保存位置\n$!callback.setFileName($tool.append('detail', \".vue\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/vue/\",$tableInfo.name))\n\n##拿到主键\n#if(!$tableInfo.pkColumn.isEmpty())\n    #set($pk = $tableInfo.pkColumn.get(0))\n#end\n\n#set($size = $tableInfo.fullColumn.size())\n#set($inputs = $tool.newArrayList())\n#set($areas = $tool.newArrayList())\n#foreach($column in $tableInfo.fullColumn)   \n\n\n#if ($column.ext.sqlType == \"text\"||($column.obj.dataType.length>1000&&$column.ext.sqlType == \"varchar\"))\n#set($xx = $areas.add($column))\n#elseif($column.name != \"projectCode\" && $column.name != \"id\" &&  $column.name != \"updateUser\" && $column.name != \"updateTime\" &&  $column.name != \"createTime\" && $column.name != \"createUser\" && $column.name != \"isDeleted\" && $column.name != \"orderId\" )\n#set($xx = $inputs.add($column))\n#end\n#end\n\n#set($cols = ($inputs.size()+$areas.size())/7+1)\n#if($cols>3)\n#set($cols = 3)\n#end\n\n#set($span = 24/$cols)\n\n#if($cols==3)\n#set($width = 75)\n#elseif($cols==2)\n#set($width = 50)\n#elseif($cols==1)\n#set($width = 30)\n#end\n\n\n\n<template>\n  <div>\n    <el-dialog title=\"查看\" width=\"$width%\" :visible.sync=\"visible\" :close-on-click-modal=\"false\">\n          <template>\n        <div class=\"create-menu-model\">\n          <el-form :model=\"dataForm\" label-width=\"120px\" size=\"small\" ref=\"dataForm\">\n            #foreach($column in $inputs)\n                #if(($foreach.index % (24/$span)) == 0)\n                <el-row>\n                #end\n                <el-col :span=\"$span\">\n                #if($column.ext.sqlType== \"tinyint\")\n                <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                    <div>\n                        {{dataForm.${column.name}===1?'是':'否'}}\n                    </div>\n                </el-form-item>\n                #else\n                <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                    <div>\n                        {{dataForm.${column.name}}}\n                    </div>\n                </el-form-item>\n                #end\n                </el-col>\n                #if((($foreach.index+1) % (24/$span)) == 0)\n                </el-row>\n                #end\n            #end\n            \n            #foreach($column in $areas)\n            <el-row>\n            <el-col :span=\"24\">\n            <el-form-item label=\"${column.comment}\" label-width=\"120px\" prop=\"${column.name}\">\n                <div>\n                    {{dataForm.${column.name}}}\n                </div>\n            </el-form-item>\n            </el-col>\n            </el-row>\n            #end\n          \n          </el-form>\n        </div>\n      </template>\n      <template slot=\"footer\">\n        <el-button @click=\"handleClose\" size=\"mini\">关闭</el-button>\n      </template>\n    </el-dialog>\n  </div>\n</template>\n\n<script>\n  import * as api from './api'\n\n  export default {\n    data() {\n      return {\n        nowCol: $!cols,\n        visible: false,\n        dataForm: {\n#foreach($column in $tableInfo.fullColumn)\n    #if ($column.name != \"id\" &&  $column.name != \"updateUser\" && $column.name != \"updateTime\" &&  $column.name != \"createTime\" && $column.name != \"createUser\" && $column.name != \"isDeleted\" && $column.name != \"orderId\" )\n          ${column.name}: null #if( $foreach.hasNext ),#end\n    #end      \n#end\n        }\n      }\n    },\n    computed: {\n      \n    },\n    methods: {\n      init() {\n        this.visible = true\n        this.#[[$]]#nextTick(() => {\n          if (this.dataForm.id) this.getInfo()\n        })\n      },\n      handleClose() {\n          this.visible = false\n      },\n      // 获取信息\n      getInfo() {\n        api.info(this.dataForm.id).then(data => {\n          this.dataForm = data.data\n        })\n      }\n    },\n    watch: {\n      \n    }\n  }\n</script>\n<style lang=\"scss\" scoped>\n::v-deep .el-form-item {\n  margin-bottom: 5px;\n}\n\n::v-deep label {\n  font-weight: 400;\n}\n\n::v-deep .el-dialog .el-dialog__body {\n  padding: 10px 23px;\n  /* padding-right: 40px; */\n}\n\n::v-deep .el-dialog {\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  left: 50%;\n  top: 40%;\n  transform: translate(-50%, -40%);\n  margin: 0px !important;\n  max-height:calc(100% - 30px);\n}\n::v-deep  .el-dialog .el-dialog__body{\n  padding-right: 40px;\n  flex:1;\n  overflow-y: auto;\n  padding-bottom: 20px;\n}\n\n.el-dialog .el-form .el-form-item {\n  margin-bottom: 20px\n}\n\n::v-deep .el-select {\n  position: relative;\n  width: 100%;\n}\n</style>\n"
      }, {
        "name" : "excel.java.vm",
        "code" : "##导入宏定义\n$!{define.vm}\n##引入mybatis支持\n$!{mybatisSupport.vm}\n\n##保存文件(宏定义)\n#save(\"/excel\", \".java\")\n\n##包路径(宏定义)\n#setPackageSuffix(\"excel\")\n\n$!callback.setFileName($tool.append($!{tableInfo.name}, \"Excel.java\"))\n$!callback.setSavePath($tool.append($tableInfo.savePath, \"/excel/\"))\n\n##自动导入包(全局变量)\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport cn.dmp.common.easycode.EasyCodeConfig;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\n\n/**\n * $!{tableInfo.comment}($!{tableInfo.name})Excel 模板\n * @author $!author\n * @since $!time.currTime()\n */\n@Data\npublic class $!{tableInfo.name}Excel {\n    // 导出字段配置,字段名、字段配置 请注意修改表字段后 需要同步这里!!\n\n#foreach($column in $tableInfo.fullColumn)\n#if($!column.name!=\"id\"&&$!column.name!=\"createTime\"&&$!column.name!=\"createUser\"&&$!column.name!=\"updateTime\"&&$!column.name!=\"updateUser\"&&$!column.name!=\"isDeleted\")\n    #if($column.ext.sqlType=='date')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length ,tip = \"日期类型,格式:1999-12-01\", type = \"date\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #elseif($column.ext.sqlType=='datetime'||$column.ext.sqlType=='timestampe')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length ,tip = \"时间类型,格式:1999-12-01 23:01:04\", type = \"datetime\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #elseif($column.ext.sqlType=='int')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length ,tip = \"整数类型,范围:-2,147,483,648 到 2,147,483,64\", type = \"$column.ext.sqlType\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #elseif($column.ext.sqlType=='bigint')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length ,tip = \"长整数类型,范围:-2^63 到 2^63-1\", type = \"$column.ext.sqlType\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #elseif($column.ext.sqlType=='tinyint')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length ,tip = \"布尔类型,只允许是/否\", type = \"$column.ext.sqlType\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #elseif($column.ext.sqlType == 'decimal')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length , scale = $column.obj.dataType.scale ,tip = \"小数类型,限制${column.obj.dataType.scale}小数位\", type = \"$column.ext.sqlType\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #elseif( $column.ext.sqlType=='text')\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= 65535 ,tip = \"字符类型,限制${column.obj.dataType.length}个字符\", type = \"$column.ext.sqlType\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #else\n    @EasyCodeConfig(title = \"${column.comment}\",propName = \"${column.name}\" ,length= $column.obj.dataType.length ,tip = \"字符类型,限制${column.obj.dataType.length}个字符\", type = \"varchar\" ,noNull = ${column.obj.notNull},comment = \"${column.comment}\")\n    #end\n    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};\n#end\n#end\n}\n"
      } ]
    }
  },
  "columnConfig" : {
    "Default" : {
      "name" : "Default",
      "elementList" : [ {
        "title" : "disable",
        "type" : "BOOLEAN",
        "selectValue" : ""
      }, {
        "title" : "support",
        "type" : "SELECT",
        "selectValue" : "add,edit,query,del,ui"
      } ]
    }
  },
  "globalConfig" : {
    "Default" : {
      "name" : "Default",
      "elementList" : [ {
        "name" : "autoImport.vm",
        "value" : "##自动导入包(仅导入实体属性需要的包,通常用于实体类)\n#foreach($import in $importList)\nimport $!import;\n#end"
      }, {
        "name" : "define.vm",
        "value" : "##(Velocity宏定义)\n\n##定义设置表名后缀的宏定义,调用方式:#setTableSuffix(\"Test\")\n#macro(setTableSuffix $suffix)\n    #set($tableName = $!tool.append($tableInfo.name, $suffix))\n#end\n\n##定义设置包名后缀的宏定义,调用方式:#setPackageSuffix(\"Test\")\n#macro(setPackageSuffix $suffix)\n#if($suffix!=\"\")package #end#if($tableInfo.savePackageName!=\"\")$!{tableInfo.savePackageName}.#{end}$!suffix;\n#end\n\n##定义直接保存路径与文件名简化的宏定义,调用方式:#save(\"/entity\", \".java\")\n#macro(save $path $fileName)\n    $!callback.setSavePath($tool.append($tableInfo.savePath, $path))\n    $!callback.setFileName($tool.append($tableInfo.name, $fileName))\n#end\n\n##定义表注释的宏定义,调用方式:#tableComment(\"注释信息\")\n#macro(tableComment $desc)\n/**\n * $!{tableInfo.comment}($!{tableInfo.name})$desc\n *\n * @author $!author\n * @since $!time.currTime()\n */\n#end\n\n##定义GET,SET方法的宏定义,调用方式:#getSetMethod($column)\n#macro(getSetMethod $column)\n\n    public $!{tool.getClsNameByFullName($column.type)} get$!{tool.firstUpperCase($column.name)}() {\n        return $!{column.name};\n    }\n\n    public void set$!{tool.firstUpperCase($column.name)}($!{tool.getClsNameByFullName($column.type)} $!{column.name}) {\n        this.$!{column.name} = $!{column.name};\n    }\n#end"
      }, {
        "name" : "init.vm",
        "value" : "##初始化区域\n\n##去掉表的t_前缀\n$!tableInfo.setName($tool.getClassName($tableInfo.obj.name.replaceFirst(\"book_\",\"\")))\n\n##参考阿里巴巴开发手册,POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误\n#foreach($column in $tableInfo.fullColumn)\n#if($column.name.startsWith(\"is\") && $column.type.equals(\"java.lang.Boolean\"))\n    $!column.setName($tool.firstLowerCase($column.name.substring(2)))\n#end\n#end\n\n##实现动态排除列\n#set($temp = $tool.newHashSet(\"testCreateTime\", \"otherColumn\"))\n#foreach($item in $temp)\n    #set($newList = $tool.newArrayList())\n    #foreach($column in $tableInfo.fullColumn)\n        #if($column.name!=$item)\n            ##带有反回值的方法调用时使用$tool.call来消除返回值\n            $tool.call($newList.add($column))\n        #end\n    #end\n    ##重新保存\n    $tableInfo.setFullColumn($newList)\n#end\n\n##对importList进行篡改\n#set($temp = $tool.newHashSet())\n#foreach($column in $tableInfo.fullColumn)\n    #if(!$column.type.startsWith(\"java.lang.\"))\n        ##带有反回值的方法调用时使用$tool.call来消除返回值\n        $tool.call($temp.add($column.type))\n    #end\n#end\n##覆盖\n#set($importList = $temp)"
      }, {
        "name" : "mybatisSupport.vm",
        "value" : "##针对Mybatis 进行支持,主要用于生成xml文件\n#foreach($column in $tableInfo.fullColumn)\n    ##储存列类型\n    $tool.call($column.ext.put(\"sqlType\", $tool.getField($column.obj.dataType, \"typeName\")))\n    #if($tool.newHashSet(\"java.lang.String\").contains($column.type))\n        #set($jdbcType=\"VARCHAR\")\n    #elseif($tool.newHashSet(\"java.lang.Boolean\", \"boolean\").contains($column.type))\n        #set($jdbcType=\"BOOLEAN\")\n    #elseif($tool.newHashSet(\"java.lang.Byte\", \"byte\").contains($column.type))\n        #set($jdbcType=\"BYTE\")\n    #elseif($tool.newHashSet(\"java.lang.Integer\", \"int\", \"java.lang.Short\", \"short\").contains($column.type))\n        #set($jdbcType=\"INTEGER\")\n    #elseif($tool.newHashSet(\"java.lang.Long\", \"long\").contains($column.type))\n        #set($jdbcType=\"INTEGER\")\n    #elseif($tool.newHashSet(\"java.lang.Float\", \"float\", \"java.lang.Double\", \"double\").contains($column.type))\n        #set($jdbcType=\"NUMERIC\")\n    #elseif($tool.newHashSet(\"java.util.Date\", \"java.sql.Timestamp\", \"java.time.Instant\", \"java.time.LocalDateTime\", \"java.time.OffsetDateTime\", \"\tjava.time.ZonedDateTime\").contains($column.type))\n        #set($jdbcType=\"TIMESTAMP\")\n    #elseif($tool.newHashSet(\"java.sql.Date\", \"java.time.LocalDate\").contains($column.type))\n        #set($jdbcType=\"TIMESTAMP\")\n    #else\n        ##其他类型\n        #set($jdbcType=\"VARCHAR\")\n    #end\n    $tool.call($column.ext.put(\"jdbcType\", $jdbcType))\n#end\n\n##定义宏,查询所有列\n#macro(allSqlColumn)#foreach($column in $tableInfo.fullColumn)$column.obj.name#if($velocityHasNext), #end#end#end\n"
      } ]
    }
  }
}

前端效果展示

tree 结构

支持左右拖拽

普通结构

新增、修改

数据查看

导入、导出

导出模板

数据批改

 数据导出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值