package com.vincent.rsf.framework.generators;
|
|
import com.vincent.rsf.framework.common.Cools;
|
import com.vincent.rsf.framework.generators.constant.SqlOsType;
|
import com.vincent.rsf.framework.generators.domain.Column;
|
import com.vincent.rsf.framework.generators.utils.GeneratorUtils;
|
import org.springframework.core.io.ClassPathResource;
|
|
import java.io.BufferedReader;
|
import java.io.BufferedWriter;
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.IOException;
|
import java.io.InputStreamReader;
|
import java.io.OutputStreamWriter;
|
import java.nio.charset.StandardCharsets;
|
import java.sql.Connection;
|
import java.sql.DriverManager;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
|
public class RsfDesignGenerator {
|
|
private static final String BASE_DIR = "src/main/";
|
private static final String JAVA_DIR = BASE_DIR + "java/";
|
private static final String MODULES_DIR = "modules/";
|
private static final List<String> MANAGED_FIELDS = Arrays.asList(
|
"deleted",
|
"tenantId",
|
"createBy",
|
"createTime",
|
"updateBy",
|
"updateTime",
|
"version"
|
);
|
private static final List<String> SEARCH_EXCLUDED_FIELDS = Arrays.asList(
|
"deleted",
|
"tenantId",
|
"createBy",
|
"createTime",
|
"updateBy",
|
"updateTime",
|
"version"
|
);
|
|
public String url;
|
public String username;
|
public String password;
|
public String table;
|
public String tableDesc;
|
public String packagePath;
|
public boolean controller = true;
|
public boolean service = true;
|
public boolean mapper = true;
|
public boolean entity = true;
|
public boolean xml = true;
|
public boolean frontend = true;
|
public boolean sql = true;
|
public SqlOsType sqlOsType;
|
public String backendPrefixPath;
|
public String frontendPrefixPath;
|
public String frontendViewPath;
|
public String frontendApiModule;
|
|
private List<Column> columns = new ArrayList<>();
|
private String fullEntityName;
|
private String simpleEntityName;
|
private String kebabEntityName;
|
private String constantPrefix;
|
private String primaryKeyColumn;
|
private String majorColumn;
|
private String itemName;
|
private String normalizedFrontendViewPath;
|
private String normalizedFrontendApiModule;
|
|
public void build() throws Exception {
|
init();
|
buildBackendArtifacts();
|
if (controller) {
|
writeTemplate("Controller", resolveControllerDirectory(), fullEntityName + "Controller.java");
|
}
|
if (frontend) {
|
buildFrontendArtifacts();
|
}
|
}
|
|
private void init() throws Exception {
|
validateBaseConfig();
|
gainDbInfo();
|
fullEntityName = GeneratorUtils.getNameSpace(table);
|
simpleEntityName = GeneratorUtils.firstCharConvert(fullEntityName, true);
|
kebabEntityName = humpToKebab(simpleEntityName);
|
constantPrefix = GeneratorUtils.humpToLine(simpleEntityName).toUpperCase();
|
primaryKeyColumn = resolvePrimaryKeyColumn();
|
majorColumn = resolveMajorColumn();
|
|
String[] packagePathSplit = packagePath.split("\\.");
|
itemName = packagePathSplit[packagePathSplit.length - 1];
|
normalizedFrontendViewPath = normalizePath(frontendViewPath);
|
normalizedFrontendApiModule = normalizeApiModule(frontendApiModule);
|
}
|
|
private void validateBaseConfig() {
|
if (this.sqlOsType == null) {
|
throw new RuntimeException("请选择sqlOsType!");
|
}
|
if (Cools.isEmpty(this.table)) {
|
throw new RuntimeException("请输入table!");
|
}
|
if (Cools.isEmpty(this.tableDesc)) {
|
throw new RuntimeException("请输入tableDesc!");
|
}
|
if (Cools.isEmpty(this.packagePath)) {
|
throw new RuntimeException("请输入packagePath!");
|
}
|
if (frontend) {
|
if (Cools.isEmpty(frontendPrefixPath)) {
|
throw new RuntimeException("请输入frontendPrefixPath!");
|
}
|
if (Cools.isEmpty(frontendViewPath)) {
|
throw new RuntimeException("请输入frontendViewPath!");
|
}
|
if (Cools.isEmpty(frontendApiModule)) {
|
throw new RuntimeException("请输入frontendApiModule!");
|
}
|
}
|
}
|
|
private void gainDbInfo() throws Exception {
|
Connection connection = null;
|
try {
|
switch (this.sqlOsType) {
|
case MYSQL:
|
Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
|
connection = DriverManager.getConnection("jdbc:mysql://" + url, username, password);
|
this.columns = ReactGenerator.getMysqlColumns(connection, table, true, sqlOsType);
|
break;
|
case SQL_SERVER:
|
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
|
connection = DriverManager.getConnection("jdbc:sqlserver://" + url, username, password);
|
this.columns = ReactGenerator.getSqlServerColumns(connection, table, true, sqlOsType);
|
break;
|
default:
|
throw new RuntimeException("请指定数据库类型!");
|
}
|
} finally {
|
if (connection != null) {
|
try {
|
connection.close();
|
} catch (Exception ignore) {
|
}
|
}
|
}
|
}
|
|
private void buildBackendArtifacts() throws Exception {
|
ReactGenerator generator = new ReactGenerator();
|
generator.url = url;
|
generator.username = username;
|
generator.password = password;
|
generator.table = table;
|
generator.tableDesc = tableDesc;
|
generator.packagePath = packagePath;
|
generator.controller = false;
|
generator.service = service;
|
generator.mapper = mapper;
|
generator.entity = entity;
|
generator.xml = xml;
|
generator.react = false;
|
generator.sql = sql;
|
generator.sqlOsType = sqlOsType;
|
generator.backendPrefixPath = backendPrefixPath;
|
generator.frontendPrefixPath = frontendPrefixPath;
|
generator.build();
|
}
|
|
private void buildFrontendArtifacts() throws IOException {
|
String pageDirectory = resolveFrontendPageDirectory();
|
String modulesDirectory = pageDirectory + MODULES_DIR;
|
writeTemplate("Index", pageDirectory, "index.vue");
|
writeTemplate("PageHelpers", pageDirectory, simpleEntityName + "Page.helpers.js");
|
writeTemplate("TableColumns", pageDirectory, simpleEntityName + "Table.columns.js");
|
writeTemplate("Search", modulesDirectory, kebabEntityName + "-search.vue");
|
writeTemplate("EditDialog", modulesDirectory, kebabEntityName + "-edit-dialog.vue");
|
writeTemplate("Api", resolveFrontendApiDirectory(), normalizedFrontendApiModule + ".js");
|
}
|
|
private String resolveControllerDirectory() {
|
return ensureTrailingSlash(backendPrefixPath)
|
+ JAVA_DIR
|
+ packagePath.replace(".", "/")
|
+ "/controller/";
|
}
|
|
private String resolveFrontendPageDirectory() {
|
return ensureTrailingSlash(frontendPrefixPath) + "src/views/" + normalizedFrontendViewPath + "/";
|
}
|
|
private String resolveFrontendApiDirectory() {
|
String directory = ensureTrailingSlash(frontendPrefixPath) + "src/api/";
|
int index = normalizedFrontendApiModule.lastIndexOf('/');
|
if (index < 0) {
|
return directory;
|
}
|
return directory + normalizedFrontendApiModule.substring(0, index + 1);
|
}
|
|
private void writeTemplate(String templateName, String directory, String fileName) throws IOException {
|
String content = readTemplate(templateName);
|
writeFile(applyReplacements(content), directory, fileName, templateName);
|
}
|
|
private String readTemplate(String templateName) throws IOException {
|
StringBuilder builder = new StringBuilder();
|
ClassPathResource classPath = new ClassPathResource("templates/rsf-design/" + templateName + ".txt");
|
try (BufferedReader reader = new BufferedReader(
|
new InputStreamReader(classPath.getInputStream(), StandardCharsets.UTF_8))) {
|
String lineContent;
|
while ((lineContent = reader.readLine()) != null) {
|
builder.append(lineContent).append("\n");
|
}
|
}
|
return builder.toString();
|
}
|
|
private String applyReplacements(String content) {
|
Map<String, String> replacements = buildReplacements();
|
String resolved = content;
|
for (Map.Entry<String, String> entry : replacements.entrySet()) {
|
resolved = resolved.replace("@{" + entry.getKey() + "}", Objects.toString(entry.getValue(), ""));
|
}
|
return resolved;
|
}
|
|
private Map<String, String> buildReplacements() {
|
Map<String, String> replacements = new LinkedHashMap<>();
|
replacements.put("TABLENAME", table);
|
replacements.put("TABLEDESC", safeText(tableDesc));
|
replacements.put("ENTITYNAME", fullEntityName);
|
replacements.put("SIMPLEENTITYNAME", simpleEntityName);
|
replacements.put("UENTITYNAME", GeneratorUtils.firstCharConvert(simpleEntityName, false));
|
replacements.put("KEBABENTITYNAME", kebabEntityName);
|
replacements.put("COMPANYNAME", packagePath);
|
replacements.put("ITEMNAME", itemName);
|
replacements.put("PRIMARYKEYCOLUMN", GeneratorUtils.firstCharConvert(primaryKeyColumn, false));
|
replacements.put("PRIMARYKEYCOLUMN0", GeneratorUtils.firstCharConvert(primaryKeyColumn, true));
|
replacements.put("MAJORCOLUMN", GeneratorUtils.firstCharConvert(majorColumn, false));
|
replacements.put("MAJORCOLUMN0", GeneratorUtils.firstCharConvert(majorColumn, true));
|
replacements.put("ENTITYPREFIX", constantPrefix);
|
replacements.put("APIMODULE", normalizedFrontendApiModule);
|
replacements.put("SEARCHSTATECONTENT", buildSearchStateContent());
|
replacements.put("FORMSTATECONTENT", buildFormStateContent());
|
replacements.put("FIELDOPTIONSCONTENT", buildFieldOptionsContent());
|
replacements.put("SEARCHPARAMSCONTENT", buildSearchParamsContent());
|
replacements.put("SAVEPAYLOADCONTENT", buildSavePayloadContent());
|
replacements.put("DIALOGMODELCONTENT", buildDialogModelContent());
|
replacements.put("NORMALIZEROWCONTENT", buildNormalizeRowContent());
|
replacements.put("REPORTCOLUMNSCONTENT", buildReportColumnsContent());
|
replacements.put("REPORTSOURCEALIASCONTENT", buildReportSourceAliasContent());
|
replacements.put("SEARCHITEMSCONTENT", buildSearchItemsContent());
|
replacements.put("FORMITEMSCONTENT", buildFormItemsContent());
|
replacements.put("RULESCONTENT", buildRulesContent());
|
replacements.put("TABLECOLUMNSCONTENT", buildTableColumnsContent());
|
replacements.put("EXPORTROWCONTENT", buildExportRowContent());
|
replacements.put("SAVEINITCONTENT", buildSaveInitContent());
|
replacements.put("UPDATEINITCONTENT", buildUpdateInitContent());
|
return replacements;
|
}
|
|
private void writeFile(String content, String directory, String fileName, String templateName) throws IOException {
|
File codeDirectory = new File(directory);
|
if (!codeDirectory.exists()) {
|
codeDirectory.mkdirs();
|
}
|
|
File writerFile = new File(directory + fileName);
|
if (writerFile.exists()) {
|
System.out.println(fullEntityName + templateName + " 源文件已经存在创建失败!");
|
return;
|
}
|
|
writerFile.createNewFile();
|
try (BufferedWriter writer = new BufferedWriter(
|
new OutputStreamWriter(new FileOutputStream(writerFile), StandardCharsets.UTF_8))) {
|
writer.write(content);
|
writer.flush();
|
}
|
System.out.println(fullEntityName + templateName + " 源文件创建成功!");
|
}
|
|
private String resolvePrimaryKeyColumn() {
|
for (Column column : columns) {
|
if (column.isPrimaryKey() || column.isMainKey()) {
|
return column.getHumpName();
|
}
|
}
|
return "id";
|
}
|
|
private String resolveMajorColumn() {
|
for (Column column : columns) {
|
if (column.isMajor()) {
|
return column.getHumpName();
|
}
|
}
|
for (String preferred : Arrays.asList("name", "code", "title", "uuid")) {
|
Column column = findColumn(preferred);
|
if (column != null) {
|
return column.getHumpName();
|
}
|
}
|
for (Column column : columns) {
|
if (!MANAGED_FIELDS.contains(column.getHumpName()) && !column.isPrimaryKey()) {
|
return column.getHumpName();
|
}
|
}
|
return primaryKeyColumn;
|
}
|
|
private Column findColumn(String humpName) {
|
for (Column column : columns) {
|
if (humpName.equals(column.getHumpName())) {
|
return column;
|
}
|
}
|
return null;
|
}
|
|
private boolean hasColumn(String humpName) {
|
return findColumn(humpName) != null;
|
}
|
|
private boolean isManagedColumn(Column column) {
|
return MANAGED_FIELDS.contains(column.getHumpName());
|
}
|
|
private boolean isSearchExcludedColumn(Column column) {
|
return SEARCH_EXCLUDED_FIELDS.contains(column.getHumpName());
|
}
|
|
private boolean isBooleanColumn(Column column) {
|
return "Boolean".equals(column.getType());
|
}
|
|
private boolean isNumericColumn(Column column) {
|
return "Short".equals(column.getType())
|
|| "Integer".equals(column.getType())
|
|| "Long".equals(column.getType())
|
|| "Double".equals(column.getType());
|
}
|
|
private boolean isDateColumn(Column column) {
|
return "Date".equals(column.getType());
|
}
|
|
private boolean hasEnumOptions(Column column) {
|
return !Cools.isEmpty(column.getEnums());
|
}
|
|
private boolean hasForeignDisplay(Column column) {
|
return !Cools.isEmpty(column.getForeignKeyMajor());
|
}
|
|
private boolean isStatusColumn(Column column) {
|
return "status".equals(column.getHumpName());
|
}
|
|
private boolean isMemoColumn(Column column) {
|
return "memo".equals(column.getHumpName());
|
}
|
|
private boolean isSelectableColumn(Column column) {
|
return isBooleanColumn(column) || hasEnumOptions(column);
|
}
|
|
private boolean isDisplayTextColumn(Column column) {
|
return isBooleanColumn(column) || isDateColumn(column) || hasEnumOptions(column) || hasForeignDisplay(column);
|
}
|
|
private List<Column> getSearchColumns() {
|
List<Column> result = new ArrayList<>();
|
for (Column column : columns) {
|
if (column.isPrimaryKey() || isSearchExcludedColumn(column) || isDateColumn(column)) {
|
continue;
|
}
|
result.add(column);
|
}
|
return result;
|
}
|
|
private List<Column> getFormColumns() {
|
List<Column> result = new ArrayList<>();
|
for (Column column : columns) {
|
if (column.isPrimaryKey() || isManagedColumn(column)) {
|
continue;
|
}
|
result.add(column);
|
}
|
return result;
|
}
|
|
private List<Column> getListColumns() {
|
List<Column> result = new ArrayList<>();
|
for (Column column : columns) {
|
if (column.isPrimaryKey()) {
|
continue;
|
}
|
if ("deleted".equals(column.getHumpName()) || "tenantId".equals(column.getHumpName())) {
|
continue;
|
}
|
result.add(column);
|
}
|
return result;
|
}
|
|
private List<Column> getReportColumns() {
|
return getListColumns();
|
}
|
|
private List<Column> getPayloadColumns() {
|
List<Column> result = new ArrayList<>();
|
Column primaryColumn = findColumn(primaryKeyColumn);
|
if (primaryColumn != null) {
|
result.add(primaryColumn);
|
}
|
Column versionColumn = findColumn("version");
|
if (versionColumn != null) {
|
result.add(versionColumn);
|
}
|
result.addAll(getFormColumns());
|
return result;
|
}
|
|
private String buildSearchStateContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getSearchColumns()) {
|
sb.append(" ").append(column.getHumpName()).append(": '',\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildFormStateContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getPayloadColumns()) {
|
sb.append(" ")
|
.append(column.getHumpName())
|
.append(": ")
|
.append(resolveFormDefaultValue(column))
|
.append(",\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildFieldOptionsContent() {
|
StringBuilder sb = new StringBuilder();
|
sb.append("{\n");
|
boolean hasOptions = false;
|
for (Column column : columns) {
|
if (!isSelectableColumn(column)) {
|
continue;
|
}
|
hasOptions = true;
|
sb.append(" ").append(column.getHumpName()).append(": [\n");
|
for (Map<String, Object> option : buildColumnOptions(column)) {
|
sb.append(" { label: '")
|
.append(escapeJs(String.valueOf(option.get("label"))))
|
.append("', value: ")
|
.append(option.get("value"))
|
.append(" },\n");
|
}
|
sb.append(" ],\n");
|
}
|
if (!hasOptions) {
|
return "{}";
|
}
|
sb.append("}");
|
return sb.toString();
|
}
|
|
private String buildSearchParamsContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getSearchColumns()) {
|
sb.append(" ")
|
.append(column.getHumpName())
|
.append(": ")
|
.append(resolveParamNormalizer("params", column))
|
.append(",\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildSavePayloadContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getPayloadColumns()) {
|
sb.append(resolvePayloadLine("formData", column));
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildDialogModelContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getPayloadColumns()) {
|
sb.append(" ")
|
.append(column.getHumpName())
|
.append(": ")
|
.append(resolveDialogValue(column))
|
.append(",\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildNormalizeRowContent() {
|
StringBuilder sb = new StringBuilder();
|
Column statusColumn = findColumn("status");
|
if (statusColumn != null) {
|
sb.append(" statusBool: record.statusBool !== void 0 ? Boolean(record.statusBool) : statusMeta.bool,\n")
|
.append(" statusText: normalizeText(record.statusText || record.status$ || statusMeta.text),\n")
|
.append(" statusType: statusMeta.type,\n");
|
}
|
for (Column column : getReportColumns()) {
|
if (isStatusColumn(column)) {
|
continue;
|
}
|
if (isBooleanColumn(column)) {
|
sb.append(" ")
|
.append(column.getHumpName())
|
.append("Text: formatBooleanText(toOptionalBoolean(record.")
|
.append(column.getHumpName())
|
.append(")),\n");
|
continue;
|
}
|
if (isDisplayTextColumn(column)) {
|
sb.append(" ")
|
.append(column.getHumpName())
|
.append("Text: normalizeText(record.")
|
.append(column.getHumpName())
|
.append("$ || record.")
|
.append(column.getHumpName())
|
.append("Text || record.")
|
.append(column.getHumpName())
|
.append("),\n");
|
}
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildReportColumnsContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getReportColumns()) {
|
sb.append(" { source: '")
|
.append(resolveReportSource(column))
|
.append("', label: '")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("' },\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildReportSourceAliasContent() {
|
Column statusColumn = findColumn("status");
|
if (statusColumn == null) {
|
return "";
|
}
|
return " status: 'statusText'";
|
}
|
|
private String buildSearchItemsContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getSearchColumns()) {
|
if (isSelectableColumn(column)) {
|
sb.append(" createSelectSearchItem('")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', '")
|
.append(column.getHumpName())
|
.append("', '请选择")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', get")
|
.append(fullEntityName)
|
.append("FieldOptions('")
|
.append(column.getHumpName())
|
.append("')),\n");
|
} else {
|
sb.append(" createInputSearchItem('")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', '")
|
.append(column.getHumpName())
|
.append("', '请输入")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("'),\n");
|
}
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildFormItemsContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getFormColumns()) {
|
String label = escapeJs(resolveFieldLabel(column));
|
String key = column.getHumpName();
|
if (isSelectableColumn(column)) {
|
sb.append(" createSelectFormItem('")
|
.append(label)
|
.append("', '")
|
.append(key)
|
.append("', '请选择")
|
.append(label)
|
.append("', get")
|
.append(fullEntityName)
|
.append("FieldOptions('")
|
.append(key)
|
.append("')),\n");
|
continue;
|
}
|
if (isMemoColumn(column) || (column.getLength() != null && column.getLength() > 255)) {
|
sb.append(" createInputFormItem('")
|
.append(label)
|
.append("', '")
|
.append(key)
|
.append("', '请输入")
|
.append(label)
|
.append("', { type: 'textarea', rows: 3 }, { span: 24 }),\n");
|
continue;
|
}
|
if (isNumericColumn(column)) {
|
sb.append(" createInputFormItem('")
|
.append(label)
|
.append("', '")
|
.append(key)
|
.append("', '请输入")
|
.append(label)
|
.append("', { type: 'number' }),\n");
|
continue;
|
}
|
sb.append(" createInputFormItem('")
|
.append(label)
|
.append("', '")
|
.append(key)
|
.append("', '请输入")
|
.append(label)
|
.append("'),\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildRulesContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getFormColumns()) {
|
if (!column.isNotNull()) {
|
continue;
|
}
|
String label = escapeJs(resolveFieldLabel(column));
|
String message = (isSelectableColumn(column) ? "请选择" : "请输入") + label;
|
String trigger = isSelectableColumn(column) ? "change" : "blur";
|
sb.append(" ")
|
.append(column.getHumpName())
|
.append(": [{ required: true, message: '")
|
.append(message)
|
.append("', trigger: '")
|
.append(trigger)
|
.append("' }],\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildTableColumnsContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getListColumns()) {
|
if (isStatusColumn(column)) {
|
sb.append(" createTagColumn('status', '")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', 120, (row) => get")
|
.append(fullEntityName)
|
.append("StatusMeta(row.statusBool ?? row.status)),\n");
|
continue;
|
}
|
if (isNumericColumn(column)) {
|
sb.append(" createNumberColumn('")
|
.append(column.getHumpName())
|
.append("', '")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', 120),\n");
|
continue;
|
}
|
if (isDisplayTextColumn(column)) {
|
sb.append(" createTextColumn('")
|
.append(column.getHumpName())
|
.append("Text', '")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', ")
|
.append(resolveTextColumnWidth(column))
|
.append("),\n");
|
continue;
|
}
|
sb.append(" createTextColumn('")
|
.append(column.getHumpName())
|
.append("', '")
|
.append(escapeJs(resolveFieldLabel(column)))
|
.append("', ")
|
.append(resolveTextColumnWidth(column))
|
.append("),\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildExportRowContent() {
|
StringBuilder sb = new StringBuilder();
|
for (Column column : getReportColumns()) {
|
sb.append(" row.put(\"")
|
.append(resolveReportSource(column))
|
.append("\", ")
|
.append(resolveExportExpression(column))
|
.append(");\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildSaveInitContent() {
|
StringBuilder sb = new StringBuilder();
|
if (hasColumn("createBy")) {
|
sb.append(" ").append(simpleEntityName).append(".setCreateBy(getLoginUserId());\n");
|
}
|
if (hasColumn("createTime")) {
|
sb.append(" ").append(simpleEntityName).append(".setCreateTime(new Date());\n");
|
}
|
if (hasColumn("updateBy")) {
|
sb.append(" ").append(simpleEntityName).append(".setUpdateBy(getLoginUserId());\n");
|
}
|
if (hasColumn("updateTime")) {
|
sb.append(" ").append(simpleEntityName).append(".setUpdateTime(new Date());\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private String buildUpdateInitContent() {
|
StringBuilder sb = new StringBuilder();
|
if (hasColumn("updateBy")) {
|
sb.append(" ").append(simpleEntityName).append(".setUpdateBy(getLoginUserId());\n");
|
}
|
if (hasColumn("updateTime")) {
|
sb.append(" ").append(simpleEntityName).append(".setUpdateTime(new Date());\n");
|
}
|
return trimTrailingLineBreak(sb);
|
}
|
|
private List<Map<String, Object>> buildColumnOptions(Column column) {
|
List<Map<String, Object>> options = new ArrayList<>();
|
if (isBooleanColumn(column) && Cools.isEmpty(column.getEnums())) {
|
options.add(buildOption("是", "true"));
|
options.add(buildOption("否", "false"));
|
return options;
|
}
|
if (Cools.isEmpty(column.getEnums())) {
|
return options;
|
}
|
for (Map<String, Object> item : column.getEnums()) {
|
for (Map.Entry<String, Object> entry : item.entrySet()) {
|
options.add(buildOption(String.valueOf(entry.getValue()), toJsValue(column, String.valueOf(entry.getKey()))));
|
}
|
}
|
return options;
|
}
|
|
private Map<String, Object> buildOption(String label, String jsValue) {
|
Map<String, Object> option = new LinkedHashMap<>();
|
option.put("label", label);
|
option.put("value", jsValue);
|
return option;
|
}
|
|
private String resolveFormDefaultValue(Column column) {
|
if (column == null) {
|
return "void 0";
|
}
|
if (isStatusColumn(column) && isSelectableColumn(column)) {
|
List<Map<String, Object>> options = buildColumnOptions(column);
|
if (!options.isEmpty()) {
|
return String.valueOf(options.get(0).get("value"));
|
}
|
}
|
if (isBooleanColumn(column) || isNumericColumn(column)) {
|
return "void 0";
|
}
|
return "''";
|
}
|
|
private String resolveParamNormalizer(String sourceName, Column column) {
|
String field = sourceName + "." + column.getHumpName();
|
if (isBooleanColumn(column)) {
|
return "toOptionalBoolean(" + field + ")";
|
}
|
if (isNumericColumn(column)) {
|
return "toOptionalNumber(" + field + ")";
|
}
|
return "normalizeText(" + field + ")";
|
}
|
|
private String resolvePayloadLine(String sourceName, Column column) {
|
String field = sourceName + "." + column.getHumpName();
|
if (isBooleanColumn(column)) {
|
return " ...(hasValue(" + field + ") ? { " + column.getHumpName() + ": toOptionalBoolean(" + field + ") } : {}),\n";
|
}
|
if (isNumericColumn(column)) {
|
return " ...buildNumberField('" + column.getHumpName() + "', " + field + "),\n";
|
}
|
return " " + column.getHumpName() + ": normalizeText(" + field + ") || '',\n";
|
}
|
|
private String resolveDialogValue(Column column) {
|
String field = "record." + column.getHumpName();
|
if (isStatusColumn(column) && isSelectableColumn(column)) {
|
List<Map<String, Object>> options = buildColumnOptions(column);
|
String fallback = options.isEmpty() ? "void 0" : String.valueOf(options.get(0).get("value"));
|
if (isBooleanColumn(column)) {
|
return "hasValue(" + field + ") ? toOptionalBoolean(" + field + ") : " + fallback;
|
}
|
if (isNumericColumn(column)) {
|
return "hasValue(" + field + ") ? toOptionalNumber(" + field + ") : " + fallback;
|
}
|
return "normalizeText(" + field + ") || " + fallback;
|
}
|
if (isBooleanColumn(column)) {
|
return "toOptionalBoolean(" + field + ")";
|
}
|
if (isNumericColumn(column)) {
|
return "toOptionalNumber(" + field + ")";
|
}
|
return "normalizeText(" + field + " || '')";
|
}
|
|
private String resolveFieldLabel(Column column) {
|
if (column == null || Cools.isEmpty(column.getComment())) {
|
return column == null ? "" : column.getHumpName();
|
}
|
return column.getComment().trim();
|
}
|
|
private int resolveTextColumnWidth(Column column) {
|
if (isMemoColumn(column)) {
|
return 220;
|
}
|
if (isDateColumn(column)) {
|
return 180;
|
}
|
return 160;
|
}
|
|
private String resolveReportSource(Column column) {
|
if (isStatusColumn(column) || isDisplayTextColumn(column)) {
|
return column.getHumpName() + "Text";
|
}
|
return column.getHumpName();
|
}
|
|
private String resolveExportExpression(Column column) {
|
String getter = "record." + getterName(column);
|
if (isBooleanColumn(column)) {
|
return "Boolean.TRUE.equals(" + getter + "()) ? \"是\" : Boolean.FALSE.equals(" + getter + "()) ? \"否\" : \"\"";
|
}
|
if (isStatusColumn(column) || isDisplayTextColumn(column)) {
|
return getter + "$()";
|
}
|
return getter + "()";
|
}
|
|
private String getterName(Column column) {
|
return "get" + GeneratorUtils.firstCharConvert(column.getHumpName(), false);
|
}
|
|
private String toJsValue(Column column, String rawValue) {
|
if (isBooleanColumn(column)) {
|
if ("1".equals(rawValue) || "true".equalsIgnoreCase(rawValue)) {
|
return "true";
|
}
|
if ("0".equals(rawValue) || "false".equalsIgnoreCase(rawValue)) {
|
return "false";
|
}
|
}
|
if (isNumericColumn(column)) {
|
return rawValue;
|
}
|
return "'" + escapeJs(rawValue) + "'";
|
}
|
|
private String trimTrailingLineBreak(StringBuilder sb) {
|
if (sb.length() == 0) {
|
return "";
|
}
|
while (sb.length() > 0 && (sb.charAt(sb.length() - 1) == '\n' || sb.charAt(sb.length() - 1) == '\r')) {
|
sb.deleteCharAt(sb.length() - 1);
|
}
|
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ',') {
|
sb.deleteCharAt(sb.length() - 1);
|
}
|
return sb.toString();
|
}
|
|
private String safeText(String value) {
|
return value == null ? "" : value.trim();
|
}
|
|
private String escapeJs(String value) {
|
return value
|
.replace("\\", "\\\\")
|
.replace("'", "\\'");
|
}
|
|
private String humpToKebab(String value) {
|
if (Cools.isEmpty(value)) {
|
return "";
|
}
|
return value.replaceAll("([a-z0-9])([A-Z])", "$1-$2").toLowerCase();
|
}
|
|
private String ensureTrailingSlash(String prefix) {
|
if (Cools.isEmpty(prefix)) {
|
return "";
|
}
|
return prefix.endsWith("/") ? prefix : prefix + "/";
|
}
|
|
private String normalizePath(String value) {
|
if (Cools.isEmpty(value)) {
|
return "";
|
}
|
String normalized = value.replace("\\", "/");
|
while (normalized.startsWith("/")) {
|
normalized = normalized.substring(1);
|
}
|
while (normalized.endsWith("/")) {
|
normalized = normalized.substring(0, normalized.length() - 1);
|
}
|
return normalized;
|
}
|
|
private String normalizeApiModule(String value) {
|
String normalized = normalizePath(value);
|
if (normalized.endsWith(".js")) {
|
return normalized.substring(0, normalized.length() - 3);
|
}
|
return normalized;
|
}
|
}
|