Commit 67c3a62dcffb86fd07758cca29b5783cf54c629d
1 parent
753c7678
开始开发代码生成器,完成数据库 information_schema 的读取
Showing
25 changed files
with
523 additions
and
246 deletions
pom.xml
| @@ -37,7 +37,6 @@ | @@ -37,7 +37,6 @@ | ||
| 37 | <!-- <commons.fileupload.version>1.3.3</commons.fileupload.version>--> | 37 | <!-- <commons.fileupload.version>1.3.3</commons.fileupload.version>--> |
| 38 | <!-- <poi.version>4.1.2</poi.version>--> | 38 | <!-- <poi.version>4.1.2</poi.version>--> |
| 39 | <!-- <velocity.version>1.7</velocity.version>--> | 39 | <!-- <velocity.version>1.7</velocity.version>--> |
| 40 | -<!-- <jwt.version>0.9.1</jwt.version>--> | ||
| 41 | 40 | ||
| 42 | <!-- Web 相关 --> | 41 | <!-- Web 相关 --> |
| 43 | <knife4j.version>3.0.2</knife4j.version> | 42 | <knife4j.version>3.0.2</knife4j.version> |
| @@ -169,6 +168,13 @@ | @@ -169,6 +168,13 @@ | ||
| 169 | <version>${spring-boot-admin.version}</version> | 168 | <version>${spring-boot-admin.version}</version> |
| 170 | </dependency> | 169 | </dependency> |
| 171 | 170 | ||
| 171 | + <!-- Test 测试相关 --> | ||
| 172 | + <dependency> | ||
| 173 | + <groupId>org.springframework.boot</groupId> | ||
| 174 | + <artifactId>spring-boot-starter-test</artifactId> | ||
| 175 | + <scope>test</scope> | ||
| 176 | + </dependency> | ||
| 177 | + | ||
| 172 | <!-- 工具类相关 --> | 178 | <!-- 工具类相关 --> |
| 173 | <dependency> | 179 | <dependency> |
| 174 | <groupId>org.projectlombok</groupId> | 180 | <groupId>org.projectlombok</groupId> |
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
| @@ -5,105 +5,158 @@ package com.ruoyi.common.constant; | @@ -5,105 +5,158 @@ package com.ruoyi.common.constant; | ||
| 5 | * | 5 | * |
| 6 | * @author ruoyi | 6 | * @author ruoyi |
| 7 | */ | 7 | */ |
| 8 | -public class GenConstants | ||
| 9 | -{ | ||
| 10 | - /** 单表(增删改查) */ | ||
| 11 | - public static final String TPL_CRUD = "crud"; | 8 | +public class GenConstants { |
| 12 | 9 | ||
| 13 | - /** 树表(增删改查) */ | ||
| 14 | - public static final String TPL_TREE = "tree"; | ||
| 15 | - | ||
| 16 | - | ||
| 17 | - /** 树编码字段 */ | 10 | + /** |
| 11 | + * 树编码字段 | ||
| 12 | + */ | ||
| 18 | public static final String TREE_CODE = "treeCode"; | 13 | public static final String TREE_CODE = "treeCode"; |
| 19 | 14 | ||
| 20 | - /** 树父编码字段 */ | 15 | + /** |
| 16 | + * 树父编码字段 | ||
| 17 | + */ | ||
| 21 | public static final String TREE_PARENT_CODE = "treeParentCode"; | 18 | public static final String TREE_PARENT_CODE = "treeParentCode"; |
| 22 | 19 | ||
| 23 | - /** 树名称字段 */ | 20 | + /** |
| 21 | + * 树名称字段 | ||
| 22 | + */ | ||
| 24 | public static final String TREE_NAME = "treeName"; | 23 | public static final String TREE_NAME = "treeName"; |
| 25 | 24 | ||
| 26 | - /** 上级菜单ID字段 */ | 25 | + /** |
| 26 | + * 上级菜单ID字段 | ||
| 27 | + */ | ||
| 27 | public static final String PARENT_MENU_ID = "parentMenuId"; | 28 | public static final String PARENT_MENU_ID = "parentMenuId"; |
| 28 | 29 | ||
| 29 | - /** 上级菜单名称字段 */ | 30 | + /** |
| 31 | + * 上级菜单名称字段 | ||
| 32 | + */ | ||
| 30 | public static final String PARENT_MENU_NAME = "parentMenuName"; | 33 | public static final String PARENT_MENU_NAME = "parentMenuName"; |
| 31 | 34 | ||
| 32 | - /** 数据库字符串类型 */ | ||
| 33 | - public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; | ||
| 34 | - | ||
| 35 | - /** 数据库文本类型 */ | ||
| 36 | - public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; | ||
| 37 | - | ||
| 38 | - /** 数据库时间类型 */ | ||
| 39 | - public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; | ||
| 40 | - | ||
| 41 | - /** 数据库数字类型 */ | ||
| 42 | - public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", | ||
| 43 | - "bit", "bigint", "float", "double", "decimal" }; | ||
| 44 | - | ||
| 45 | - /** 页面不需要编辑字段 */ | ||
| 46 | - public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; | ||
| 47 | - | ||
| 48 | - /** 页面不需要显示的列表字段 */ | ||
| 49 | - public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", | ||
| 50 | - "update_time" }; | ||
| 51 | - | ||
| 52 | - /** 页面不需要查询字段 */ | ||
| 53 | - public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", | ||
| 54 | - "update_time", "remark" }; | ||
| 55 | - | ||
| 56 | - /** Entity基类字段 */ | ||
| 57 | - public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; | ||
| 58 | - | ||
| 59 | - /** Tree基类字段 */ | ||
| 60 | - public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; | ||
| 61 | - | ||
| 62 | - /** 文本框 */ | 35 | + /** |
| 36 | + * 数据库字符串类型 | ||
| 37 | + */ | ||
| 38 | + public static final String[] COLUMNTYPE_STR = {"char", "varchar", "nvarchar", "varchar2"}; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 数据库文本类型 | ||
| 42 | + */ | ||
| 43 | + public static final String[] COLUMNTYPE_TEXT = {"tinytext", "text", "mediumtext", "longtext"}; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 数据库时间类型 | ||
| 47 | + */ | ||
| 48 | + public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"}; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 数据库数字类型 | ||
| 52 | + */ | ||
| 53 | + public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", | ||
| 54 | + "bit", "bigint", "float", "double", "decimal"}; | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 页面不需要编辑字段 | ||
| 58 | + */ | ||
| 59 | + public static final String[] COLUMNNAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"}; | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 页面不需要显示的列表字段 | ||
| 63 | + */ | ||
| 64 | + public static final String[] COLUMNNAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by", | ||
| 65 | + "update_time"}; | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * 页面不需要查询字段 | ||
| 69 | + */ | ||
| 70 | + public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by", | ||
| 71 | + "update_time", "remark"}; | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Entity基类字段 | ||
| 75 | + */ | ||
| 76 | + public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"}; | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * Tree基类字段 | ||
| 80 | + */ | ||
| 81 | + public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors", "children"}; | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * 文本框 | ||
| 85 | + */ | ||
| 63 | public static final String HTML_INPUT = "input"; | 86 | public static final String HTML_INPUT = "input"; |
| 64 | 87 | ||
| 65 | - /** 文本域 */ | 88 | + /** |
| 89 | + * 文本域 | ||
| 90 | + */ | ||
| 66 | public static final String HTML_TEXTAREA = "textarea"; | 91 | public static final String HTML_TEXTAREA = "textarea"; |
| 67 | 92 | ||
| 68 | - /** 下拉框 */ | 93 | + /** |
| 94 | + * 下拉框 | ||
| 95 | + */ | ||
| 69 | public static final String HTML_SELECT = "select"; | 96 | public static final String HTML_SELECT = "select"; |
| 70 | 97 | ||
| 71 | - /** 单选框 */ | 98 | + /** |
| 99 | + * 单选框 | ||
| 100 | + */ | ||
| 72 | public static final String HTML_RADIO = "radio"; | 101 | public static final String HTML_RADIO = "radio"; |
| 73 | 102 | ||
| 74 | - /** 复选框 */ | 103 | + /** |
| 104 | + * 复选框 | ||
| 105 | + */ | ||
| 75 | public static final String HTML_CHECKBOX = "checkbox"; | 106 | public static final String HTML_CHECKBOX = "checkbox"; |
| 76 | 107 | ||
| 77 | - /** 日期控件 */ | 108 | + /** |
| 109 | + * 日期控件 | ||
| 110 | + */ | ||
| 78 | public static final String HTML_DATETIME = "datetime"; | 111 | public static final String HTML_DATETIME = "datetime"; |
| 79 | 112 | ||
| 80 | - /** 上传控件 */ | 113 | + /** |
| 114 | + * 上传控件 | ||
| 115 | + */ | ||
| 81 | public static final String HTML_UPLOAD_IMAGE = "uploadImage"; | 116 | public static final String HTML_UPLOAD_IMAGE = "uploadImage"; |
| 82 | 117 | ||
| 83 | - /** 富文本控件 */ | 118 | + /** |
| 119 | + * 富文本控件 | ||
| 120 | + */ | ||
| 84 | public static final String HTML_EDITOR = "editor"; | 121 | public static final String HTML_EDITOR = "editor"; |
| 85 | 122 | ||
| 86 | - /** 字符串类型 */ | 123 | + /** |
| 124 | + * 字符串类型 | ||
| 125 | + */ | ||
| 87 | public static final String TYPE_STRING = "String"; | 126 | public static final String TYPE_STRING = "String"; |
| 88 | 127 | ||
| 89 | - /** 整型 */ | 128 | + /** |
| 129 | + * 整型 | ||
| 130 | + */ | ||
| 90 | public static final String TYPE_INTEGER = "Integer"; | 131 | public static final String TYPE_INTEGER = "Integer"; |
| 91 | 132 | ||
| 92 | - /** 长整型 */ | 133 | + /** |
| 134 | + * 长整型 | ||
| 135 | + */ | ||
| 93 | public static final String TYPE_LONG = "Long"; | 136 | public static final String TYPE_LONG = "Long"; |
| 94 | 137 | ||
| 95 | - /** 浮点型 */ | 138 | + /** |
| 139 | + * 浮点型 | ||
| 140 | + */ | ||
| 96 | public static final String TYPE_DOUBLE = "Double"; | 141 | public static final String TYPE_DOUBLE = "Double"; |
| 97 | 142 | ||
| 98 | - /** 高精度计算类型 */ | 143 | + /** |
| 144 | + * 高精度计算类型 | ||
| 145 | + */ | ||
| 99 | public static final String TYPE_BIGDECIMAL = "BigDecimal"; | 146 | public static final String TYPE_BIGDECIMAL = "BigDecimal"; |
| 100 | 147 | ||
| 101 | - /** 时间类型 */ | 148 | + /** |
| 149 | + * 时间类型 | ||
| 150 | + */ | ||
| 102 | public static final String TYPE_DATE = "Date"; | 151 | public static final String TYPE_DATE = "Date"; |
| 103 | 152 | ||
| 104 | - /** 模糊查询 */ | 153 | + /** |
| 154 | + * 模糊查询 | ||
| 155 | + */ | ||
| 105 | public static final String QUERY_LIKE = "LIKE"; | 156 | public static final String QUERY_LIKE = "LIKE"; |
| 106 | 157 | ||
| 107 | - /** 需要 */ | 158 | + /** |
| 159 | + * 需要 | ||
| 160 | + */ | ||
| 108 | public static final String REQUIRE = "1"; | 161 | public static final String REQUIRE = "1"; |
| 109 | } | 162 | } |
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
| @@ -3,6 +3,7 @@ package com.ruoyi.generator.domain; | @@ -3,6 +3,7 @@ package com.ruoyi.generator.domain; | ||
| 3 | import java.util.List; | 3 | import java.util.List; |
| 4 | import javax.validation.Valid; | 4 | import javax.validation.Valid; |
| 5 | import javax.validation.constraints.NotBlank; | 5 | import javax.validation.constraints.NotBlank; |
| 6 | + | ||
| 6 | import org.apache.commons.lang3.ArrayUtils; | 7 | import org.apache.commons.lang3.ArrayUtils; |
| 7 | import com.ruoyi.common.constant.GenConstants; | 8 | import com.ruoyi.common.constant.GenConstants; |
| 8 | import com.ruoyi.common.core.domain.BaseEntity; | 9 | import com.ruoyi.common.core.domain.BaseEntity; |
| @@ -13,108 +14,87 @@ import com.ruoyi.common.utils.StringUtils; | @@ -13,108 +14,87 @@ import com.ruoyi.common.utils.StringUtils; | ||
| 13 | * | 14 | * |
| 14 | * @author ruoyi | 15 | * @author ruoyi |
| 15 | */ | 16 | */ |
| 16 | -public class GenTable extends BaseEntity | ||
| 17 | -{ | ||
| 18 | - private static final long serialVersionUID = 1L; | ||
| 19 | - | ||
| 20 | - /** 编号 */ | ||
| 21 | - private Long tableId; | ||
| 22 | - | ||
| 23 | - /** 表名称 */ | ||
| 24 | - @NotBlank(message = "表名称不能为空") | ||
| 25 | - private String tableName; | ||
| 26 | - | ||
| 27 | - /** 表描述 */ | ||
| 28 | - @NotBlank(message = "表描述不能为空") | ||
| 29 | - private String tableComment; | ||
| 30 | - | ||
| 31 | - /** 实体类名称(首字母大写) */ | ||
| 32 | - @NotBlank(message = "实体类名称不能为空") | ||
| 33 | - private String className; | 17 | +public class GenTable extends BaseEntity { |
| 34 | 18 | ||
| 35 | - /** 使用的模板(crud单表操作 tree树表操作) */ | ||
| 36 | - private String tplCategory; | ||
| 37 | - | ||
| 38 | - /** 生成包路径 */ | 19 | + /** |
| 20 | + * 生成包路径 | ||
| 21 | + */ | ||
| 39 | @NotBlank(message = "生成包路径不能为空") | 22 | @NotBlank(message = "生成包路径不能为空") |
| 40 | private String packageName; | 23 | private String packageName; |
| 41 | 24 | ||
| 42 | - /** 生成模块名 */ | ||
| 43 | - @NotBlank(message = "生成模块名不能为空") | ||
| 44 | - private String moduleName; | ||
| 45 | - | ||
| 46 | - /** 生成业务名 */ | ||
| 47 | - @NotBlank(message = "生成业务名不能为空") | ||
| 48 | - private String businessName; | ||
| 49 | - | ||
| 50 | - /** 生成功能名 */ | ||
| 51 | - @NotBlank(message = "生成功能名不能为空") | ||
| 52 | - private String functionName; | ||
| 53 | - | ||
| 54 | - /** 生成作者 */ | ||
| 55 | - @NotBlank(message = "作者不能为空") | ||
| 56 | - private String functionAuthor; | ||
| 57 | - | ||
| 58 | - /** 生成代码方式(0zip压缩包 1自定义路径) */ | 25 | + /** |
| 26 | + * 生成代码方式(0zip压缩包 1自定义路径) | ||
| 27 | + */ | ||
| 59 | private String genType; | 28 | private String genType; |
| 60 | 29 | ||
| 61 | - /** 生成路径(不填默认项目路径) */ | 30 | + /** |
| 31 | + * 生成路径(不填默认项目路径) | ||
| 32 | + */ | ||
| 62 | private String genPath; | 33 | private String genPath; |
| 63 | 34 | ||
| 64 | - /** 主键信息 */ | 35 | + /** |
| 36 | + * 主键信息 | ||
| 37 | + */ | ||
| 65 | private GenTableColumn pkColumn; | 38 | private GenTableColumn pkColumn; |
| 66 | 39 | ||
| 67 | - /** 表列信息 */ | 40 | + /** |
| 41 | + * 表列信息 | ||
| 42 | + */ | ||
| 68 | @Valid | 43 | @Valid |
| 69 | private List<GenTableColumn> columns; | 44 | private List<GenTableColumn> columns; |
| 70 | 45 | ||
| 71 | - /** 其它生成选项 */ | 46 | + /** |
| 47 | + * 其它生成选项 | ||
| 48 | + */ | ||
| 72 | private String options; | 49 | private String options; |
| 73 | 50 | ||
| 74 | - /** 树编码字段 */ | 51 | + /** |
| 52 | + * 树编码字段 | ||
| 53 | + */ | ||
| 75 | private String treeCode; | 54 | private String treeCode; |
| 76 | 55 | ||
| 77 | - /** 树父编码字段 */ | 56 | + /** |
| 57 | + * 树父编码字段 | ||
| 58 | + */ | ||
| 78 | private String treeParentCode; | 59 | private String treeParentCode; |
| 79 | 60 | ||
| 80 | - /** 树名称字段 */ | 61 | + /** |
| 62 | + * 树名称字段 | ||
| 63 | + */ | ||
| 81 | private String treeName; | 64 | private String treeName; |
| 82 | 65 | ||
| 83 | - /** 上级菜单ID字段 */ | 66 | + /** |
| 67 | + * 上级菜单ID字段 | ||
| 68 | + */ | ||
| 84 | private String parentMenuId; | 69 | private String parentMenuId; |
| 85 | 70 | ||
| 86 | - /** 上级菜单名称字段 */ | 71 | + /** |
| 72 | + * 上级菜单名称字段 | ||
| 73 | + */ | ||
| 87 | private String parentMenuName; | 74 | private String parentMenuName; |
| 88 | 75 | ||
| 89 | - public boolean isTree() | ||
| 90 | - { | 76 | + public boolean isTree() { |
| 91 | return isTree(this.tplCategory); | 77 | return isTree(this.tplCategory); |
| 92 | } | 78 | } |
| 93 | 79 | ||
| 94 | - public static boolean isTree(String tplCategory) | ||
| 95 | - { | 80 | + public static boolean isTree(String tplCategory) { |
| 96 | return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory); | 81 | return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory); |
| 97 | } | 82 | } |
| 98 | 83 | ||
| 99 | - public boolean isCrud() | ||
| 100 | - { | 84 | + public boolean isCrud() { |
| 101 | return isCrud(this.tplCategory); | 85 | return isCrud(this.tplCategory); |
| 102 | } | 86 | } |
| 103 | 87 | ||
| 104 | - public static boolean isCrud(String tplCategory) | ||
| 105 | - { | 88 | + public static boolean isCrud(String tplCategory) { |
| 106 | return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory); | 89 | return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory); |
| 107 | } | 90 | } |
| 108 | 91 | ||
| 109 | - public boolean isSuperColumn(String javaField) | ||
| 110 | - { | 92 | + public boolean isSuperColumn(String javaField) { |
| 111 | return isSuperColumn(this.tplCategory, javaField); | 93 | return isSuperColumn(this.tplCategory, javaField); |
| 112 | } | 94 | } |
| 113 | 95 | ||
| 114 | - public static boolean isSuperColumn(String tplCategory, String javaField) | ||
| 115 | - { | ||
| 116 | - if (isTree(tplCategory)) | ||
| 117 | - { | 96 | + public static boolean isSuperColumn(String tplCategory, String javaField) { |
| 97 | + if (isTree(tplCategory)) { | ||
| 118 | return StringUtils.equalsAnyIgnoreCase(javaField, | 98 | return StringUtils.equalsAnyIgnoreCase(javaField, |
| 119 | ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY)); | 99 | ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY)); |
| 120 | } | 100 | } |
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
| @@ -6,7 +6,7 @@ import com.ruoyi.common.utils.StringUtils; | @@ -6,7 +6,7 @@ import com.ruoyi.common.utils.StringUtils; | ||
| 6 | 6 | ||
| 7 | /** | 7 | /** |
| 8 | * 代码生成业务字段表 gen_table_column | 8 | * 代码生成业务字段表 gen_table_column |
| 9 | - * | 9 | + * |
| 10 | * @author ruoyi | 10 | * @author ruoyi |
| 11 | */ | 11 | */ |
| 12 | public class GenTableColumn extends BaseEntity | 12 | public class GenTableColumn extends BaseEntity |
| @@ -68,86 +68,6 @@ public class GenTableColumn extends BaseEntity | @@ -68,86 +68,6 @@ public class GenTableColumn extends BaseEntity | ||
| 68 | /** 排序 */ | 68 | /** 排序 */ |
| 69 | private Integer sort; | 69 | private Integer sort; |
| 70 | 70 | ||
| 71 | - public void setColumnId(Long columnId) | ||
| 72 | - { | ||
| 73 | - this.columnId = columnId; | ||
| 74 | - } | ||
| 75 | - | ||
| 76 | - public Long getColumnId() | ||
| 77 | - { | ||
| 78 | - return columnId; | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - public void setTableId(Long tableId) | ||
| 82 | - { | ||
| 83 | - this.tableId = tableId; | ||
| 84 | - } | ||
| 85 | - | ||
| 86 | - public Long getTableId() | ||
| 87 | - { | ||
| 88 | - return tableId; | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - public void setColumnName(String columnName) | ||
| 92 | - { | ||
| 93 | - this.columnName = columnName; | ||
| 94 | - } | ||
| 95 | - | ||
| 96 | - public String getColumnName() | ||
| 97 | - { | ||
| 98 | - return columnName; | ||
| 99 | - } | ||
| 100 | - | ||
| 101 | - public void setColumnComment(String columnComment) | ||
| 102 | - { | ||
| 103 | - this.columnComment = columnComment; | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - public String getColumnComment() | ||
| 107 | - { | ||
| 108 | - return columnComment; | ||
| 109 | - } | ||
| 110 | - | ||
| 111 | - public void setColumnType(String columnType) | ||
| 112 | - { | ||
| 113 | - this.columnType = columnType; | ||
| 114 | - } | ||
| 115 | - | ||
| 116 | - public String getColumnType() | ||
| 117 | - { | ||
| 118 | - return columnType; | ||
| 119 | - } | ||
| 120 | - | ||
| 121 | - public void setJavaType(String javaType) | ||
| 122 | - { | ||
| 123 | - this.javaType = javaType; | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - public String getJavaType() | ||
| 127 | - { | ||
| 128 | - return javaType; | ||
| 129 | - } | ||
| 130 | - | ||
| 131 | - public void setJavaField(String javaField) | ||
| 132 | - { | ||
| 133 | - this.javaField = javaField; | ||
| 134 | - } | ||
| 135 | - | ||
| 136 | - public String getJavaField() | ||
| 137 | - { | ||
| 138 | - return javaField; | ||
| 139 | - } | ||
| 140 | - | ||
| 141 | - public void setIsPk(String isPk) | ||
| 142 | - { | ||
| 143 | - this.isPk = isPk; | ||
| 144 | - } | ||
| 145 | - | ||
| 146 | - public String getIsPk() | ||
| 147 | - { | ||
| 148 | - return isPk; | ||
| 149 | - } | ||
| 150 | - | ||
| 151 | public boolean isPk() | 71 | public boolean isPk() |
| 152 | { | 72 | { |
| 153 | return isPk(this.isPk); | 73 | return isPk(this.isPk); |
| @@ -278,46 +198,6 @@ public class GenTableColumn extends BaseEntity | @@ -278,46 +198,6 @@ public class GenTableColumn extends BaseEntity | ||
| 278 | return isQuery != null && StringUtils.equals("1", isQuery); | 198 | return isQuery != null && StringUtils.equals("1", isQuery); |
| 279 | } | 199 | } |
| 280 | 200 | ||
| 281 | - public void setQueryType(String queryType) | ||
| 282 | - { | ||
| 283 | - this.queryType = queryType; | ||
| 284 | - } | ||
| 285 | - | ||
| 286 | - public String getQueryType() | ||
| 287 | - { | ||
| 288 | - return queryType; | ||
| 289 | - } | ||
| 290 | - | ||
| 291 | - public String getHtmlType() | ||
| 292 | - { | ||
| 293 | - return htmlType; | ||
| 294 | - } | ||
| 295 | - | ||
| 296 | - public void setHtmlType(String htmlType) | ||
| 297 | - { | ||
| 298 | - this.htmlType = htmlType; | ||
| 299 | - } | ||
| 300 | - | ||
| 301 | - public void setDictType(String dictType) | ||
| 302 | - { | ||
| 303 | - this.dictType = dictType; | ||
| 304 | - } | ||
| 305 | - | ||
| 306 | - public String getDictType() | ||
| 307 | - { | ||
| 308 | - return dictType; | ||
| 309 | - } | ||
| 310 | - | ||
| 311 | - public void setSort(Integer sort) | ||
| 312 | - { | ||
| 313 | - this.sort = sort; | ||
| 314 | - } | ||
| 315 | - | ||
| 316 | - public Integer getSort() | ||
| 317 | - { | ||
| 318 | - return sort; | ||
| 319 | - } | ||
| 320 | - | ||
| 321 | public boolean isSuperColumn() | 201 | public boolean isSuperColumn() |
| 322 | { | 202 | { |
| 323 | return isSuperColumn(this.javaField); | 203 | return isSuperColumn(this.javaField); |
src/main/java/cn/iocoder/dashboard/modules/system/enums/logger/SysLoginLogTypeEnum.java
| @@ -10,8 +10,12 @@ import lombok.Getter; | @@ -10,8 +10,12 @@ import lombok.Getter; | ||
| 10 | @AllArgsConstructor | 10 | @AllArgsConstructor |
| 11 | public enum SysLoginLogTypeEnum { | 11 | public enum SysLoginLogTypeEnum { |
| 12 | 12 | ||
| 13 | - LOGIN(1), | ||
| 14 | - LOGOUT(2); | 13 | + LOGIN_USERNAME(100), // 使用账号登录 |
| 14 | + | ||
| 15 | + LOGOUT_SELF(200), // 自己主动登出 | ||
| 16 | + LOGOUT_TIMEOUT(201), // 超时登出 | ||
| 17 | + LOGOUT_DELETE(202), // 强制退出 | ||
| 18 | + ; | ||
| 15 | 19 | ||
| 16 | /** | 20 | /** |
| 17 | * 日志类型 | 21 | * 日志类型 |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
| @@ -137,7 +137,7 @@ public class SysAuthServiceImpl implements SysAuthService { | @@ -137,7 +137,7 @@ public class SysAuthServiceImpl implements SysAuthService { | ||
| 137 | 137 | ||
| 138 | private void createLoginLog(String username, SysLoginResultEnum loginResult) { | 138 | private void createLoginLog(String username, SysLoginResultEnum loginResult) { |
| 139 | SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO(); | 139 | SysLoginLogCreateReqVO reqVO = new SysLoginLogCreateReqVO(); |
| 140 | - reqVO.setLogType(SysLoginLogTypeEnum.LOGIN.getType()); | 140 | + reqVO.setLogType(SysLoginLogTypeEnum.LOGIN_USERNAME.getType()); |
| 141 | reqVO.setTraceId(TracerUtils.getTraceId()); | 141 | reqVO.setTraceId(TracerUtils.getTraceId()); |
| 142 | reqVO.setUsername(username); | 142 | reqVO.setUsername(username); |
| 143 | reqVO.setUserAgent(ServletUtils.getUserAgent()); | 143 | reqVO.setUserAgent(ServletUtils.getUserAgent()); |
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/ToolCodeGenController.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.controller.codegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.dashboard.modules.tool.controller.codegen.vo.ToolCodeGenTablePageItemRespVO; | ||
| 6 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 7 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 8 | +import org.springframework.web.bind.annotation.RestController; | ||
| 9 | + | ||
| 10 | +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||
| 11 | + | ||
| 12 | +@RestController | ||
| 13 | +@RequestMapping("/tool/code-gen") | ||
| 14 | +public class ToolCodeGenController { | ||
| 15 | + | ||
| 16 | + @GetMapping("/table/page") | ||
| 17 | + public CommonResult<PageResult<ToolCodeGenTablePageItemRespVO>> getCodeGenTablePage() { | ||
| 18 | + return success(null); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/ToolCodeGenTableBaseRespVO.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/ToolCodeGenTablePageItemRespVO.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/tool/controller/codegen/vo/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.controller.codegen.vo; |
src/main/java/cn/iocoder/dashboard/modules/tool/controller/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.controller; |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaColumnMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; | ||
| 5 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 6 | +import org.apache.ibatis.annotations.Mapper; | ||
| 7 | + | ||
| 8 | +import java.util.List; | ||
| 9 | + | ||
| 10 | +@Mapper | ||
| 11 | +public interface ToolInformationSchemaColumnMapper extends BaseMapperX<ToolInformationSchemaColumnDO> { | ||
| 12 | + | ||
| 13 | + default List<ToolInformationSchemaColumnDO> selectListByTableName(String tableName) { | ||
| 14 | + return selectList(new QueryWrapper<ToolInformationSchemaColumnDO>().eq("table_name", tableName) | ||
| 15 | + .orderByAsc("ordinal_position")); | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; | ||
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; | ||
| 5 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | ||
| 6 | +import org.apache.ibatis.annotations.Mapper; | ||
| 7 | + | ||
| 8 | +import java.util.List; | ||
| 9 | + | ||
| 10 | +@Mapper | ||
| 11 | +public interface ToolInformationSchemaTableMapper extends BaseMapperX<ToolInformationSchemaTableDO> { | ||
| 12 | + | ||
| 13 | + default List<ToolInformationSchemaTableDO> selectListByTableSchema(String tableSchema) { | ||
| 14 | + return selectList(new QueryWrapper<ToolInformationSchemaTableDO>().eq("table_schema", tableSchema)); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao; |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolCodegenColumnDO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 5 | +import lombok.Builder; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 代码生成 column 字段定义 | ||
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 13 | + */ | ||
| 14 | +@TableName(value = "tool_codegen_table_column", autoResultMap = true) | ||
| 15 | +@Data | ||
| 16 | +@Builder | ||
| 17 | +@EqualsAndHashCode(callSuper = true) | ||
| 18 | +public class ToolCodegenColumnDO extends BaseDO { | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolCodegenTableDO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import cn.iocoder.dashboard.modules.tool.enums.codegen.ToolCodeGenTemplateTypeEnum; | ||
| 5 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | +import lombok.Builder; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 代码生成 table 表定义 | ||
| 12 | + * | ||
| 13 | + * @author 芋道源码 | ||
| 14 | + */ | ||
| 15 | +@TableName(value = "tool_codegen_table", autoResultMap = true) | ||
| 16 | +@Data | ||
| 17 | +@Builder | ||
| 18 | +@EqualsAndHashCode(callSuper = true) | ||
| 19 | +public class ToolCodegenTableDO extends BaseDO { | ||
| 20 | + | ||
| 21 | + // ========== 表相关字段 ========== | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * ID 编号 | ||
| 25 | + */ | ||
| 26 | + private Long id; | ||
| 27 | + /** | ||
| 28 | + * 表名称 | ||
| 29 | + */ | ||
| 30 | +// @NotBlank(message = "表名称不能为空") | ||
| 31 | + private String tableName; | ||
| 32 | + /** | ||
| 33 | + * 表描述 | ||
| 34 | + */ | ||
| 35 | +// @NotBlank(message = "表描述不能为空") | ||
| 36 | + private String tableComment; | ||
| 37 | + /** | ||
| 38 | + * 备注 | ||
| 39 | + */ | ||
| 40 | + private String remark; | ||
| 41 | + | ||
| 42 | + // ========== 类相关字段 ========== | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 模块名,即一级目录 | ||
| 46 | + * | ||
| 47 | + * 例如说,infra、system、tool 等等 | ||
| 48 | + */ | ||
| 49 | +// @NotBlank(message = "模块名不能为空") | ||
| 50 | + private String moduleName; | ||
| 51 | + /** | ||
| 52 | + * 业务名,即二级目录 | ||
| 53 | + * | ||
| 54 | + * 例如说,user、permission、dict 等等 | ||
| 55 | + */ | ||
| 56 | +// @NotBlank(message = "生成业务名不能为空") | ||
| 57 | + private String businessName; | ||
| 58 | + /** | ||
| 59 | + * 类名称(首字母大写) | ||
| 60 | + * | ||
| 61 | + * 例如说,SysUser、SysMenu、SysDictData 等等 | ||
| 62 | + */ | ||
| 63 | +// @NotBlank(message = "实体类名称不能为空") | ||
| 64 | + private String className; | ||
| 65 | + /** | ||
| 66 | + * 类描述 | ||
| 67 | + */ | ||
| 68 | +// @NotBlank(message = "生成功能名不能为空") | ||
| 69 | + private String classComment; | ||
| 70 | + /** | ||
| 71 | + * 作者 | ||
| 72 | + */ | ||
| 73 | +// @NotBlank(message = "作者不能为空") | ||
| 74 | + private String author; | ||
| 75 | + | ||
| 76 | + // ========== 生成相关字段 ========== | ||
| 77 | + | ||
| 78 | + /** | ||
| 79 | + * 模板类型 | ||
| 80 | + * | ||
| 81 | + * 枚举 {@link ToolCodeGenTemplateTypeEnum} | ||
| 82 | + */ | ||
| 83 | + private Integer templateType; | ||
| 84 | + | ||
| 85 | + // ========== 菜单相关字段 ========== | ||
| 86 | + | ||
| 87 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolInformationSchemaColumnDO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.annotation.TableField; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 5 | +import lombok.Builder; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * MySQL 数据库中的 column 字段定义 | ||
| 10 | + * | ||
| 11 | + * @author 芋道源码 | ||
| 12 | + */ | ||
| 13 | +@TableName(value = "information_schema.columns", autoResultMap = true) | ||
| 14 | +@Data | ||
| 15 | +@Builder | ||
| 16 | +public class ToolInformationSchemaColumnDO { | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 表名称 | ||
| 20 | + */ | ||
| 21 | + private String tableName; | ||
| 22 | + /** | ||
| 23 | + * 字段名 | ||
| 24 | + */ | ||
| 25 | + private String columnName; | ||
| 26 | + /** | ||
| 27 | + * 字段类型 | ||
| 28 | + */ | ||
| 29 | + private String columnType; | ||
| 30 | + /** | ||
| 31 | + * 是否允许为空 | ||
| 32 | + */ | ||
| 33 | + @TableField("case when is_nullable = 'yes' then '1' else '0' end") | ||
| 34 | + private Boolean nullable; | ||
| 35 | + /** | ||
| 36 | + * 是否主键 | ||
| 37 | + */ | ||
| 38 | + @TableField("case when column_key = 'PRI' then '1' else '0' end") | ||
| 39 | + private Boolean primaryKey; | ||
| 40 | + /** | ||
| 41 | + * 排序字段 | ||
| 42 | + */ | ||
| 43 | + private Integer ordinalPosition; | ||
| 44 | + | ||
| 45 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/codegen/ToolInformationSchemaTableDO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 4 | +import lombok.Builder; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import java.util.Date; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * MySQL 数据库中的 table 表定义 | ||
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 13 | + */ | ||
| 14 | +@TableName(value = "information_schema.tables", autoResultMap = true) | ||
| 15 | +@Data | ||
| 16 | +@Builder | ||
| 17 | +public class ToolInformationSchemaTableDO { | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 数据库 | ||
| 21 | + */ | ||
| 22 | + private String tableSchema; | ||
| 23 | + /** | ||
| 24 | + * 表名称 | ||
| 25 | + */ | ||
| 26 | + private String tableName; | ||
| 27 | + /** | ||
| 28 | + * 表描述 | ||
| 29 | + */ | ||
| 30 | + private String tableComment; | ||
| 31 | + /** | ||
| 32 | + * 创建时间 | ||
| 33 | + */ | ||
| 34 | + private Date createTime; | ||
| 35 | + | ||
| 36 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dataobject/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject; |
src/main/java/cn/iocoder/dashboard/modules/tool/enums/codegen/ToolCodeGenTemplateTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.enums.codegen; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 代码生成模板类型 | ||
| 8 | + * | ||
| 9 | + * @author 芋道源码 | ||
| 10 | + */ | ||
| 11 | +@AllArgsConstructor | ||
| 12 | +@Getter | ||
| 13 | +public enum ToolCodeGenTemplateTypeEnum { | ||
| 14 | + | ||
| 15 | + CRUD(1), // 基础 CRUD | ||
| 16 | + TREE(2), // 树形 CRUD | ||
| 17 | + SUB(3) // 子表 CRUD | ||
| 18 | + ; | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 类型 | ||
| 22 | + */ | ||
| 23 | + private final Integer type; | ||
| 24 | + | ||
| 25 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/enums/package-info.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.enums; |
src/main/java/cn/iocoder/dashboard/modules/tool/package-info.java
0 → 100644
src/test/java/cn/iocoder/dashboard/TestApplication.java
0 → 100644
src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaColumnMapperTest.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.TestApplication; | ||
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaColumnDO; | ||
| 5 | +import org.junit.jupiter.api.Test; | ||
| 6 | +import org.springframework.boot.test.context.SpringBootTest; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | ||
| 15 | +public class ToolInformationSchemaColumnMapperTest { | ||
| 16 | + | ||
| 17 | + @Resource | ||
| 18 | + private ToolInformationSchemaColumnMapper toolInformationSchemaColumnMapper; | ||
| 19 | + | ||
| 20 | + @Test | ||
| 21 | + public void testSelectListByTableName() { | ||
| 22 | + List<ToolInformationSchemaColumnDO> columns = toolInformationSchemaColumnMapper | ||
| 23 | + .selectListByTableName("inf_config"); | ||
| 24 | + assertTrue(columns.size() > 0); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | +} |
src/test/java/cn/iocoder/dashboard/modules/tool/dal/mysql/dao/coegen/ToolInformationSchemaTableMapperTest.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.tool.dal.mysql.dao.coegen; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.TestApplication; | ||
| 4 | +import cn.iocoder.dashboard.modules.tool.dal.mysql.dataobject.codegen.ToolInformationSchemaTableDO; | ||
| 5 | +import org.junit.jupiter.api.Test; | ||
| 6 | +import org.springframework.boot.test.context.SpringBootTest; | ||
| 7 | + | ||
| 8 | +import javax.annotation.Resource; | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| 12 | + | ||
| 13 | +@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) | ||
| 14 | +class ToolInformationSchemaTableMapperTest { | ||
| 15 | + | ||
| 16 | + @Resource | ||
| 17 | + private ToolInformationSchemaTableMapper toolInformationSchemaTableMapper; | ||
| 18 | + | ||
| 19 | + @Test | ||
| 20 | + public void tstSelectListByTableSchema() { | ||
| 21 | + List<ToolInformationSchemaTableDO> tables = toolInformationSchemaTableMapper | ||
| 22 | + .selectListByTableSchema("ruoyi-vue-pro"); | ||
| 23 | + assertTrue(tables.size() > 0); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | +} |