feat: 代码模板使用字典配置替换枚举值.

This commit is contained in:
lijiahang
2023-10-30 18:35:08 +08:00
parent 83a0fb99f1
commit ada22636b3
28 changed files with 737 additions and 624 deletions

View File

@@ -7,7 +7,7 @@ package com.orion.ops.framework.common.constant;
* @version 1.0.0
* @since 2023/6/23 18:49
*/
public interface Const extends com.orion.lang.constant.Const, ConstField {
public interface Const extends com.orion.lang.constant.Const, FieldConst {
Integer NOT_DELETE = 0;

View File

@@ -7,7 +7,7 @@ package com.orion.ops.framework.common.constant;
* @version 1.0.0
* @since 2023/10/17 12:44
*/
public interface ConstField {
public interface FieldConst {
String ID = "id";

View File

@@ -1,6 +1,6 @@
package com.orion.ops.framework.biz.operator.log.core.constant;
import com.orion.ops.framework.common.constant.ConstField;
import com.orion.ops.framework.common.constant.FieldConst;
/**
* 操作日志常量
@@ -9,7 +9,7 @@ import com.orion.ops.framework.common.constant.ConstField;
* @version 1.0.0
* @since 2023/10/10 19:00
*/
public interface OperatorLogKeys extends ConstField {
public interface OperatorLogKeys extends FieldConst {
String ID_LIST = "idList";

View File

@@ -30,38 +30,21 @@ public class CodeGenerators {
String module = "infra";
// 生成的表
Table[] tables = {
// Template.create("preference", "用户偏好", "preference")
// .enableProviderApi()
// .cache("user:preference:{}:{}", "用户偏好 ${type} ${userId}")
// .expire(1, TimeUnit.HOURS)
// .vue("user", "preference")
// .enums("type")
// .names("APP", "HOST")
// // 同 .value(1, 2)
// .values("value", 1, 2)
// // 同 .label("应用", "主机")
// .values("label", "应用", "主机")
// .color("blue", "green")
// .build(),
// Template.create("history_value", "历史归档", "history")
// .enableProviderApi()
// .vue("meta", "history-value")
// .build(),
Template.create("dict_key", "字典配置项", "dict")
.disableOperatorLog()
.enableProviderApi()
.disableUnitTest()
.cache("dict:keys", "字典配置项")
.expire(1, TimeUnit.DAYS)
.vue("system", "dict-key")
.enums("value_type")
.names("STRING", "INTEGER", "DECIMAL", "BOOLEAN", "COLOR")
.label("字符串", "整数", "小数", "布尔值", "颜色")
.enableRowSelection()
.enableCardView()
.enableDrawerForm()
.dict("dictValueType", "value_type")
.fields("STRING", "INTEGER", "DECIMAL", "BOOLEAN", "COLOR")
.labels("字符串", "整数", "小数", "布尔值", "颜色")
.color("blue", "gray", "red", "green", "white")
.valueUseFields()
.build(),
// Template.create("dict_value", "字典配置值", "dict")
// .cache("dict:value:{}", "字典配置值 ${key}")
// .expire(1, TimeUnit.DAYS)
// .vue("system", "dict-value")
// .enableRowSelection()
// .build(),
};
// jdbc 配置 - 使用配置文件
File yamlFile = new File("orion-ops-launch/src/main/resources/application-dev.yaml");

View File

@@ -357,8 +357,6 @@ public class CodeGenerator implements Executable {
new String[]{"/templates/orion-vue-views-components-table.vue.vm", "${feature}-table.vue", "vue/views/${module}/${feature}/components"},
// card-list.vue 文件
new String[]{"/templates/orion-vue-views-components-card-list.vue.vm", "${feature}-card-list.vue", "vue/views/${module}/${feature}/components"},
// enum.types.ts 文件
new String[]{"/templates/orion-vue-views-types-enum.types.ts.vm", "enum.types.ts", "vue/views/${module}/${feature}/types"},
// const.ts 文件
new String[]{"/templates/orion-vue-views-types-const.ts.vm", "const.ts", "vue/views/${module}/${feature}/types"},
// form.rules.ts 文件

View File

@@ -3,9 +3,7 @@ package com.orion.ops.framework.mybatis.core.generator.core;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.orion.lang.define.collect.MultiLinkedHashMap;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.VariableStyles;
import com.orion.lang.utils.io.Files1;
@@ -14,11 +12,13 @@ import com.orion.lang.utils.reflect.Fields;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.OrionOpsProConst;
import com.orion.ops.framework.mybatis.core.generator.template.Table;
import com.orion.ops.framework.mybatis.core.generator.template.VueEnum;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -46,10 +46,10 @@ public class CodeGeneratorEngine extends VelocityTemplateEngine {
customFiles = new CustomFileFilter(tables.get(tableInfo.getName()), customFiles).doFilter();
// 添加表元数据
this.addTableMeta(tableInfo, objectMap);
// 替换自定义包名
this.replacePackageName(customFiles, tableInfo, objectMap);
// 添加注释元数据
this.addApiCommentMeta(tableInfo, objectMap);
// 替换自定义包名
this.replacePackageName(customFiles, tableInfo, objectMap);
// 生成后端文件
this.generatorServerFile(customFiles, tableInfo, objectMap);
// 生成前端文件
@@ -65,10 +65,6 @@ public class CodeGeneratorEngine extends VelocityTemplateEngine {
* @param objectMap objectMap
*/
private void addTableMeta(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// http 注释标识
objectMap.put("httpComment", "###");
// 版本
objectMap.put("since", OrionOpsProConst.VERSION);
// 替换业务注释
tableInfo.setComment(tables.get(tableInfo.getName()).getComment());
Table table = tables.get(tableInfo.getName());
@@ -87,6 +83,38 @@ public class CodeGeneratorEngine extends VelocityTemplateEngine {
objectMap.put("typeHyphen", mappingHyphen.substring(0, mappingHyphen.length() - 3));
// 类型常量
objectMap.put("typeConst", VariableStyles.BIG_HUMP.toSerpentine(entityName).toUpperCase());
// 字典配置
objectMap.put("dictMap", new DictParser(tableInfo, table).parse());
}
/**
* 插入 api 注释
*
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void addApiCommentMeta(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
// http 注释标识
objectMap.put("httpComment", "###");
// 版本
objectMap.put("since", OrionOpsProConst.VERSION);
// api 注释
Map<String, String> apiComment = new HashMap<>(12);
String comment = tableInfo.getComment();
apiComment.put("create", "创建" + comment);
apiComment.put("updateAll", "根据条件更新" + comment);
apiComment.put("updateById", "更新" + comment);
apiComment.put("getById", "查询" + comment);
apiComment.put("getByIdList", "批量查询" + comment);
apiComment.put("queryList", "查询全部" + comment);
apiComment.put("queryListByCache", "通过缓存查询" + comment);
apiComment.put("queryPage", "分页查询" + comment);
apiComment.put("queryCount", "查询" + comment + "数量");
apiComment.put("deleteById", "删除" + comment);
apiComment.put("deleteAll", "根据条件删除" + comment);
apiComment.put("batchDelete", "批量删除" + comment);
apiComment.put("export", "导出" + comment);
objectMap.put("apiComment", apiComment);
}
/**
@@ -133,31 +161,6 @@ public class CodeGeneratorEngine extends VelocityTemplateEngine {
objectMap.put("customProviderFilePackages", customProviderFilePackages);
}
/**
* 插入 api 注释
*
* @param tableInfo tableInfo
* @param objectMap objectMap
*/
private void addApiCommentMeta(@NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
Map<String, String> map = new HashMap<>(12);
objectMap.put("apiComment", map);
String comment = tableInfo.getComment();
map.put("create", "创建" + comment);
map.put("updateAll", "根据条件更新" + comment);
map.put("updateById", "更新" + comment);
map.put("getById", "查询" + comment);
map.put("getByIdList", "批量查询" + comment);
map.put("queryList", "查询全部" + comment);
map.put("queryListByCache", "通过缓存查询" + comment);
map.put("queryPage", "分页查询" + comment);
map.put("queryCount", "查询" + comment + "数量");
map.put("deleteById", "删除" + comment);
map.put("deleteAll", "根据条件删除" + comment);
map.put("batchDelete", "批量删除" + comment);
map.put("export", "导出" + comment);
}
/**
* 生成后端文件
*
@@ -222,8 +225,6 @@ public class CodeGeneratorEngine extends VelocityTemplateEngine {
vueMeta.put("featureEntityFirstLower", Strings.firstLower(vueMeta.get("featureEntity")));
// 功能名称常量
vueMeta.put("featureConst", VariableStyles.SPINE.toSerpentine(table.getFeature()).toUpperCase());
// 枚举
vueMeta.put("enums", this.getEnumMap(tableInfo, table));
objectMap.put("vue", vueMeta);
// 生成文件
@@ -263,71 +264,4 @@ public class CodeGeneratorEngine extends VelocityTemplateEngine {
});
}
/**
* 获取枚举
*
* @param tableInfo tableInfo
* @param table table
* @return enumMap
*/
private Map<String, EnumMeta> getEnumMap(TableInfo tableInfo, Table table) {
// 枚举值
Map<String, EnumMeta> enumMap = new LinkedHashMap<>();
for (VueEnum meta : table.getEnums()) {
// 检查字段是否存在
String variable = meta.getVariable();
TableField tableField = tableInfo.getFields()
.stream()
.filter(s -> variable.equals(s.getName()) || variable.equals(s.getPropertyName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("未查询到枚举映射字段 " + variable));
// 设置枚举名称
if (meta.getClassName() == null) {
meta.setClassName(Strings.firstUpper(tableField.getPropertyName()) + "Enum");
}
// 设置枚举注释
if (meta.getComment() == null) {
meta.setComment(Strings.def(tableField.getComment(), meta.getClassName()));
}
// 设置枚举
MultiLinkedHashMap<String, String, Object> enumInfo = new MultiLinkedHashMap<>();
for (int i = 0; i < meta.getNames().size(); i++) {
// 枚举名称
String name = meta.getNames().get(i);
// 设置枚举值
for (int j = 0; j < meta.getFields().size(); j++) {
String field = meta.getFields().get(j);
Object value = safeGet(safeGet(meta.getValues(), j), i);
enumInfo.put(name, field, value);
}
// 检查是否有 value
if (!meta.getFields().contains(Const.VALUE)) {
// 没有 value 用 name
enumInfo.put(name, Const.VALUE, name);
}
}
enumMap.put(tableField.getPropertyName(), new EnumMeta(meta.getClassName(), meta.getComment(), enumInfo));
}
return enumMap;
}
/**
* 获取值
*
* @param list list
* @param index index
* @param <T> T
* @return value
*/
private <T> T safeGet(List<T> list, int index) {
if (list == null) {
return null;
}
if (list.size() > index) {
return list.get(index);
} else {
return null;
}
}
}

View File

@@ -75,6 +75,19 @@ public class CustomFileFilter {
files.removeIf(file -> isVueFile(file.getTemplatePath()));
// 不生成菜单 sql 文件
files.removeIf(file -> isMenuDataFile(file.getTemplatePath()));
} else {
// form
if (!table.isEnableDrawerForm()) {
// 不生成抽屉表单
files.removeIf(file -> isVueFormDrawerFile(file.getTemplatePath()));
} else {
// 不生成模态框表单
files.removeIf(file -> isVueFormModalFile(file.getTemplatePath()));
}
// 不生成卡片文件
if (!table.isEnableCardView()) {
files.removeIf(file -> isVueCardViewFile(file.getTemplatePath()));
}
}
return files;
}
@@ -180,4 +193,35 @@ public class CustomFileFilter {
return templatePath.contains("orion-vue-");
}
/**
* 是否为抽屉表单文件
*
* @param templatePath templatePath
* @return 是否为抽屉表单文件
*/
public static boolean isVueFormDrawerFile(String templatePath) {
return templatePath.contains("orion-vue-views-components-form-drawer");
}
/**
* 是否为模态框表单文件
*
* @param templatePath templatePath
* @return 是否为模态框表单文件
*/
public static boolean isVueFormModalFile(String templatePath) {
return templatePath.contains("orion-vue-views-components-form-modal");
}
/**
* 是否为卡片视图文件
*
* @param templatePath templatePath
* @return 是否为卡片视图文件
*/
public static boolean isVueCardViewFile(String templatePath) {
return templatePath.contains("orion-vue-views-components-card-list") ||
templatePath.contains("orion-vue-views-types-card.fields");
}
}

View File

@@ -0,0 +1,87 @@
package com.orion.ops.framework.mybatis.core.generator.core;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.orion.lang.utils.Strings;
import com.orion.ops.framework.common.constant.Const;
import com.orion.ops.framework.common.constant.FieldConst;
import com.orion.ops.framework.mybatis.core.generator.template.DictMeta;
import com.orion.ops.framework.mybatis.core.generator.template.Table;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 字典解析器
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/10/30 16:02
*/
public class DictParser {
private final TableInfo tableInfo;
private final Table table;
public DictParser(TableInfo tableInfo, Table table) {
this.tableInfo = tableInfo;
this.table = table;
}
/**
* 解析字典
*
* @return dictMap
*/
public Map<String, DictMeta> parse() {
// 字典值
Map<String, DictMeta> dictMap = new LinkedHashMap<>();
for (DictMeta meta : table.getDictList()) {
// 检查字段是否存在
String variable = meta.getVariable();
TableField tableField = tableInfo.getFields()
.stream()
.filter(s -> variable.equals(s.getName()) || variable.equals(s.getPropertyName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("未查询到字典映射字段 " + variable));
// 设置字段名称
if (meta.getField() == null) {
meta.setField(Strings.firstUpper(tableField.getPropertyName()));
}
meta.setKeyField(meta.getField() + "Key");
// 设置注释
if (meta.getComment() == null) {
meta.setComment(Strings.def(tableField.getComment(), meta.getField()));
}
// 设置额外参数 schema
if (meta.getExtraValues().size() > 0) {
List<Map<String, String>> extraSchema = meta.getExtraValues().get(0)
.keySet()
.stream()
.map(s -> {
Map<String, String> res = new LinkedHashMap<>();
res.put(FieldConst.NAME, s);
res.put(FieldConst.TYPE, "STRING");
return res;
}).collect(Collectors.toList());
meta.setExtraSchema(JSON.toJSONString(extraSchema));
} else {
meta.setExtraSchema(Const.EMPTY_ARRAY);
}
// 设置额外参数 json
List<String> extraJson = meta.getExtraValues()
.stream()
.map(JSON::toJSONString)
.collect(Collectors.toList());
meta.setExtraJson(extraJson);
dictMap.put(tableField.getPropertyName(), meta);
}
return dictMap;
}
}

View File

@@ -1,35 +0,0 @@
package com.orion.ops.framework.mybatis.core.generator.core;
import com.orion.lang.define.collect.MultiLinkedHashMap;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* vue 枚举
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/26 16:50
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EnumMeta {
/**
* 类名称
*/
private String className;
/**
* 备注
*/
private String comment;
/**
* 配置
*/
private MultiLinkedHashMap<String, String, Object> info;
}

View File

@@ -0,0 +1,91 @@
package com.orion.ops.framework.mybatis.core.generator.template;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 字典元数据
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/26 13:53
*/
@Data
public class DictMeta {
/**
* 字典配置名称
*/
protected String keyName;
/**
* 替换的字段 数据库/小驼峰
*/
protected String variable;
/**
* 字段名称 如果为空使用 Strings.firstUpper(field.propertyName)
*/
protected String field;
/**
* key 字段名称
*/
private String keyField;
/**
* 注释 如果为空使用 field.comment || field
*/
protected String comment;
/**
* 字段
*/
protected List<String> fields;
/**
* label
*/
protected List<String> labels;
/**
* value
*/
protected List<Object> values;
/**
* 额外参数
*/
protected List<Map<String, Object>> extraValues;
/**
* 额外参数 schema
*/
private String extraSchema;
/**
* 额外参数 json
*/
private List<String> extraJson;
public DictMeta() {
}
public DictMeta(String keyName, String variable) {
this(keyName, variable, null);
}
public DictMeta(String keyName, String variable, String field) {
this.keyName = keyName;
this.variable = variable;
this.field = field;
this.fields = new ArrayList<>();
this.labels = new ArrayList<>();
this.values = new ArrayList<>();
this.extraValues = new ArrayList<>();
}
}

View File

@@ -0,0 +1,175 @@
package com.orion.ops.framework.mybatis.core.generator.template;
import com.orion.lang.utils.collect.Lists;
import com.orion.ops.framework.common.constant.Const;
import java.util.LinkedHashMap;
/**
* 字典配置模板
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/26 1:14
*/
public class DictTemplate extends Template {
private final DictMeta dictMeta;
public DictTemplate(Table table, String keyName, String variable) {
this(table, keyName, variable, null);
}
public DictTemplate(Table table, String keyName, String variable, String field) {
super(table);
this.dictMeta = new DictMeta(keyName, variable, field);
table.dictList.add(dictMeta);
}
/**
* 设置字典配置名称
*
* @param keyName keyName
* @return this
*/
public DictTemplate keyName(String keyName) {
dictMeta.keyName = keyName;
return this;
}
/**
* 设置字段名称
*
* @param field field
* @return this
*/
public DictTemplate field(String field) {
dictMeta.field = field;
return this;
}
/**
* 设置注释
*
* @param comment comment
* @return this
*/
public DictTemplate comment(String comment) {
dictMeta.comment = comment;
return this;
}
/**
* 设置字段
*
* @param fields fields
* @return this
*/
public DictTemplate fields(String... fields) {
dictMeta.fields.addAll(Lists.of(fields));
return this;
}
/**
* 设置 label
*
* @param labels labels
* @return this
*/
public DictTemplate labels(String... labels) {
dictMeta.labels.addAll(Lists.of(labels));
return this;
}
/**
* 设置 value
*
* @param values values
* @return this
*/
public DictTemplate values(Object... values) {
dictMeta.values.addAll(Lists.of(values));
return this;
}
/**
* 设置 value 使用 fields
*
* @return this
*/
public DictTemplate valueUseFields() {
dictMeta.values.addAll(dictMeta.fields);
return this;
}
/**
* 添加 status
*
* @param status status
* @return this
*/
public DictTemplate status(Object... status) {
return this.extra(Const.STATUS, status);
}
/**
* 添加 type
*
* @param type type
* @return this
*/
public DictTemplate type(Object... type) {
return this.extra(Const.TYPE, type);
}
/**
* 添加 color
*
* @param colors colors
* @return this
*/
public DictTemplate color(Object... colors) {
return this.extra(Const.COLOR, colors);
}
/**
* 添加额外值
*
* @param key key
* @param values values
* @return this
*/
public DictTemplate extra(String key, Object... values) {
// 初始化额外值
if (dictMeta.extraValues.size() == 0) {
for (int i = 0; i < dictMeta.fields.size(); i++) {
dictMeta.extraValues.add(new LinkedHashMap<>());
}
}
// 设置额外值
for (int i = 0; i < dictMeta.extraValues.size(); i++) {
Object value = this.safeGet(i, values);
dictMeta.extraValues.get(i).put(key, value);
}
return this;
}
/**
* 获取值
*
* @param index index
* @param list list
* @return value
*/
private Object safeGet(int index, Object... list) {
if (list == null) {
return null;
}
if (list.length > index) {
return list[index];
} else {
return null;
}
}
}

View File

@@ -1,151 +0,0 @@
package com.orion.ops.framework.mybatis.core.generator.template;
import com.orion.lang.utils.Enums;
import com.orion.lang.utils.collect.Lists;
import com.orion.lang.utils.reflect.Fields;
import com.orion.ops.framework.common.constant.Const;
import java.util.List;
import java.util.stream.Collectors;
/**
* 前端代码枚举模板
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/26 1:14
*/
public class EnumsTemplate extends VueTemplate {
private final VueEnum vueEnum;
public EnumsTemplate(Table table, String variable) {
this(table, variable, (String) null);
}
public EnumsTemplate(Table table, String variable, String className) {
super(table);
this.vueEnum = new VueEnum(variable, className);
table.enums.add(vueEnum);
}
public EnumsTemplate(Table table, String variable, Class<? extends Enum<?>> enumClass) {
super(table);
this.vueEnum = new VueEnum(variable);
table.enums.add(vueEnum);
this.parseEnumMeta(enumClass);
}
/**
* 解析枚举
*
* @param enumClass enumClass
*/
private void parseEnumMeta(Class<? extends Enum<?>> enumClass) {
// 获取枚举
List<? extends Enum<?>> enumList = Lists.of(enumClass.getEnumConstants());
// 枚举名称
List<String> names = enumList.stream()
.map(Enum::name)
.collect(Collectors.toList());
// 枚举字段
List<String> fields = Enums.getFields(enumClass);
// 枚举值
List<List<Object>> values = fields.stream()
.map(field -> enumList.stream()
.map(enumItem -> Fields.getFieldValue(enumItem, field))
.collect(Collectors.toList()))
.collect(Collectors.toList());
vueEnum.className = enumClass.getSimpleName();
vueEnum.names.addAll(names);
vueEnum.fields.addAll(fields);
vueEnum.values.addAll(values);
}
/**
* 设置类名
*
* @param className className
* @return this
*/
public EnumsTemplate className(String className) {
vueEnum.className = className;
return this;
}
/**
* 设置注释
*
* @param comment comment
* @return this
*/
public EnumsTemplate comment(String comment) {
vueEnum.comment = comment;
return this;
}
/**
* 设置枚举名称
*
* @param names names
* @return this
*/
public EnumsTemplate names(String... names) {
vueEnum.names.addAll(Lists.of(names));
return this;
}
/**
* 设置字段值
*
* @param values values
* @return this
*/
public EnumsTemplate values(String field, Object... values) {
vueEnum.fields.add(field);
vueEnum.values.add(Lists.of(values));
return this;
}
/**
* 添加 label
*
* @param labels labels
* @return this
*/
public EnumsTemplate label(Object... labels) {
return this.values(Const.LABEL, labels);
}
/**
* 添加 value
* 如果 value 和 name 相同可以省略 (无 value 自动使用 name)
*
* @param values values
* @return this
*/
public EnumsTemplate value(Object... values) {
return this.values(Const.VALUE, values);
}
/**
* 添加 color
*
* @param colors colors
* @return this
*/
public EnumsTemplate color(Object... colors) {
return this.values(Const.COLOR, colors);
}
/**
* 添加 status
*
* @param status status
* @return this
*/
public EnumsTemplate status(Object... status) {
return this.values(Const.STATUS, status);
}
}

View File

@@ -116,12 +116,12 @@ public class Table {
protected boolean enableCardView;
/**
* 生成的枚举文件
* 生成的字典数据
*/
protected List<VueEnum> enums;
protected List<DictMeta> dictList;
protected Table() {
this.enums = new ArrayList<>();
this.dictList = new ArrayList<>();
}
}

View File

@@ -69,6 +69,29 @@ public class Template {
return new VueTemplate(table, module, feature);
}
/**
* 设置字典
*
* @param keyName 字典配置名称
* @param variable 替换字段 数据库/小驼峰
* @return dict
*/
public DictTemplate dict(String keyName, String variable) {
return new DictTemplate(table, keyName, variable);
}
/**
* 设置字典
*
* @param keyName 字典配置名称
* @param variable 替换字段 数据库/小驼峰
* @param className 字段名称
* @return dict
*/
public DictTemplate dict(String keyName, String variable, String className) {
return new DictTemplate(table, keyName, variable, className);
}
/**
* 构建
*

View File

@@ -1,69 +0,0 @@
package com.orion.ops.framework.mybatis.core.generator.template;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 枚举元数据
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023/9/26 13:53
*/
@Data
public class VueEnum {
/**
* 替换的枚举字段 数据库/小驼峰
*/
protected String variable;
/**
* 枚举类名 如果为空使用 field.propertyName + Enum
*/
protected String className;
/**
* 枚举注释 如果为空使用 field.comment || className
*/
protected String comment;
/**
* 枚举名称
*/
protected List<String> names;
/**
* 枚举字段
*/
protected List<String> fields;
/**
* 枚举值
*/
protected List<List<Object>> values;
public VueEnum(String variable) {
this(variable, null);
}
public VueEnum(String variable, String className) {
this.className = className;
this.variable = variable;
this.names = new ArrayList<>();
this.fields = new ArrayList<>();
this.values = new ArrayList<>();
}
public VueEnum(String variable, String className, String comment, List<String> names, List<String> fields, List<List<Object>> values) {
this.variable = variable;
this.className = className;
this.comment = comment;
this.names = names;
this.fields = fields;
this.values = values;
}
}

View File

@@ -73,36 +73,4 @@ public class VueTemplate extends Template {
return this;
}
/**
* 设置枚举
*
* @param variable 枚举字段 数据库/小驼峰
* @return enums
*/
public EnumsTemplate enums(String variable) {
return new EnumsTemplate(table, variable);
}
/**
* 设置枚举
*
* @param variable 枚举字段 数据库/小驼峰
* @param className className
* @return enums
*/
public EnumsTemplate enums(String variable, String className) {
return new EnumsTemplate(table, variable, className);
}
/**
* 设置枚举
*
* @param variable 枚举字段 数据库/小驼峰
* @param enumClass 枚举类
* @return enums
*/
public EnumsTemplate enums(String variable, Class<? extends Enum<?>> enumClass) {
return new EnumsTemplate(table, variable, enumClass);
}
}

View File

@@ -1,30 +1,49 @@
-- 执行完成后 需要在菜单页面刷新缓存
-- 执行完成后 需要在字典配置项页面刷新缓存
#if($meta.enableOperatorLog)
-- 父菜单
INSERT INTO system_menu
(parent_id, name, type, sort, visible, status, cache, component)
-- 模块 key id
SELECT @MODULE_KEY_ID:= id FROM dict_key WHERE key_name = 'operatorLogModule' AND deleted = 0;
-- 模块 key 排序
SELECT @MODULE_KEY_MAX_SORT:= IFNULL(MAX(sort), 0) FROM dict_value where key_id = @MODULE_KEY_ID AND deleted = 0;
-- 类型 key id
SELECT @TYPE_KEY_ID:= id FROM dict_key WHERE key_name = 'operatorLogType' AND deleted = 0;
-- 类型 key 排序
SELECT @TYPE_KEY_MAX_SORT:= IFNULL(MAX(sort), 0) FROM dict_value WHERE key_id = @TYPE_KEY_ID AND deleted = 0;
-- 插入类型
INSERT INTO dict_value
(`key_id`, `key_name`, `value`, `label`, `extra`, `sort`, `create_time`, `update_time`, `creator`, `updater`, `deleted`)
VALUES
(0, '${table.comment}管理', 1, 10, 1, 1, 1, '$vue.moduleEntityFirstLower');
(@MODULE_KEY_ID, 'operatorLogModule', '${package.ModuleName}:${typeHyphen}', '$!{table.comment}', '{}', @MODULE_KEY_MAX_SORT + 10, now(), now(), '1', '1', 0),
(@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:create', '创建$!{table.comment}', '{}', @TYPE_KEY_MAX_SORT + 10, now(), now(), '1', '1', 0),
(@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:update', '更新$!{table.comment}', '{}', @TYPE_KEY_MAX_SORT + 20, now(), now(), '1', '1', 0),
#if($meta.enableExport)
(@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:delete', '删除$!{table.comment}', '{}', @TYPE_KEY_MAX_SORT + 30, now(), now(), '1', '1', 0),
(@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:export', '导出$!{table.comment}', '{}', @TYPE_KEY_MAX_SORT + 40, now(), now(), '1', '1', 0);
#else
(@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:delete', '删除$!{table.comment}', '{}', @TYPE_KEY_MAX_SORT + 30, now(), now(), '1', '1', 0);
#end
#end
-- 设置临时父菜单id
SELECT @TMP_PARENT_ID:=LAST_INSERT_ID();
-- 子菜单
INSERT INTO system_menu
(parent_id, name, type, sort, visible, status, cache, component)
#if($dictMap.entrySet().size() > 0)
#foreach($enumEntity in $dictMap.entrySet())
-- 插入字典配置项 FIXME 检查这里的类型
INSERT INTO dict_key
(`key_name`, `value_type`, `extra_schema`, `description`, `create_time`, `update_time`, `creator`, `updater`, `deleted`)
VALUES
(@TMP_PARENT_ID, '$table.comment', 2, 10, 1, 1, 1, '$vue.moduleEntityFirstLower$vue.featureEntity');
('$enumEntity.value.keyName', 'STRING', '$enumEntity.value.extraSchema', '$enumEntity.value.comment', now(), now(), '1', '1', 0);
-- 设置临时子菜单id
SELECT @TMP_SUB_ID:=LAST_INSERT_ID();
-- 设置临时配置项id
SELECT @TMP_KEY_ID:=LAST_INSERT_ID();
-- 功能
INSERT INTO system_menu
(parent_id, name, permission, type, sort)
-- 插入字典配置值 FIXME 检查这里的类型
INSERT INTO dict_value
(`key_id`, `key_name`, `value`, `label`, `extra`, `sort`, `create_time`, `update_time`, `creator`, `updater`, `deleted`)
VALUES
(@TMP_SUB_ID, '查询$table.comment', '${package.ModuleName}:${typeHyphen}:query', 3, 10),
(@TMP_SUB_ID, '创建$table.comment', '${package.ModuleName}:${typeHyphen}:create', 3, 20),
(@TMP_SUB_ID, '修改$table.comment', '${package.ModuleName}:${typeHyphen}:update', 3, 30),
(@TMP_SUB_ID, '删除$table.comment', '${package.ModuleName}:${typeHyphen}:delete', 3, 40),
(@TMP_SUB_ID, '导出$table.comment', '${package.ModuleName}:${typeHyphen}:export', 3, 50),
(@TMP_SUB_ID, '导入$table.comment', '${package.ModuleName}:${typeHyphen}:import', 3, 60);
#set($count = $enumEntity.value.fields.size() - 1)
#foreach($index in [0..$count])
#set($sort = $index * 10 + 10)
(@TMP_KEY_ID, '$enumEntity.value.keyName', '$enumEntity.value.values.get($index)', '$enumEntity.value.labels.get($index)', '$enumEntity.value.extraJson.get($index)', $sort, now(), now(), '1', '1', 0)#if($foreach.hasNext),#else;#end
#end
#end
#end

View File

@@ -1,4 +1,4 @@
-- 执行完成后 需要在菜单页面刷新缓存
-- 执行完成后 需要在系统菜单页面刷新缓存
-- 父菜单
INSERT INTO system_menu

View File

@@ -1,6 +1,6 @@
<template>
<card-list v-model:searchValue="formModel.searchValue"
search-input-placeholder="输入xxx"
search-input-placeholder="输入搜索值"
create-card-position="head"
:loading="loading"
:fieldConfig="fieldConfig"
@@ -13,10 +13,57 @@
@reset="reset"
@search="fetchCardData"
@page-change="fetchCardData">
<!-- 过滤条件 -->
<template #filterContent>
<a-form :model="formModel"
class="modal-form"
size="small"
ref="formRef"
label-align="right"
:style="{ width: '320px' }"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 18 }"
@keyup.enter="() => fetchCardData()">
#foreach($field in ${table.fields})
<!-- $field.comment -->
<a-form-item field="${field.propertyName}" label="${field.comment}">
#if(${dictMap.containsKey(${field.propertyName})})
<a-select v-model="formModel.${field.propertyName}"
:options="toOptions($dictMap.get(${field.propertyName}).keyField)"
placeholder="请选择${field.comment}"
allow-clear />
#else
#if("$field.propertyType" == "Integer" || "$field.propertyType" == "Long")
<a-input-number v-model="formModel.${field.propertyName}"
placeholder="请输入${field.comment}"
allow-clear
hide-button />
#elseif("$field.propertyType" == "Date")
<a-date-picker v-model="formModel.${field.propertyName}"
style="width: 100%"
placeholder="请选择${field.comment}"
show-time
allow-clear />
#else
<a-input v-model="formModel.${field.propertyName}" placeholder="请输入${field.comment}" allow-clear />
#end
#end
</a-form-item>
#end
</a-form>
</template>
<!-- 标题 -->
<template #title="{ record }">
{{ record.id }}
</template>
#foreach($field in ${table.fields})
#if(${dictMap.containsKey(${field.propertyName})})
<!-- $field.comment -->
<template #${field.propertyName}="{ record }">
{{ getDictValue($dictMap.get(${field.propertyName}).keyField, record.${field.propertyName}}) }}
</template>
#end
#end
<!-- 拓展操作 -->
<template #extra="{ record }">
<a-space>
@@ -57,45 +104,6 @@
删除
</a-doption>
</template>
<!-- 过滤条件 -->
<template #filterContent>
<a-form :model="formModel"
class="modal-form"
size="small"
ref="formRef"
label-align="right"
:style="{ width: '320px' }"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 18 }"
@keyup.enter="() => fetchCardData()">
#foreach($field in ${table.fields})
<!-- $field.comment -->
<a-form-item field="${field.propertyName}" label="${field.comment}">
#if(${vue.enums.containsKey(${field.propertyName})})
<a-select v-model="formModel.${field.propertyName}"
:options="toOptions(${vue.enums.get(${field.propertyName}).className})"
placeholder="请选择${field.comment}"
allow-clear />
#else
#if("$field.propertyType" == "Integer" || "$field.propertyType" == "Long")
<a-input-number v-model="formModel.${field.propertyName}"
placeholder="请输入${field.comment}"
allow-clear
hide-button />
#elseif("$field.propertyType" == "Date")
<a-date-picker v-model="formModel.${field.propertyName}"
style="width: 100%"
placeholder="请选择${field.comment}"
show-time
allow-clear />
#else
<a-input v-model="formModel.${field.propertyName}" placeholder="请输入${field.comment}" allow-clear />
#end
#end
</a-form-item>
#end
</a-form>
</template>
</card-list>
</template>
@@ -112,15 +120,16 @@
import useLoading from '@/hooks/loading';
import { objectTruthKeyCount, resetObject } from '@/utils';
import fieldConfig from '../types/card.fields';
#if($dictMap.entrySet().size() > 0)
import { #foreach($entry in ${dictMap.entrySet()})${entry.value.keyField}#if($foreach.hasNext), #end#end } from '../types/const';
#else
import {} from '../types/const';
#end
import { delete${vue.featureEntity}, get${vue.featureEntity}Page } from '@/api/${vue.module}/${vue.feature}';
import { Message, Modal } from '@arco-design/web-vue';
import {} from '../types/const';
#if($vue.enums.isEmpty())
import {} from '../types/enum.types';
#else
import { #foreach($entry in ${vue.enums.entrySet()})${entry.value.className}#if($foreach.hasNext), #end#end } from '../types/enum.types';
#if($dictMap.entrySet().size() > 0)
import { useDictStore } from '@/store';
#end
import { toOptions, getEnumValue } from '@/utils/enum';
const emits = defineEmits(['openAdd', 'openUpdate']);
@@ -129,6 +138,9 @@
const cardColLayout = useColLayout();
const pagination = usePagination();
const { loading, setLoading } = useLoading();
#if($dictMap.entrySet().size() > 0)
const { toOptions, getDictValue } = useDictStore();
#end
const formRef = ref();
const formModel = reactive<${vue.featureEntity}QueryRequest>({

View File

@@ -20,10 +20,10 @@
#if("$field.propertyName" != "id")
<!-- $field.comment -->
<a-form-item field="${field.propertyName}" label="${field.comment}">
#if(${vue.enums.containsKey(${field.propertyName})})
#if(${dictMap.containsKey(${field.propertyName})})
<a-select v-model="formModel.${field.propertyName}"
:options="toOptions(${vue.enums.get(${field.propertyName}).className})"
placeholder="请选择${field.comment}"/>
:options="toOptions($dictMap.get(${field.propertyName}).keyField)"
placeholder="请选择${field.comment}" />
#else
#if("$field.propertyType" == "Integer" || "$field.propertyType" == "Long")
<a-input-number v-model="formModel.${field.propertyName}"
@@ -58,18 +58,22 @@
import useLoading from '@/hooks/loading';
import useVisible from '@/hooks/visible';
import formRules from '../types/form.rules';
#if($dictMap.entrySet().size() > 0)
import { #foreach($entry in ${dictMap.entrySet()})${entry.value.keyField}#if($foreach.hasNext), #end#end } from '../types/const';
#else
import {} from '../types/const';
#end
import { create${vue.featureEntity}, update${vue.featureEntity} } from '@/api/${vue.module}/${vue.feature}';
import { Message } from '@arco-design/web-vue';
import {} from '../types/const';
#if($vue.enums.isEmpty())
import {} from '../types/enum.types';
#else
import { #foreach($entry in ${vue.enums.entrySet()})${entry.value.className}#if($foreach.hasNext), #end#end } from '../types/enum.types';
#if($dictMap.entrySet().size() > 0)
import { useDictStore } from '@/store';
#end
import { toOptions } from '@/utils/enum';
const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading();
#if($dictMap.entrySet().size() > 0)
const { toOptions } = useDictStore();
#end
const title = ref<string>();
const isAddHandle = ref<boolean>(true);

View File

@@ -24,9 +24,9 @@
#if("$field.propertyName" != "id")
<!-- $field.comment -->
<a-form-item field="${field.propertyName}" label="${field.comment}">
#if(${vue.enums.containsKey(${field.propertyName})})
#if(${dictMap.containsKey(${field.propertyName})})
<a-select v-model="formModel.${field.propertyName}"
:options="toOptions(${vue.enums.get(${field.propertyName}).className})"
:options="toOptions($dictMap.get(${field.propertyName}).keyField)"
placeholder="请选择${field.comment}" />
#else
#if("$field.propertyType" == "Integer" || "$field.propertyType" == "Long")
@@ -62,18 +62,22 @@
import useLoading from '@/hooks/loading';
import useVisible from '@/hooks/visible';
import formRules from '../types/form.rules';
#if($dictMap.entrySet().size() > 0)
import { #foreach($entry in ${dictMap.entrySet()})${entry.value.keyField}#if($foreach.hasNext), #end#end } from '../types/const';
#else
import {} from '../types/const';
#end
import { create${vue.featureEntity}, update${vue.featureEntity} } from '@/api/${vue.module}/${vue.feature}';
import { Message } from '@arco-design/web-vue';
import {} from '../types/const';
#if($vue.enums.isEmpty())
import {} from '../types/enum.types';
#else
import { #foreach($entry in ${vue.enums.entrySet()})${entry.value.className}#if($foreach.hasNext), #end#end } from '../types/enum.types';
#if($dictMap.entrySet().size() > 0)
import { useDictStore } from '@/store';
#end
import { toOptions } from '@/utils/enum';
const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading();
#if($dictMap.entrySet().size() > 0)
const { toOptions } = useDictStore();
#end
const title = ref<string>();
const isAddHandle = ref<boolean>(true);

View File

@@ -9,9 +9,9 @@
#foreach($field in ${table.fields})
<!-- $field.comment -->
<a-form-item field="${field.propertyName}" label="${field.comment}" label-col-flex="50px">
#if(${vue.enums.containsKey(${field.propertyName})})
#if(${dictMap.containsKey(${field.propertyName})})
<a-select v-model="formModel.${field.propertyName}"
:options="toOptions(${vue.enums.get(${field.propertyName}).className})"
:options="toOptions($dictMap.get(${field.propertyName}).keyField)"
placeholder="请选择${field.comment}"
allow-clear />
#else
@@ -93,10 +93,10 @@
@page-size-change="(size) => fetchTableData(1, size)"
:bordered="false">
#foreach($field in ${table.fields})
#if(${vue.enums.containsKey(${field.propertyName})})
#if(${dictMap.containsKey(${field.propertyName})})
<!-- $field.comment -->
<template #${field.propertyName}="{ record }">
{{ getEnumValue(record.${field.propertyName}, ${vue.enums.get(${field.propertyName}).className}) }}
{{ getDictValue($dictMap.get(${field.propertyName}).keyField, record.${field.propertyName}}) }}
</template>
#end
#end
@@ -141,18 +141,19 @@
import { Message } from '@arco-design/web-vue';
import useLoading from '@/hooks/loading';
import columns from '../types/table.columns';
#if($dictMap.entrySet().size() > 0)
import { #foreach($entry in ${dictMap.entrySet()})${entry.value.keyField}#if($foreach.hasNext), #end#end } from '../types/const';
#else
import {} from '../types/const';
#end
#if($vue.enableRowSelection)
import { usePagination, useRowSelection } from '@/types/table';
#else
import { usePagination } from '@/types/table';
#end
import {} from '../types/const';
#if($vue.enums.isEmpty())
import {} from '../types/enum.types';
#else
import { #foreach($entry in ${vue.enums.entrySet()})${entry.value.className}#if($foreach.hasNext), #end#end } from '../types/enum.types';
#if($dictMap.entrySet().size() > 0)
import { useDictStore } from '@/store';
#end
import { toOptions, getEnumValue } from '@/utils/enum';
const emits = defineEmits(['openAdd', 'openUpdate']);
@@ -166,6 +167,9 @@
const rowSelection = useRowSelection();
#end
const { loading, setLoading } = useLoading();
#if($dictMap.entrySet().size() > 0)
const { toOptions, getDictValue } = useDictStore();
#end
const formModel = reactive<${vue.featureEntity}QueryRequest>({
#foreach($field in ${table.fields})

View File

@@ -47,12 +47,20 @@
#else
import ${vue.featureEntity}FormModal from './components/${vue.feature}-form-modal.vue';
#end
#if($vue.enableCardView)
import { computed, ref, onBeforeMount } from 'vue';
#if($dictMap.entrySet().size() > 0)
import { useAppStore, useDictStore } from '@/store';
import { dictKeys } from './types/const';
#else
import { useAppStore } from '@/store';
#end
#else
import { ref } from 'vue';
#if($dictMap.entrySet().size() > 0)
import { useDictStore } from '@/store';
import { dictKeys } from './types/const';
#end
#end
const render = ref(false);
@@ -68,7 +76,7 @@
#if($vue.enableCardView)
const appStore = useAppStore();
// FIXME 这里需要修改一下字段名称
// FIXME 这里需要修改一下字段名称 同时 appStore 的类型和 AppPreferenceModel 都需要定义该字段类型
const renderTable = computed(() => appStore.${vue.featureEntityFirstLower}View === 'table');
#end
@@ -99,6 +107,10 @@
};
onBeforeMount(async () => {
#if($dictMap.entrySet().size() > 0)
const dictStore = useDictStore();
await dictStore.loadKeys(dictKeys);
#end
render.value = true;
});

View File

@@ -0,0 +1,23 @@
#if($dictMap.entrySet().size() > 0)
#foreach($enumEntity in $dictMap.entrySet())
/**
* $enumEntity.value.comment
*/
// FIXME 检查这里的类型
export const $enumEntity.value.field = {
#set($count = $enumEntity.value.fields.size() - 1)
#foreach($index in [0..$count])
// $enumEntity.value.labels.get($index)
$enumEntity.value.fields.get($index): '$enumEntity.value.values.get($index)',
#end
}
#end
#foreach($enumEntity in $dictMap.entrySet())
// $enumEntity.value.comment 字典项
export const $enumEntity.value.keyField = '$enumEntity.value.keyName';
#end
// 加载的字典值
export const dictKeys = [#foreach($enumEntity in $dictMap.entrySet())${enumEntity.value.field}Key#if($foreach.hasNext), #end#end];
#end

View File

@@ -1,15 +0,0 @@
#foreach($enumEntity in ${vue.enums.entrySet()})
/**
* $!{enumEntity.value.comment}
*/
export const $enumEntity.value.className = {
#foreach($enumEntityItem in $enumEntity.value.info.entrySet())
$enumEntityItem.key: {
#foreach($enumEntityItemFields in $enumEntityItem.value.entrySet())
$enumEntityItemFields.key: '$!enumEntityItemFields.value',
#end
},
#end
}
#end