diff --git a/play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkUserInfoServiceImpl.java b/play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkUserInfoServiceImpl.java index 3864c7a..a7a8ef4 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkUserInfoServiceImpl.java +++ b/play-admin/src/main/java/com/starry/admin/modules/clerk/service/impl/PlayClerkUserInfoServiceImpl.java @@ -16,6 +16,7 @@ import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityQueryVo; import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoQueryVo; import com.starry.admin.modules.clerk.module.vo.PlayClerkUnsettledWagesInfoReturnVo; import com.starry.admin.modules.clerk.service.IPlayClerkCommodityService; +import com.starry.admin.modules.clerk.service.IPlayClerkLevelInfoService; import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService; import com.starry.admin.modules.custom.entity.PlayCustomFollowInfoEntity; import com.starry.admin.modules.custom.service.IPlayCustomFollowInfoService; @@ -56,8 +57,6 @@ public class PlayClerkUserInfoServiceImpl extends ServiceImpl listAllByTypeId(String typeId) { @@ -182,6 +182,7 @@ public class PlayClerkUserInfoServiceImpl extends ServiceImpl { + ca.setLevelInfo(playClerkLevelInfoService.selectPlayClerkLevelInfoById(ca.getLevelId())); + }); return voPage; } diff --git a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserLoginResponseVo.java b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserLoginResponseVo.java index 2388449..ebb1395 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserLoginResponseVo.java +++ b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/PlayClerkUserLoginResponseVo.java @@ -1,6 +1,7 @@ package com.starry.admin.modules.weichat.entity; import com.alibaba.fastjson2.JSONObject; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; import com.starry.admin.modules.clerk.module.vo.PlayClerkCommodityQueryVo; import lombok.Data; @@ -144,5 +145,9 @@ public class PlayClerkUserLoginResponseVo { private JSONObject pcData; + private PlayClerkLevelInfoEntity levelInfo; + + + } diff --git a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkUserInfoResultVo.java b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkUserInfoResultVo.java index c25dc59..0ff6c20 100644 --- a/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkUserInfoResultVo.java +++ b/play-admin/src/main/java/com/starry/admin/modules/weichat/entity/clerk/PlayClerkUserInfoResultVo.java @@ -1,5 +1,6 @@ package com.starry.admin.modules.weichat.entity.clerk; +import com.starry.admin.modules.clerk.module.entity.PlayClerkLevelInfoEntity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -32,6 +33,7 @@ public class PlayClerkUserInfoResultVo { @ApiModelProperty(value = "店员等级ID") private String levelId; + private PlayClerkLevelInfoEntity levelInfo; /** * 店员等级 */ diff --git a/play-generator/README.md b/play-generator/README.md new file mode 100644 index 0000000..42dac95 --- /dev/null +++ b/play-generator/README.md @@ -0,0 +1,148 @@ +# Play Generator - 代码生成器 + +这是一个独立的代码生成器工具,可以通过 main 方法直接运行生成代码。 + +## 功能特性 + +- 支持 MySQL 数据库表结构读取 +- 自动生成 Entity、Mapper、Service、Controller 等代码文件 +- 基于 Velocity 模板引擎 +- 支持批量生成多个表 +- 可自定义输出目录和包名 + +## 使用方法 + +提供两种方式来使用代码生成器: + +### 方式一:使用配置文件(推荐) + +#### 1. 修改配置文件 + +编辑 `src/main/resources/config.properties` 文件: + +```properties +# 数据库配置 +db.url=jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai +db.driver=com.mysql.cj.jdbc.Driver +db.username=your_username +db.password=your_password + +# 代码生成配置 +gen.author=your_name +gen.packageName=com.your.package +gen.outputDir=./generated-code +gen.autoRemovePre=false +gen.tablePrefix=sys_ +gen.tplCategory=crud + +# 要生成的表名,多个表名用逗号分隔 +gen.tableNames=your_table1,your_table2,your_table3 +``` + +#### 2. 运行生成器 + +直接运行 `MainGeneratorWithConfig.main()` 方法或使用脚本: +- Windows: 双击 `run.bat` +- Linux/Mac: 执行 `./run.sh` + +### 方式二:代码配置 + +#### 1. 配置数据库连接 + +编辑 `MainGenerator.java` 文件中的数据库配置: + +```java +// 数据库配置 +GeneratorConfig config = new GeneratorConfig(); +config.setUrl("jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"); +config.setDriverName("com.mysql.cj.jdbc.Driver"); +config.setUsername("your_username"); +config.setPassword("your_password"); +``` + +#### 2. 配置生成参数 + +```java +// 生成配置 +config.setAuthor("your_name"); +config.setPackageName("com.your.package"); +config.setOutputDir("./generated-code"); +config.setAutoRemovePre(false); +config.setTablePrefix("sys_"); +``` + +#### 3. 指定要生成的表名 + +```java +// 要生成的表名(可以配置多个) +String[] tableNames = { + "your_table1", + "your_table2", + "your_table3" +}; +``` + +### 4. 运行生成器 + +#### 方式一:通过 Maven 运行 +```bash +mvn clean compile exec:java +``` + +#### 方式二:通过 IDE 运行 +直接运行 `MainGenerator.main()` 方法 + +#### 方式三:打包后运行 +```bash +mvn clean package +java -cp target/classes:target/lib/* com.starry.generator.MainGenerator +``` + +## 生成的代码结构 + +``` +generated-code/ +├── src/main/java/com/your/package/ +│ ├── entity/ # 实体类 +│ ├── mapper/ # Mapper 接口 +│ ├── service/ # Service 接口 +│ ├── service/impl/ # Service 实现类 +│ └── controller/ # Controller 类 +└── src/main/resources/ + └── mapper/ # MyBatis XML 文件 +``` + +## 配置参数说明 + +| 参数 | 说明 | 默认值 | +|------|------|--------| +| url | 数据库连接地址 | - | +| driverName | 数据库驱动类名 | com.mysql.cj.jdbc.Driver | +| username | 数据库用户名 | - | +| password | 数据库密码 | - | +| author | 代码作者 | admin | +| packageName | 生成代码的包名 | com.starry.play | +| outputDir | 代码输出目录 | ./generated-code | +| autoRemovePre | 是否自动移除表前缀 | false | +| tablePrefix | 表前缀 | sys_ | +| tplCategory | 模板类型(crud/tree/sub) | crud | + +## 注意事项 + +1. **重要**:首次使用前,请修改 `src/main/resources/config.properties` 文件中的数据库连接信息 +2. 确保数据库连接正常,数据库服务器可访问 +3. 确保指定的表存在于数据库中 +4. 生成的代码会覆盖同名文件,请注意备份 +5. 支持的数据库类型:MySQL 5.7+ +6. 确保数据库用户有足够的权限读取表结构信息 + +## 常见问题 + +### Q: 如何自定义模板? +A: 模板文件位于 `src/main/resources/vm/` 目录下,可以根据需要修改 `.vm` 文件。 + +### Q: 如何修改生成的文件结构? +A: 修改 `CodeGenerator.getFileName()` 方法中的文件路径逻辑。 + +### Q: 支持其他数据库吗? +A: 目前只支持 MySQL,如需支持其他数据库,需要修改 SQL 查询语句和驱动配置。 \ No newline at end of file diff --git a/play-generator/pom.xml b/play-generator/pom.xml index c918d6f..f42217a 100644 --- a/play-generator/pom.xml +++ b/play-generator/pom.xml @@ -52,6 +52,44 @@ 0.2.0 + + + mysql + mysql-connector-java + 8.0.33 + + + + + ch.qos.logback + logback-classic + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/play-generator/run.bat b/play-generator/run.bat new file mode 100644 index 0000000..4edb84e --- /dev/null +++ b/play-generator/run.bat @@ -0,0 +1,4 @@ +@echo off +echo 开始编译和运行代码生成器... +mvn clean compile exec:java +pause \ No newline at end of file diff --git a/play-generator/run.sh b/play-generator/run.sh new file mode 100644 index 0000000..72494b7 --- /dev/null +++ b/play-generator/run.sh @@ -0,0 +1,3 @@ +#!/bin/bash +echo "开始编译和运行代码生成器..." +mvn clean compile exec:java \ No newline at end of file diff --git a/play-generator/src/main/java/com/starry/generator/MainGenerator.java b/play-generator/src/main/java/com/starry/generator/MainGenerator.java new file mode 100644 index 0000000..ee9cfed --- /dev/null +++ b/play-generator/src/main/java/com/starry/generator/MainGenerator.java @@ -0,0 +1,47 @@ +package com.starry.generator; + +import com.starry.generator.core.CodeGenerator; +import com.starry.generator.config.GeneratorConfig; + +/** + * 代码生成器主类 + * 通过main方法直接运行生成代码 + * + * @author admin + * @since 2024-01-01 + */ +public class MainGenerator { + + public static void main(String[] args) { + // 数据库配置 + GeneratorConfig config = new GeneratorConfig(); + config.setUrl("jdbc:mysql://122.51.20.105:3306/play-with?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"); + config.setDriverName("com.mysql.cj.jdbc.Driver"); + config.setUsername("root"); + config.setPassword("KdaKRZ2trpdhNePa"); + + // 生成配置 + config.setAuthor("huchuansai"); + config.setPackageName("com.starry.admin"); + config.setOutputDir("./generated-code"); + config.setAutoRemovePre(false); + config.setTablePrefix("sys_"); + + // 要生成的表名(可以配置多个) + String[] tableNames = { + "sys_role", + }; + + // 创建代码生成器并执行生成 + CodeGenerator generator = new CodeGenerator(config); + + try { + System.out.println("开始生成代码..."); + generator.generateCode(tableNames); + System.out.println("代码生成完成!输出目录:" + config.getOutputDir()); + } catch (Exception e) { + System.err.println("代码生成失败:" + e.getMessage()); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/play-generator/src/main/java/com/starry/generator/MainGeneratorWithConfig.java b/play-generator/src/main/java/com/starry/generator/MainGeneratorWithConfig.java new file mode 100644 index 0000000..a1fe59f --- /dev/null +++ b/play-generator/src/main/java/com/starry/generator/MainGeneratorWithConfig.java @@ -0,0 +1,105 @@ +package com.starry.generator; + +import com.starry.generator.core.CodeGenerator; +import com.starry.generator.config.GeneratorConfig; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * 代码生成器主类 - 支持配置文件版本 + * 通过读取 config.properties 配置文件来生成代码 + * + * @author admin + * @since 2024-01-01 + */ +public class MainGeneratorWithConfig { + + public static void main(String[] args) { + try { + // 读取配置文件 + GeneratorConfig config = loadConfig(); + + // 获取要生成的表名 + String tableNamesStr = getProperty("gen.tableNames", ""); + if (tableNamesStr.isEmpty()) { + System.err.println("错误:未配置要生成的表名,请在 config.properties 中设置 gen.tableNames"); + return; + } + String[] tableNames = tableNamesStr.split(","); + + // 清理表名(去除前后空格) + for (int i = 0; i < tableNames.length; i++) { + tableNames[i] = tableNames[i].trim(); + } + + // 创建代码生成器并执行生成 + CodeGenerator generator = new CodeGenerator(config); + + System.out.println("=== 代码生成器配置信息 ==="); + System.out.println("数据库地址: " + config.getUrl()); + System.out.println("包名: " + config.getPackageName()); + System.out.println("输出目录: " + config.getOutputDir()); + System.out.println("作者: " + config.getAuthor()); + System.out.println("要生成的表: " + String.join(", ", tableNames)); + System.out.println("========================"); + System.out.println(); + + System.out.println("开始生成代码..."); + generator.generateCode(tableNames); + System.out.println(); + System.out.println("代码生成完成!输出目录:" + config.getOutputDir()); + + } catch (Exception e) { + System.err.println("代码生成失败:" + e.getMessage()); + e.printStackTrace(); + } + } + + private static Properties properties; + + private static GeneratorConfig loadConfig() throws IOException { + // 加载配置文件 + properties = new Properties(); + try (InputStream input = MainGeneratorWithConfig.class.getClassLoader() + .getResourceAsStream("config.properties")) { + if (input == null) { + throw new IOException("配置文件 config.properties 未找到"); + } + properties.load(input); + } + + // 创建配置对象 + GeneratorConfig config = new GeneratorConfig(); + + // 数据库配置 + config.setUrl(getProperty("db.url", "")); + config.setDatabaseName(getProperty("db.name", "")); + config.setDriverName(getProperty("db.driver", "com.mysql.cj.jdbc.Driver")); + config.setUsername(getProperty("db.username", "")); + config.setPassword(getProperty("db.password", "")); + + // 生成配置 + config.setAuthor(getProperty("gen.author", "admin")); + config.setPackageName(getProperty("gen.packageName", "com.starry.play")); + config.setOutputDir(getProperty("gen.outputDir", "./generated-code")); + config.setAutoRemovePre(Boolean.parseBoolean(getProperty("gen.autoRemovePre", "false"))); + config.setTablePrefix(getProperty("gen.tablePrefix", "sys_")); + config.setTplCategory(getProperty("gen.tplCategory", "crud")); + + // 验证必需的配置 + if (config.getUrl().isEmpty()) { + throw new IllegalArgumentException("数据库连接地址不能为空,请配置 db.url"); + } + if (config.getUsername().isEmpty()) { + throw new IllegalArgumentException("数据库用户名不能为空,请配置 db.username"); + } + + return config; + } + + private static String getProperty(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } +} \ No newline at end of file diff --git a/play-generator/src/main/java/com/starry/generator/config/GeneratorConfig.java b/play-generator/src/main/java/com/starry/generator/config/GeneratorConfig.java new file mode 100644 index 0000000..98a3902 --- /dev/null +++ b/play-generator/src/main/java/com/starry/generator/config/GeneratorConfig.java @@ -0,0 +1,69 @@ +package com.starry.generator.config; + +import lombok.Data; + +/** + * 代码生成器配置类 + * 用于配置数据库连接和生成参数 + * + * @author admin + * @since 2024-01-01 + */ +@Data +public class GeneratorConfig { + + // 数据库连接配置 + private String url; + private String driverName; + private String username; + private String password; + private String databaseName; + + // 代码生成配置 + private String author; + private String packageName; + private String outputDir; + private boolean autoRemovePre; + private String tablePrefix; + + // 模板类型 (crud, tree, sub) + private String tplCategory = "crud"; + + // 功能名称 + private String functionName; + + // 模块名 + private String moduleName; + + // 业务名 + private String businessName; + + public GeneratorConfig() { + // 设置默认值 + this.author = "admin"; + this.packageName = "com.starry.play"; + this.outputDir = "./generated-code"; + this.autoRemovePre = false; + this.tablePrefix = "sys_"; + this.tplCategory = "crud"; + } + + /** + * 从URL中获取数据库名 + */ + public String getDatabaseName() { + if (databaseName != null && !databaseName.isEmpty()) { + return databaseName; + } + + // 如果没有手动设置数据库名,从URL中解析 + if (url != null) { + String dbName = url.substring(url.lastIndexOf("/") + 1); + if (dbName.contains("?")) { + dbName = dbName.substring(0, dbName.indexOf("?")); + } + return dbName; + } + return ""; + } +} \ No newline at end of file diff --git a/play-generator/src/main/java/com/starry/generator/core/CodeGenerator.java b/play-generator/src/main/java/com/starry/generator/core/CodeGenerator.java new file mode 100644 index 0000000..341331d --- /dev/null +++ b/play-generator/src/main/java/com/starry/generator/core/CodeGenerator.java @@ -0,0 +1,309 @@ +package com.starry.generator.core; + +import com.starry.generator.config.GeneratorConfig; +import com.starry.generator.entity.GenTableEntity; +import com.starry.generator.entity.GenTableColumnEntity; +import com.starry.generator.utils.GenUtils; +import com.starry.generator.utils.VelocityInitializer; +import com.starry.generator.utils.VelocityUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 核心代码生成器 + * + * @author admin + * @since 2024-01-01 + */ +@Slf4j +public class CodeGenerator { + + private final GeneratorConfig config; + + public CodeGenerator(GeneratorConfig config) { + this.config = config; + } + + /** + * 生成代码 + * + * @param tableNames 表名数组 + */ + public void generateCode(String[] tableNames) throws Exception { + // 初始化 Velocity + VelocityInitializer.initVelocity(); + + // 创建输出目录 + createOutputDirectory(); + + for (String tableName : tableNames) { + log.info("开始生成表 {} 的代码", tableName); + generateTableCode(tableName); + log.info("表 {} 代码生成完成", tableName); + } + } + + /** + * 生成单个表的代码 + * + * @param tableName 表名 + */ + private void generateTableCode(String tableName) throws Exception { + // 获取表信息 + GenTableEntity table = getTableInfo(tableName); + if (table == null) { + log.warn("表 {} 不存在,跳过生成", tableName); + return; + } + + // 获取表字段信息 + List columns = getTableColumns(tableName); + table.setColumns(columns); + + // 初始化表信息 + initTableInfo(table); + + // 初始化字段信息 + initColumnInfo(table); + + // 设置主键列信息 + setPkColumn(table); + + // 设置模板变量信息 + VelocityContext context = VelocityUtils.prepareContext(table); + + // 获取模版列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + + for (String template : templates) { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, "UTF-8"); + tpl.merge(context, sw); + + // 写入文件 + writeToFile(template, table, sw.toString()); + } + } + + /** + * 获取表信息 + */ + private GenTableEntity getTableInfo(String tableName) throws Exception { + String sql = "SELECT table_name, table_comment FROM information_schema.tables " + + "WHERE table_schema = ? AND table_name = ?"; + + try (Connection conn = getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + + String dbName = getDatabaseName(); + log.info("查询表信息 - 数据库名: {}, 表名: {}", dbName, tableName); + + stmt.setString(1, dbName); + stmt.setString(2, tableName); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + GenTableEntity table = new GenTableEntity(); + table.setTableName(rs.getString("table_name")); + table.setTableComment(rs.getString("table_comment")); + log.info("找到表: {}, 注释: {}", table.getTableName(), table.getTableComment()); + return table; + } else { + // 如果找不到表,尝试查询所有表来调试 + log.warn("未找到表 {},正在查询数据库 {} 中的所有表...", tableName, dbName); + showAllTables(conn, dbName); + } + } + } + return null; + } + + /** + * 显示数据库中的所有表(用于调试) + */ + private void showAllTables(Connection conn, String dbName) throws Exception { + String sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = ? LIMIT 10"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, dbName); + try (ResultSet rs = stmt.executeQuery()) { + log.info("数据库 {} 中的表:", dbName); + boolean hasTable = false; + while (rs.next()) { + hasTable = true; + log.info(" - {}", rs.getString("table_name")); + } + if (!hasTable) { + log.warn("数据库 {} 中没有找到任何表,请检查数据库名称是否正确", dbName); + } + } + } + } + + /** + * 获取表字段信息 + */ + private List getTableColumns(String tableName) throws Exception { + List columns = new ArrayList<>(); + + String sql = "SELECT column_name, data_type, column_comment, is_nullable, " + + "column_key, column_default, extra FROM information_schema.columns " + + "WHERE table_schema = ? AND table_name = ? ORDER BY ordinal_position"; + + try (Connection conn = getConnection(); + PreparedStatement stmt = conn.prepareStatement(sql)) { + + String dbName = getDatabaseName(); + stmt.setString(1, dbName); + stmt.setString(2, tableName); + + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + GenTableColumnEntity column = new GenTableColumnEntity(); + column.setColumnName(rs.getString("column_name")); + column.setColumnType(rs.getString("data_type")); + column.setColumnComment(rs.getString("column_comment")); + column.setIsRequired("NO".equals(rs.getString("is_nullable")) ? "1" : "0"); + column.setIsPk("PRI".equals(rs.getString("column_key")) ? "1" : "0"); + column.setIsIncrement("auto_increment".equals(rs.getString("extra")) ? "1" : "0"); + + columns.add(column); + } + } + } + + return columns; + } + + /** + * 初始化表信息 + */ + private void initTableInfo(GenTableEntity table) { + table.setClassName(GenUtils.convertClassName(table.getTableName())); + table.setPackageName(config.getPackageName()); + table.setModuleName(GenUtils.getModuleName(config.getPackageName())); + table.setBusinessName(GenUtils.getBusinessName(table.getTableName())); + table.setFunctionName(table.getTableComment()); + table.setFunctionAuthor(config.getAuthor()); + table.setTplCategory(config.getTplCategory()); + } + + /** + * 初始化字段信息 + */ + private void initColumnInfo(GenTableEntity table) { + if (table.getColumns() != null) { + for (GenTableColumnEntity column : table.getColumns()) { + GenUtils.initColumnField(column, table); + } + } + } + + /** + * 设置主键列信息 + */ + private void setPkColumn(GenTableEntity table) { + for (GenTableColumnEntity column : table.getColumns()) { + if ("1".equals(column.getIsPk())) { + table.setPkColumn(column); + break; + } + } + + if (table.getPkColumn() == null) { + table.setPkColumn(table.getColumns().get(0)); + } + } + + /** + * 写入文件 + */ + private void writeToFile(String template, GenTableEntity table, String content) throws IOException { + String fileName = getFileName(template, table); + File file = new File(fileName); + + // 创建父目录 + file.getParentFile().mkdirs(); + + try (FileWriter writer = new FileWriter(file)) { + writer.write(content); + } + + log.info("生成文件:{}", fileName); + } + + /** + * 获取文件名 + */ + private String getFileName(String template, GenTableEntity table) { + String outputDir = config.getOutputDir(); + String packageName = table.getPackageName(); + String moduleName = table.getModuleName(); + String businessName = table.getBusinessName(); + String className = table.getClassName(); + + String javaPath = outputDir + "/src/main/java/" + packageName.replace(".", "/"); + String resourcesPath = outputDir + "/src/main/resources"; + + if (template.contains("entity.java.vm")) { + return javaPath + "/entity/" + className + "Entity.java"; + } else if (template.contains("mapper.java.vm")) { + return javaPath + "/mapper/" + className + "Mapper.java"; + } else if (template.contains("service.java.vm")) { + return javaPath + "/service/I" + className + "Service.java"; + } else if (template.contains("serviceImpl.java.vm")) { + return javaPath + "/service/impl/" + className + "ServiceImpl.java"; + } else if (template.contains("controller.java.vm")) { + return javaPath + "/controller/" + className + "Controller.java"; + } else if (template.contains("queryVo.java.vm")) { + return javaPath + "/vo/" + className + "QueryVo.java"; + } else if (template.contains("addVo.java.vm")) { + return javaPath + "/vo/" + className + "AddVo.java"; + } else if (template.contains("mapper.xml.vm")) { + return resourcesPath + "/mapper/" + className + "Mapper.xml"; + } else if (template.contains("sql.vm")) { + return outputDir + "/" + businessName + "Menu.sql"; + } else if (template.contains("api.js.vm")) { + return outputDir + "/api/" + moduleName + "/" + businessName + ".js"; + } else if (template.contains("index.vue.vm")) { + return outputDir + "/views/" + moduleName + "/" + businessName + "/index.vue"; + } + + return outputDir + "/" + template.replace(".vm", ""); + } + + /** + * 获取数据库连接 + */ + private Connection getConnection() throws Exception { + Class.forName(config.getDriverName()); + return DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword()); + } + + /** + * 从URL中获取数据库名 + */ + private String getDatabaseName() { + return config.getDatabaseName(); + } + + /** + * 创建输出目录 + */ + private void createOutputDirectory() { + File outputDir = new File(config.getOutputDir()); + if (!outputDir.exists()) { + outputDir.mkdirs(); + } + } +} \ No newline at end of file diff --git a/play-generator/src/main/java/com/starry/generator/utils/VelocityUtils.java b/play-generator/src/main/java/com/starry/generator/utils/VelocityUtils.java index cbc4633..0b321b1 100644 --- a/play-generator/src/main/java/com/starry/generator/utils/VelocityUtils.java +++ b/play-generator/src/main/java/com/starry/generator/utils/VelocityUtils.java @@ -279,6 +279,8 @@ public class VelocityUtils { templates.add("vm/java/service.java.vm"); templates.add("vm/java/serviceImpl.java.vm"); templates.add("vm/java/controller.java.vm"); + templates.add("vm/java/queryVo.java.vm"); + templates.add("vm/java/addVo.java.vm"); templates.add("vm/xml/mapper.xml.vm"); templates.add("vm/sql/sql.vm"); templates.add("vm/js/api.js.vm"); @@ -327,6 +329,10 @@ public class VelocityUtils { fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className); } else if (template.contains("controller.java.vm")) { fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className); + } else if (template.contains("queryVo.java.vm")) { + fileName = StringUtils.format("{}/vo/{}QueryVo.java", javaPath, className); + } else if (template.contains("addVo.java.vm")) { + fileName = StringUtils.format("{}/vo/{}AddVo.java", javaPath, className); } else if (template.contains("mapper.xml.vm")) { fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className); } else if (template.contains("sql.vm")) { diff --git a/play-generator/src/main/resources/config.properties b/play-generator/src/main/resources/config.properties new file mode 100644 index 0000000..8ae7ecb --- /dev/null +++ b/play-generator/src/main/resources/config.properties @@ -0,0 +1,17 @@ +# 数据库配置 +db.url=jdbc:mysql://122.51.20.105:3306/play-with?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai +db.driver=com.mysql.cj.jdbc.Driver +db.name=play-with +db.username=root +db.password=KdaKRZ2trpdhNePa + +# 代码生成配置 +gen.author=huchuansai +gen.packageName=com.starry.admin +gen.outputDir=./generated-code +gen.autoRemovePre=false +gen.tablePrefix=sys_ +gen.tplCategory=crud + +# 要生成的表名,多个表名用逗号分隔 +gen.tableNames=sys_role \ No newline at end of file diff --git a/play-generator/src/main/resources/logback.xml b/play-generator/src/main/resources/logback.xml new file mode 100644 index 0000000..68c0d66 --- /dev/null +++ b/play-generator/src/main/resources/logback.xml @@ -0,0 +1,12 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/play-generator/src/main/resources/vm/java/addVo.java.vm b/play-generator/src/main/resources/vm/java/addVo.java.vm new file mode 100644 index 0000000..9ac0159 --- /dev/null +++ b/play-generator/src/main/resources/vm/java/addVo.java.vm @@ -0,0 +1,74 @@ +package ${packageName}.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; +#foreach ($import in $importList) +import ${import}; +#end +import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; + +/** + * ${functionName}添加参数VO + * + * @author ${author} + * @since ${datetime} + */ +@Data +@ApiModel(value = "${functionName}添加参数", description = "新增${functionName}信息的请求参数") +public class ${ClassName}AddVo { + +#foreach ($column in $columns) +#if(!$column.superColumn && !$column.pk) +#if($column.insert == "1") + /** + * $column.columnComment + */ +#if($column.javaType == 'Date') + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "2024-01-01 00:00:00", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "2024-01-01 00:00:00", notes = "$column.columnComment") +#end +#elseif($column.javaType == 'String') +#if($column.isRequired == "1") + @NotBlank(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "示例${column.columnComment}", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "示例${column.columnComment}", notes = "$column.columnComment") +#end +#elseif($column.javaType == 'Integer') +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "1", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#end +#elseif($column.javaType == 'Long') +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, example = "1", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#end +#else +#if($column.isRequired == "1") + @NotNull(message = "${column.columnComment}不能为空") + @ApiModelProperty(value = "$column.columnComment", required = true, notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", notes = "$column.columnComment") +#end +#end + private $column.javaType $column.javaField; + +#end +#end +#end +} \ No newline at end of file diff --git a/play-generator/src/main/resources/vm/java/controller.java.vm b/play-generator/src/main/resources/vm/java/controller.java.vm index b74a074..d9e32e4 100644 --- a/play-generator/src/main/resources/vm/java/controller.java.vm +++ b/play-generator/src/main/resources/vm/java/controller.java.vm @@ -2,21 +2,24 @@ package ${packageName}.controller; import com.starry.common.enums.BusinessType; import com.starry.common.result.R; - - import com.starry.common.annotation.Log; +import ${packageName}.entity.${ClassName}Entity; +import ${packageName}.vo.${ClassName}QueryVo; +import ${packageName}.vo.${ClassName}AddVo; +import ${packageName}.service.I${ClassName}Service; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; - import com.baomidou.mybatisplus.core.metadata.IPage; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; /** * ${functionName}Controller @@ -24,6 +27,7 @@ import org.springframework.web.bind.annotation.RestController; * @author ${author} * @since ${datetime} */ +@Api(tags = "${functionName}管理", description = "${functionName}信息管理相关接口,包括查询、新增、修改、删除等操作") @RestController @RequestMapping("/${moduleName}/${businessName}") public class ${ClassName}Controller { @@ -31,25 +35,45 @@ public class ${ClassName}Controller { private I${ClassName}Service ${className}Service; /** - * 查询${functionName}列表 + * 分页查询${functionName}列表 */ +@ApiOperation(value = "分页查询${functionName}", notes = "分页查询${functionName}信息列表") +@ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ${ClassName}Entity.class, responseContainer = "Page") +}) @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:list')") -@GetMapping("/list") - #if($table.crud || $table.sub) - public R list(${ClassName}Entity ${className}) { - IPage<${ClassName}Entity> list = ${className}Service.select${ClassName}ByPage(${className}); - return R.ok(list); - } - #elseif($table.tree) - public R list(${ClassName}Entity ${className}) { - List<${ClassName}Entity> list = ${className}Service.select${ClassName}List(${className}); - return R.ok(list); - } - #end +@PostMapping("/listByPage") +#if($table.crud || $table.sub) +public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody ${ClassName}QueryVo vo) { + return R.ok(${className}Service.selectByPage(vo)); +} +#elseif($table.tree) +public R listByPage(@ApiParam(value = "查询条件", required = true) @Validated @RequestBody ${ClassName}QueryVo vo) { + return R.ok(${className}Service.select${ClassName}List(vo)); +} +#end + +/** + * 查询所有${functionName}列表 + */ +@ApiOperation(value = "查询所有${functionName}", notes = "获取所有${functionName}信息列表") +@ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ${ClassName}Entity.class, responseContainer = "List") +}) +@PreAuthorize("@customSs.hasPermission('${permissionPrefix}:list')") +@GetMapping("/listAll") +public R listAll() { + return R.ok(${className}Service.selectAll()); +} /** * 获取${functionName}详细信息 */ + @ApiOperation(value = "获取${functionName}详情", notes = "根据ID获取${functionName}详细信息") + @ApiImplicitParam(name = "${pkColumn.javaField}", value = "${functionName}ID", required = true, paramType = "path", dataType = "${pkColumn.javaType}", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = ${ClassName}Entity.class) + }) @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:query')") @GetMapping(value = "/{${pkColumn.javaField}}") public R getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) { @@ -59,11 +83,16 @@ public class ${ClassName}Controller { /** * 新增${functionName} */ + @ApiOperation(value = "新增${functionName}", notes = "创建新的${functionName}信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "添加失败") + }) @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:create')") @Log(title = "${functionName}", businessType = BusinessType.INSERT) @PostMapping("/create") - public R create(@RequestBody ${ClassName}Entity ${className}) { - boolean success = ${className}Service.create(${className}); + public R create(@ApiParam(value = "${functionName}信息", required = true) @Validated @RequestBody ${ClassName}AddVo vo) { + boolean success = ${className}Service.create(vo); if (success) { return R.ok(); } @@ -73,11 +102,17 @@ public class ${ClassName}Controller { /** * 修改${functionName} */ + @ApiOperation(value = "修改${functionName}", notes = "根据ID修改${functionName}信息") + @ApiImplicitParam(name = "${pkColumn.javaField}", value = "${functionName}ID", required = true, paramType = "path", dataType = "${pkColumn.javaType}", example = "1") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功"), + @ApiResponse(code = 500, message = "修改失败") + }) @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:edit')") @Log(title = "${functionName}", businessType = BusinessType.UPDATE) @PostMapping(value = "/update/{${pkColumn.javaField}}") - public R update(@PathVariable ${pkColumn.javaType} ${pkColumn.javaField}, @RequestBody ${ClassName}Entity ${className}) { - ${className}.setId(${pkColumn.javaField}); + public R update(@PathVariable ${pkColumn.javaType} ${pkColumn.javaField}, @ApiParam(value = "${functionName}信息", required = true) @RequestBody ${ClassName}Entity ${className}) { + ${className}.set${pkColumn.capJavaField}(${pkColumn.javaField}); boolean success = ${className}Service.update(${className}); if (success) { return R.ok(); @@ -88,6 +123,11 @@ public class ${ClassName}Controller { /** * 删除${functionName} */ + @ApiOperation(value = "删除${functionName}", notes = "根据ID批量删除${functionName}信息") + @ApiImplicitParam(name = "${pkColumn.javaField}s", value = "${functionName}ID数组", required = true, paramType = "path", dataType = "${pkColumn.javaType}[]", example = "1,2,3") + @ApiResponses({ + @ApiResponse(code = 200, message = "操作成功", response = Integer.class) + }) @PreAuthorize("@customSs.hasPermission('${permissionPrefix}:remove')") @Log(title = "${functionName}", businessType = BusinessType.DELETE) @DeleteMapping("/{${pkColumn.javaField}s}") diff --git a/play-generator/src/main/resources/vm/java/queryVo.java.vm b/play-generator/src/main/resources/vm/java/queryVo.java.vm new file mode 100644 index 0000000..01b4eb5 --- /dev/null +++ b/play-generator/src/main/resources/vm/java/queryVo.java.vm @@ -0,0 +1,50 @@ +package ${packageName}.vo; + +import com.starry.common.domain.BasePageEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +#foreach ($import in $importList) +import ${import}; +#end +#if($table.tree) +import java.util.List; +#end + +/** + * ${functionName}查询参数VO + * + * @author ${author} + * @since ${datetime} + */ +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel(value = "${functionName}查询参数", description = "查询${functionName}信息的条件参数") +public class ${ClassName}QueryVo extends BasePageEntity { + +#foreach ($column in $columns) +#if(!$column.superColumn) +#if($column.query) + /** + * $column.columnComment + */ +#if($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "$column.columnComment", example = "2024-01-01 00:00:00", notes = "$column.columnComment") +#elseif($column.javaType == 'String') + @ApiModelProperty(value = "$column.columnComment", example = "示例${column.columnComment}", notes = "$column.columnComment") +#elseif($column.javaType == 'Integer') + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#elseif($column.javaType == 'Long') + @ApiModelProperty(value = "$column.columnComment", example = "1", notes = "$column.columnComment") +#else + @ApiModelProperty(value = "$column.columnComment", notes = "$column.columnComment") +#end + private $column.javaType $column.javaField; + +#end +#end +#end +} \ No newline at end of file