mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-10 18:27:07 +00:00
feature: 新增生成前端文件模板接口
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package org.ruoyi.generator.controller;
|
package org.ruoyi.generator.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.net.URLDecoder;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.ruoyi.common.core.domain.R;
|
import org.ruoyi.common.core.domain.R;
|
||||||
@@ -8,10 +9,11 @@ import org.ruoyi.generator.service.IGenTableService;
|
|||||||
import org.ruoyi.generator.service.SchemaFieldService;
|
import org.ruoyi.generator.service.SchemaFieldService;
|
||||||
import org.springframework.context.annotation.Profile;
|
import org.springframework.context.annotation.Profile;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代码生成 操作处理
|
* 代码生成 操作处理
|
||||||
*
|
*
|
||||||
@@ -46,4 +48,18 @@ public class GenController extends BaseController {
|
|||||||
genTableService.generateCodeToClasspathByTableNames(tableNameStr);
|
genTableService.generateCodeToClasspathByTableNames(tableNameStr);
|
||||||
return R.ok("代码生成成功");
|
return R.ok("代码生成成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成前端代码
|
||||||
|
*
|
||||||
|
* @param workPath 执行命令路径
|
||||||
|
* @param previewCode 执行生成前端文件命令
|
||||||
|
*/
|
||||||
|
@GetMapping("/batchGenFrontendCode")
|
||||||
|
public R<String> batchGenFrontendCode(@NotNull(message = "路径不能为空") String workPath, @NotNull(message = "指令不能为空") String previewCode) {
|
||||||
|
String decodedWorkPath = URLDecoder.decode(workPath, StandardCharsets.UTF_8);
|
||||||
|
String decodedPreviewCode = URLDecoder.decode(previewCode, StandardCharsets.UTF_8);
|
||||||
|
genTableService.generateFrontendTemplateFiles(decodedWorkPath, decodedPreviewCode);
|
||||||
|
return R.ok("代码生成成功");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,9 @@ import org.ruoyi.generator.util.VelocityInitializer;
|
|||||||
import org.ruoyi.generator.util.VelocityUtils;
|
import org.ruoyi.generator.util.VelocityUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务 服务层实现
|
* 业务 服务层实现
|
||||||
@@ -59,6 +50,41 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateFrontendTemplateFiles(String workPath, String previewCode) {
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
|
||||||
|
ProcessBuilder builder;
|
||||||
|
if (os.contains("win")) {
|
||||||
|
// Windows下用 cmd /c 执行 previewCode
|
||||||
|
builder = new ProcessBuilder("cmd.exe", "/c", previewCode);
|
||||||
|
} else {
|
||||||
|
// macOS/Linux 用 bash -c 执行 previewCode
|
||||||
|
builder = new ProcessBuilder("bash", "-c", previewCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置工作目录
|
||||||
|
builder.directory(new File(workPath));
|
||||||
|
builder.redirectErrorStream(true);
|
||||||
|
|
||||||
|
try (BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
builder.start().getInputStream(),
|
||||||
|
StandardCharsets.UTF_8
|
||||||
|
)
|
||||||
|
)) {
|
||||||
|
String line;
|
||||||
|
log.info("执行结果:");
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
log.info(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成前端代码出错", e);
|
||||||
|
throw new RuntimeException("生成前端代码失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据表名称生成代码到classpath
|
* 根据表名称生成代码到classpath
|
||||||
*/
|
*/
|
||||||
@@ -128,17 +154,17 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
*/
|
*/
|
||||||
private VelocityContext prepareSchemaContext(SchemaVo schema, List<SchemaFieldVo> fields) {
|
private VelocityContext prepareSchemaContext(SchemaVo schema, List<SchemaFieldVo> fields) {
|
||||||
VelocityContext context = new VelocityContext();
|
VelocityContext context = new VelocityContext();
|
||||||
|
|
||||||
// 从配置文件读取基本配置
|
// 从配置文件读取基本配置
|
||||||
String packageName = GenConfig.getPackageName();
|
String packageName = GenConfig.getPackageName();
|
||||||
String author = GenConfig.getAuthor();
|
String author = GenConfig.getAuthor();
|
||||||
String tablePrefix = GenConfig.getTablePrefix();
|
String tablePrefix = GenConfig.getTablePrefix();
|
||||||
boolean autoRemovePre = GenConfig.getAutoRemovePre();
|
boolean autoRemovePre = GenConfig.getAutoRemovePre();
|
||||||
|
|
||||||
// 处理表名和类名
|
// 处理表名和类名
|
||||||
String tableName = schema.getTableName();
|
String tableName = schema.getTableName();
|
||||||
String baseClassName = schema.getTableName();
|
String baseClassName = schema.getTableName();
|
||||||
|
|
||||||
// 自动去除表前缀
|
// 自动去除表前缀
|
||||||
if (autoRemovePre && StrUtil.isNotBlank(tablePrefix)) {
|
if (autoRemovePre && StrUtil.isNotBlank(tablePrefix)) {
|
||||||
String[] prefixes = tablePrefix.split(",");
|
String[] prefixes = tablePrefix.split(",");
|
||||||
@@ -149,12 +175,12 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String className = toCamelCase(baseClassName, true); // 首字母大写的类名,如:SysRole
|
String className = toCamelCase(baseClassName, true); // 首字母大写的类名,如:SysRole
|
||||||
String classname = toCamelCase(baseClassName, false); // 首字母小写的类名,如:sysRole
|
String classname = toCamelCase(baseClassName, false); // 首字母小写的类名,如:sysRole
|
||||||
String businessName = toCamelCase(baseClassName, false);
|
String businessName = toCamelCase(baseClassName, false);
|
||||||
String moduleName = getModuleName(packageName);
|
String moduleName = getModuleName(packageName);
|
||||||
|
|
||||||
// 基本信息
|
// 基本信息
|
||||||
context.put("tableName", tableName);
|
context.put("tableName", tableName);
|
||||||
context.put("tableComment", schema.getComment());
|
context.put("tableComment", schema.getComment());
|
||||||
@@ -168,18 +194,18 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
context.put("packageName", packageName);
|
context.put("packageName", packageName);
|
||||||
context.put("moduleName", moduleName);
|
context.put("moduleName", moduleName);
|
||||||
context.put("businessName", businessName);
|
context.put("businessName", businessName);
|
||||||
|
|
||||||
// 权限相关
|
// 权限相关
|
||||||
context.put("permissionPrefix", moduleName + ":" + businessName);
|
context.put("permissionPrefix", moduleName + ":" + businessName);
|
||||||
context.put("parentMenuId", "2000"); // 默认父菜单ID,可配置
|
context.put("parentMenuId", "2000"); // 默认父菜单ID,可配置
|
||||||
|
|
||||||
// 生成菜单ID
|
// 生成菜单ID
|
||||||
List<Long> menuIds = new ArrayList<>();
|
List<Long> menuIds = new ArrayList<>();
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
menuIds.add(IdUtil.getSnowflakeNextId());
|
menuIds.add(IdUtil.getSnowflakeNextId());
|
||||||
}
|
}
|
||||||
context.put("menuIds", menuIds);
|
context.put("menuIds", menuIds);
|
||||||
|
|
||||||
// 创建table对象,包含menuIds等信息和方法
|
// 创建table对象,包含menuIds等信息和方法
|
||||||
Map<String, Object> table = new HashMap<>();
|
Map<String, Object> table = new HashMap<>();
|
||||||
table.put("menuIds", menuIds);
|
table.put("menuIds", menuIds);
|
||||||
@@ -188,29 +214,29 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
table.put("className", className);
|
table.put("className", className);
|
||||||
table.put("classname", classname);
|
table.put("classname", classname);
|
||||||
table.put("functionName", schema.getName());
|
table.put("functionName", schema.getName());
|
||||||
|
|
||||||
// 添加表类型属性(默认为crud类型)
|
// 添加表类型属性(默认为crud类型)
|
||||||
table.put("crud", true);
|
table.put("crud", true);
|
||||||
table.put("sub", false);
|
table.put("sub", false);
|
||||||
table.put("tree", false);
|
table.put("tree", false);
|
||||||
|
|
||||||
// 添加isSuperColumn方法
|
// 添加isSuperColumn方法
|
||||||
table.put("isSuperColumn", new Object() {
|
table.put("isSuperColumn", new Object() {
|
||||||
public boolean isSuperColumn(String javaField) {
|
public boolean isSuperColumn(String javaField) {
|
||||||
// 定义超类字段(BaseEntity中的字段)
|
// 定义超类字段(BaseEntity中的字段)
|
||||||
return "createBy".equals(javaField) || "createTime".equals(javaField)
|
return "createBy".equals(javaField) || "createTime".equals(javaField)
|
||||||
|| "updateBy".equals(javaField) || "updateTime".equals(javaField)
|
|| "updateBy".equals(javaField) || "updateTime".equals(javaField)
|
||||||
|| "remark".equals(javaField) || "tenantId".equals(javaField);
|
|| "remark".equals(javaField) || "tenantId".equals(javaField);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
context.put("table", table);
|
context.put("table", table);
|
||||||
|
|
||||||
// 处理字段信息
|
// 处理字段信息
|
||||||
List<Map<String, Object>> columns = new ArrayList<>();
|
List<Map<String, Object>> columns = new ArrayList<>();
|
||||||
Map<String, Object> pkColumn = null;
|
Map<String, Object> pkColumn = null;
|
||||||
Set<String> importList = new HashSet<>();
|
Set<String> importList = new HashSet<>();
|
||||||
|
|
||||||
// 添加基础导入
|
// 添加基础导入
|
||||||
importList.add("java.io.Serializable");
|
importList.add("java.io.Serializable");
|
||||||
|
|
||||||
@@ -218,7 +244,7 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
Map<String, Object> column = new HashMap<>();
|
Map<String, Object> column = new HashMap<>();
|
||||||
String javaType = getJavaType(field.getType());
|
String javaType = getJavaType(field.getType());
|
||||||
String javaField = StrUtil.toCamelCase(field.getCode());
|
String javaField = StrUtil.toCamelCase(field.getCode());
|
||||||
|
|
||||||
column.put("columnName", field.getCode());
|
column.put("columnName", field.getCode());
|
||||||
column.put("columnComment", field.getName());
|
column.put("columnComment", field.getName());
|
||||||
column.put("comment", field.getName()); // 添加comment别名
|
column.put("comment", field.getName()); // 添加comment别名
|
||||||
@@ -226,7 +252,7 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
column.put("javaType", javaType);
|
column.put("javaType", javaType);
|
||||||
column.put("javaField", javaField);
|
column.put("javaField", javaField);
|
||||||
column.put("capJavaField", toCamelCase(field.getCode(), true));
|
column.put("capJavaField", toCamelCase(field.getCode(), true));
|
||||||
|
|
||||||
// 布尔值属性(兼容两种格式)
|
// 布尔值属性(兼容两种格式)
|
||||||
boolean isPk = "1".equals(field.getIsPk());
|
boolean isPk = "1".equals(field.getIsPk());
|
||||||
boolean isRequired = "1".equals(field.getIsRequired());
|
boolean isRequired = "1".equals(field.getIsRequired());
|
||||||
@@ -234,7 +260,7 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
boolean isEdit = "1".equals(field.getIsEdit());
|
boolean isEdit = "1".equals(field.getIsEdit());
|
||||||
boolean isList = "1".equals(field.getIsList());
|
boolean isList = "1".equals(field.getIsList());
|
||||||
boolean isQuery = "1".equals(field.getIsQuery());
|
boolean isQuery = "1".equals(field.getIsQuery());
|
||||||
|
|
||||||
column.put("isPk", isPk ? 1 : 0);
|
column.put("isPk", isPk ? 1 : 0);
|
||||||
column.put("pk", isPk); // 添加pk别名
|
column.put("pk", isPk); // 添加pk别名
|
||||||
column.put("isRequired", isRequired);
|
column.put("isRequired", isRequired);
|
||||||
@@ -247,27 +273,27 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
column.put("list", isList); // 添加list别名
|
column.put("list", isList); // 添加list别名
|
||||||
column.put("isQuery", isQuery);
|
column.put("isQuery", isQuery);
|
||||||
column.put("query", isQuery); // 添加query别名
|
column.put("query", isQuery); // 添加query别名
|
||||||
|
|
||||||
column.put("queryType", field.getQueryType());
|
column.put("queryType", field.getQueryType());
|
||||||
column.put("htmlType", field.getHtmlType());
|
column.put("htmlType", field.getHtmlType());
|
||||||
column.put("dictType", field.getDictType());
|
column.put("dictType", field.getDictType());
|
||||||
column.put("sort", field.getSort());
|
column.put("sort", field.getSort());
|
||||||
|
|
||||||
// 添加readConverterExp方法
|
// 添加readConverterExp方法
|
||||||
column.put("readConverterExp", new Object() {
|
column.put("readConverterExp", new Object() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 根据Java类型添加相应的导入
|
// 根据Java类型添加相应的导入
|
||||||
addImportForJavaType(javaType, importList);
|
addImportForJavaType(javaType, importList);
|
||||||
|
|
||||||
columns.add(column);
|
columns.add(column);
|
||||||
|
|
||||||
// 设置主键列
|
// 设置主键列
|
||||||
if (isPk) {
|
if (isPk) {
|
||||||
pkColumn = column;
|
pkColumn = column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有主键,使用第一个字段作为主键
|
// 如果没有主键,使用第一个字段作为主键
|
||||||
if (pkColumn == null && !columns.isEmpty()) {
|
if (pkColumn == null && !columns.isEmpty()) {
|
||||||
pkColumn = columns.get(0);
|
pkColumn = columns.get(0);
|
||||||
@@ -275,27 +301,28 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
pkColumn.put("isPk", 1);
|
pkColumn.put("isPk", 1);
|
||||||
pkColumn.put("pk", true);
|
pkColumn.put("pk", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.put("columns", columns);
|
context.put("columns", columns);
|
||||||
context.put("pkColumn", pkColumn);
|
context.put("pkColumn", pkColumn);
|
||||||
context.put("importList", new ArrayList<>(importList));
|
context.put("importList", new ArrayList<>(importList));
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据Java类型添加相应的导入
|
* 根据Java类型添加相应的导入
|
||||||
*/
|
*/
|
||||||
private void addImportForJavaType(String javaType, Set<String> importList) {
|
private void addImportForJavaType(String javaType, Set<String> importList) {
|
||||||
switch (javaType) {
|
switch (javaType) {
|
||||||
case "BigDecimal" -> importList.add("java.math.BigDecimal");
|
case "BigDecimal" -> importList.add("java.math.BigDecimal");
|
||||||
case "Date" -> importList.add("java.util.Date");
|
case "Date" -> importList.add("java.util.Date");
|
||||||
case "LocalDateTime" -> importList.add("java.time.LocalDateTime");
|
case "LocalDateTime" -> importList.add("java.time.LocalDateTime");
|
||||||
case "LocalDate" -> importList.add("java.time.LocalDate");
|
case "LocalDate" -> importList.add("java.time.LocalDate");
|
||||||
case "LocalTime" -> importList.add("java.time.LocalTime");
|
case "LocalTime" -> importList.add("java.time.LocalTime");
|
||||||
default -> {}
|
default -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从包名中提取模块名
|
* 从包名中提取模块名
|
||||||
@@ -319,10 +346,10 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
String packageName = GenConfig.getPackageName();
|
String packageName = GenConfig.getPackageName();
|
||||||
String tablePrefix = GenConfig.getTablePrefix();
|
String tablePrefix = GenConfig.getTablePrefix();
|
||||||
boolean autoRemovePre = GenConfig.getAutoRemovePre();
|
boolean autoRemovePre = GenConfig.getAutoRemovePre();
|
||||||
|
|
||||||
// 处理类名
|
// 处理类名
|
||||||
String baseClassName = schema.getTableName();
|
String baseClassName = schema.getTableName();
|
||||||
|
|
||||||
// 自动去除表前缀
|
// 自动去除表前缀
|
||||||
if (autoRemovePre && StrUtil.isNotBlank(tablePrefix)) {
|
if (autoRemovePre && StrUtil.isNotBlank(tablePrefix)) {
|
||||||
String[] prefixes = tablePrefix.split(",");
|
String[] prefixes = tablePrefix.split(",");
|
||||||
@@ -333,13 +360,13 @@ public class GenTableServiceImpl implements IGenTableService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String className = toCamelCase(baseClassName, true); // 首字母大写,如:SysRole
|
String className = toCamelCase(baseClassName, true); // 首字母大写,如:SysRole
|
||||||
// 首字母小写,如:sysRole
|
// 首字母小写,如:sysRole
|
||||||
String moduleName = getModuleName(packageName);
|
String moduleName = getModuleName(packageName);
|
||||||
String javaPath = "src/main/java/";
|
String javaPath = "src/main/java/";
|
||||||
String mybatisPath = "src/main/resources/mapper/";
|
String mybatisPath = "src/main/resources/mapper/";
|
||||||
|
|
||||||
if (template.contains("domain.java.vm")) {
|
if (template.contains("domain.java.vm")) {
|
||||||
return javaPath + packageName.replace(".", "/") + "/domain/" + className + ".java";
|
return javaPath + packageName.replace(".", "/") + "/domain/" + className + ".java";
|
||||||
} else if (template.contains("mapper.java.vm")) {
|
} else if (template.contains("mapper.java.vm")) {
|
||||||
|
|||||||
@@ -13,4 +13,12 @@ public interface IGenTableService {
|
|||||||
* @param tableName 表名称数组
|
* @param tableName 表名称数组
|
||||||
*/
|
*/
|
||||||
void generateCodeToClasspathByTableNames(String tableName);
|
void generateCodeToClasspathByTableNames(String tableName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成前端文件
|
||||||
|
*
|
||||||
|
* @param workPath 执行命令路径
|
||||||
|
* @param previewCode 执行生成前端文件命令
|
||||||
|
*/
|
||||||
|
void generateFrontendTemplateFiles(String workPath, String previewCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ SET FOREIGN_KEY_CHECKS = 1;
|
|||||||
|
|
||||||
|
|
||||||
-- 菜单
|
-- 菜单
|
||||||
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1946483381643743233, '知识库角色管理', 1775500307898949634, '12', 'knowledgeRole', 'system/knowledgeRole/index', NULL, 1, 0, 'C', '0', '0', NULL, 'ri:user-3-fill', 103, 1, '2025-07-19 16:41:17', NULL, NULL, '知识库角色管理');
|
INSERT INTO `sys_menu` (`menu_id`, `menu_name`, `parent_id`, `order_num`, `path`, `component`, `query_param`, `is_frame`, `is_cache`, `menu_type`, `visible`, `status`, `perms`, `icon`, `create_dept`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) VALUES (1946483381643743233, '知识库角色管理', 1775500307898949634, '12', 'knowledgeRole', 'operator/knowledgeRole/index', NULL, 1, 0, 'C', '0', '0', NULL, 'ri:user-3-fill', 103, 1, '2025-07-19 16:41:17', NULL, NULL, '知识库角色管理');
|
||||||
|
|
||||||
-- 用户表添加字段
|
-- 用户表添加字段
|
||||||
ALTER TABLE sys_user
|
ALTER TABLE sys_user
|
||||||
|
|||||||
Reference in New Issue
Block a user