diff --git a/README.md b/README.md index e4a9eb5de..a2c8bc986 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ * 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等,基于 MyBatis Plus、Redis + Redisson 操作 * 消息队列可使用 Event、Redis、RabbitMQ、Kafka、RocketMQ 等 * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录 -* 支持加载动态权限菜单,按钮级别权限控制,本地缓存提升性能 +* 支持加载动态权限菜单,按钮级别权限控制,Redis 缓存提升性能 * 支持 SaaS 多租户系统,可自定义每个租户的权限,提供透明化的多租户底层封装 -* 工作流使用 Flowable,支持动态表单、在线设计流程、会签 / 或签、多种任务分配方式 -* 高效率开发,使用代码生成器可以一键生成前后端代码 + 单元测试 + Swagger 接口文档 + Validator 参数校验 +* 高效率开发,使用代码生成器可以一键生成 Java、Vue 前后端代码、SQL 脚本、接口文档,支持单表、树表、主子表 +* 实时通信,采用 Spring WebSocket 实现,内置 Token 身份校验,支持 WebSocket 集群 * 集成微信小程序、微信公众号、企业微信、钉钉等三方登陆,集成支付宝、微信等支付与退款 * 集成阿里云、腾讯云等短信渠道,集成 MinIO、阿里云、腾讯云、七牛云等云存储服务 * 集成报表设计器、大屏设计器,通过拖拽即可生成酷炫的报表与大屏 @@ -55,14 +55,28 @@ ### 前端项目 -| 项目 | Star | 简介 | -|----------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------| -| [yudao-ui-admin-vue3](https://gitee.com/yudaocode/yudao-ui-admin-vue3) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vue3/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vue3) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vue3.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vue3) | 基于 Vue3 + element-plus 实现的管理后台 | -| [yudao-ui-admin-vben](https://gitee.com/yudaocode/yudao-ui-admin-vben) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vben/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vben) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vben.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vben) | 基于 Vue3 + element-plus 实现的管理后台 | -| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 | -| [yudao-ui-admin-vue2](https://gitee.com/yudaocode/yudao-ui-admin-vue2) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vue2/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vue2) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vue2.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vue2) | 基于 Vue2 + element-ui 实现的管理后台 | -| [yudao-ui-admin-uniapp](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-uniapp) | 基于 Vue2 + element-ui 实现的管理后台 | -| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | +| 项目 | Star | 简介 | +|----------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------| +| [yudao-ui-admin-vue3](https://gitee.com/yudaocode/yudao-ui-admin-vue3) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vue3/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vue3) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vue3.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vue3) | 基于 Vue3 + element-plus 实现的管理后台 | +| [yudao-ui-admin-vben](https://gitee.com/yudaocode/yudao-ui-admin-vben) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vben/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vben) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vben.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vben) | 基于 Vue3 + vben(ant-design-vue) 实现的管理后台 | +| [yudao-mall-uniapp](https://gitee.com/yudaocode/yudao-mall-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-mall-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-mall-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-mall-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-mall-uniapp) | 基于 uni-app 实现的商城小程序 | +| [yudao-ui-admin-vue2](https://gitee.com/yudaocode/yudao-ui-admin-vue2) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-vue2/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-vue2) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-vue2.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-vue2) | 基于 Vue2 + element-ui 实现的管理后台 | +| [yudao-ui-admin-uniapp](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-admin-uniapp/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-admin-uniapp) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-admin-uniapp.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-admin-uniapp) | 基于 Vue2 + element-ui 实现的管理后台 | +| [yudao-ui-go-view](https://gitee.com/yudaocode/yudao-ui-go-view) | [![Gitee star](https://gitee.com/yudaocode/yudao-ui-go-view/badge/star.svg?theme=white)](https://gitee.com/yudaocode/yudao-ui-go-view) [![GitHub stars](https://img.shields.io/github/stars/yudaocode/yudao-ui-go-view.svg?style=social&label=Stars)](https://github.com/yudaocode/yudao-ui-go-view) | 基于 Vue3 + naive-ui 实现的大屏报表 | + +## 🐰 分支说明 + +| | JDK 8 完整版 | JDK 17 完整版 | +|-------|---------------------------------------------------------|----------------------------------------------------------------------------------| +| 分支 | [`master`](https://gitee.com/zhijiantianya/yudao-cloud) | [`master-boot3`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master-boot3/) | +| 说明 | 包括所有功能 | 适配 Spring Boot 3.X | +| 系统功能 | √ | √ | +| 基础设施 | √ | √ | +| 会员中心 | √ | √ | +| 工作流程 | √ | √ | +| 数据报表 | √ | 适配中 | +| 商城系统 | √ | √ | +| 微信公众号 | √ | √ | ## 😎 开源协议 @@ -154,27 +168,28 @@ ### 基础设施 -| | 功能 | 描述 | -|-----|----------|----------------------------------------------| -| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | -| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | -| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | -| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 | -| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | -| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | -| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 | -| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | -| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | -| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | -| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 | -| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | -| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 | -| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 | -| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 | -| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 | -| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 | -| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | -| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | +| | 功能 | 描述 | +|----|-----------|----------------------------------------------| +| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 | +| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 | +| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 | +| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 | +| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 | +| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 | +| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 | +| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 | +| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 | +| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 | +| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 | +| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 | +| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 | +| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 | +| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 | +| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 | +| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 | +| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 | +| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 | +| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 | ### 数据报表 diff --git a/pom.xml b/pom.xml index 84fda9663..1ff0864c6 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.8.3-snapshot + 1.9.0-snapshot 1.8 ${java.version} diff --git a/sql/db2/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java b/sql/db2/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java new file mode 100644 index 000000000..fbc4c6bc1 --- /dev/null +++ b/sql/db2/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java @@ -0,0 +1,598 @@ +package liquibase.database.core; + +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import liquibase.CatalogAndSchema; +import liquibase.Scope; +import liquibase.database.AbstractJdbcDatabase; +import liquibase.database.DatabaseConnection; +import liquibase.database.OfflineConnection; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.DatabaseException; +import liquibase.exception.UnexpectedLiquibaseException; +import liquibase.exception.ValidationErrors; +import liquibase.executor.ExecutorService; +import liquibase.statement.DatabaseFunction; +import liquibase.statement.SequenceCurrentValueFunction; +import liquibase.statement.SequenceNextValueFunction; +import liquibase.statement.core.RawCallStatement; +import liquibase.statement.core.RawSqlStatement; +import liquibase.structure.DatabaseObject; +import liquibase.structure.core.Catalog; +import liquibase.structure.core.Index; +import liquibase.structure.core.PrimaryKey; +import liquibase.structure.core.Schema; +import liquibase.util.JdbcUtils; +import liquibase.util.StringUtil; + +public class DmDatabase extends AbstractJdbcDatabase { + private static final String PRODUCT_NAME = "DM DBMS"; + + @Override + protected String getDefaultDatabaseProductName() { + return PRODUCT_NAME; + } + + /** + * Is this AbstractDatabase subclass the correct one to use for the given connection. + * + * @param conn + */ + @Override + public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException { + return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName()); + } + + /** + * If this database understands the given url, return the default driver class name. Otherwise return null. + * + * @param url + */ + @Override + public String getDefaultDriver(String url) { + if(url.startsWith("jdbc:dm")) { + return "dm.jdbc.driver.DmDriver"; + } + + return null; + } + + /** + * Returns an all-lower-case short name of the product. Used for end-user selecting of database type + * such as the DBMS precondition. + */ + @Override + public String getShortName() { + return "dm"; + } + + @Override + public Integer getDefaultPort() { + return 5236; + } + + /** + * Returns whether this database support initially deferrable columns. + */ + @Override + public boolean supportsInitiallyDeferrableColumns() { + return true; + } + + @Override + public boolean supportsTablespaces() { + return true; + } + + @Override + public int getPriority() { + return PRIORITY_DEFAULT; + } + + private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*"); + + protected final int SHORT_IDENTIFIERS_LENGTH = 30; + protected final int LONG_IDENTIFIERS_LEGNTH = 128; + public static final int ORACLE_12C_MAJOR_VERSION = 12; + + private Set reservedWords = new HashSet<>(); + private Set userDefinedTypes; + private Map savedSessionNlsSettings; + + private Boolean canAccessDbaRecycleBin; + private Integer databaseMajorVersion; + private Integer databaseMinorVersion; + + /** + * Default constructor for an object that represents the Oracle Database DBMS. + */ + public DmDatabase() { + super.unquotedObjectsAreUppercased = true; + //noinspection HardCodedStringLiteral + super.setCurrentDateTimeFunction("SYSTIMESTAMP"); + // Setting list of Oracle's native functions + //noinspection HardCodedStringLiteral + dateFunctions.add(new DatabaseFunction("SYSDATE")); + //noinspection HardCodedStringLiteral + dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP")); + //noinspection HardCodedStringLiteral + dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP")); + //noinspection HardCodedStringLiteral + super.sequenceNextValueFunction = "%s.nextval"; + //noinspection HardCodedStringLiteral + super.sequenceCurrentValueFunction = "%s.currval"; + } + + private void tryProxySession(final String url, final Connection con) { + Matcher m = PROXY_USER.matcher(url); + if (m.matches()) { + Properties props = new Properties(); + props.put("PROXY_USER_NAME", m.group(1)); + try { + Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class); + method.setAccessible(true); + method.invoke(con, 1, props); + } catch (Exception e) { + Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage()); + } + } + } + + @Override + public int getDatabaseMajorVersion() throws DatabaseException { + if (databaseMajorVersion == null) { + return super.getDatabaseMajorVersion(); + } else { + return databaseMajorVersion; + } + } + + @Override + public int getDatabaseMinorVersion() throws DatabaseException { + if (databaseMinorVersion == null) { + return super.getDatabaseMinorVersion(); + } else { + return databaseMinorVersion; + } + } + + @Override + public String getJdbcCatalogName(CatalogAndSchema schema) { + return null; + } + + @Override + public String getJdbcSchemaName(CatalogAndSchema schema) { + return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class); + } + + @Override + protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) { + if (StringUtil.isEmpty(generationType)) { + return super.getAutoIncrementClause(); + } + + String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ] + String generationStrategy = generationType; + if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) { + generationStrategy += " ON NULL"; + } + return String.format(autoIncrementClause, generationStrategy); + } + + @Override + public String generatePrimaryKeyName(String tableName) { + if (tableName.length() > 27) { + //noinspection HardCodedStringLiteral + return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27); + } else { + //noinspection HardCodedStringLiteral + return "PK_" + tableName.toUpperCase(Locale.US); + } + } + + @Override + public boolean isReservedWord(String objectName) { + return reservedWords.contains(objectName.toUpperCase()); + } + + @Override + public boolean supportsSequences() { + return true; + } + + /** + * Oracle supports catalogs in liquibase terms + * + * @return false + */ + @Override + public boolean supportsSchemas() { + return false; + } + + @Override + protected String getConnectionCatalogName() throws DatabaseException { + if (getConnection() instanceof OfflineConnection) { + return getConnection().getCatalog(); + } + try { + //noinspection HardCodedStringLiteral + return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class); + } catch (Exception e) { + //noinspection HardCodedStringLiteral + Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e); + } + return null; + } + + @Override + public String getDefaultCatalogName() {//NOPMD + return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US); + } + + /** + *

Returns an Oracle date literal with the same value as a string formatted using ISO 8601.

+ * + *

Convert an ISO8601 date string to one of the following results: + * to_date('1995-05-23', 'YYYY-MM-DD') + * to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')

+ *

+ * Implementation restriction:
+ * Currently, only the following subsets of ISO8601 are supported:
+ *

    + *
  • YYYY-MM-DD
  • + *
  • YYYY-MM-DDThh:mm:ss
  • + *
+ */ + @Override + public String getDateLiteral(String isoDate) { + String normalLiteral = super.getDateLiteral(isoDate); + + if (isDateOnly(isoDate)) { + return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')"; + } else if (isTimeOnly(isoDate)) { + return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')"; + } else if (isTimestamp(isoDate)) { + return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')"; + } else if (isDateTime(isoDate)) { + int seppos = normalLiteral.lastIndexOf('.'); + if (seppos != -1) { + normalLiteral = normalLiteral.substring(0, seppos) + "'"; + } + return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')"; + } + return "UNSUPPORTED:" + isoDate; + } + + @Override + public boolean isSystemObject(DatabaseObject example) { + if (example == null) { + return false; + } + + if (this.isLiquibaseObject(example)) { + return false; + } + + if (example instanceof Schema) { + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) { + return true; + } + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) { + return true; + } + } else if (isSystemObject(example.getSchema())) { + return true; + } + if (example instanceof Catalog) { + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) { + return true; + } + } else if (example.getName() != null) { + //noinspection HardCodedStringLiteral + if (example.getName().startsWith("BIN$")) { //oracle deleted table + boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin(); + if (!filteredInOriginalQuery) { + filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName()); + } + + if (filteredInOriginalQuery) { + return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof + liquibase.statement.UniqueConstraint)); + } else { + return true; + } + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("AQ$")) { //oracle AQ tables + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("DR$")) { //oracle index tables + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("SYS_IOT_OVER")) { //oracle system table + return true; + } else //noinspection HardCodedStringLiteral,HardCodedStringLiteral + if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) { + // CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("MLOG$_")) { //Created by materliaized view logs for every table that is part of a materialized view. Not available for DDL operations. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("RUPD$_")) { //Created by materialized view log tables using primary keys. Not available for DDL operations. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("WM$_")) { //Workspace Manager backup tables. + return true; + } else //noinspection HardCodedStringLiteral + if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) { //This table contains the name of the Java object, the date it was loaded, and has a BLOB column to store the Java object. + return true; + } else //noinspection HardCodedStringLiteral + if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) { //This is a hash table that tracks the loading of Java objects into a schema. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("ISEQ$$_")) { //System-generated sequence + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("USLOG$")) { //for update materialized view + return true; + } else if (example.getName().startsWith("SYS_FBA")) { //for Flashback tables + return true; + } + } + + return super.isSystemObject(example); + } + + @Override + public boolean supportsAutoIncrement() { + // Oracle supports Identity beginning with version 12c + boolean isAutoIncrementSupported = false; + + try { + if (getDatabaseMajorVersion() >= 12) { + isAutoIncrementSupported = true; + } + + // Returning true will generate create table command with 'IDENTITY' clause, example: + // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) GENERATED BY DEFAULT AS IDENTITY NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey)); + + // While returning false will continue to generate create table command without 'IDENTITY' clause, example: + // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey)); + + } catch (DatabaseException ex) { + isAutoIncrementSupported = false; + } + + return isAutoIncrementSupported; + } + + +// public Set findUniqueConstraints(String schema) throws DatabaseException { +// Set returnSet = new HashSet(); +// +// List maps = new Executor(this).queryForList(new RawSqlStatement("SELECT UC.CONSTRAINT_NAME, UCC.TABLE_NAME, UCC.COLUMN_NAME FROM USER_CONSTRAINTS UC, USER_CONS_COLUMNS UCC WHERE UC.CONSTRAINT_NAME=UCC.CONSTRAINT_NAME AND CONSTRAINT_TYPE='U' ORDER BY UC.CONSTRAINT_NAME")); +// +// UniqueConstraint constraint = null; +// for (Map map : maps) { +// if (constraint == null || !constraint.getName().equals(constraint.getName())) { +// returnSet.add(constraint); +// Table table = new Table((String) map.get("TABLE_NAME")); +// constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table); +// } +// } +// if (constraint != null) { +// returnSet.add(constraint); +// } +// +// return returnSet; +// } + + @Override + public boolean supportsRestrictForeignKeys() { + return false; + } + + @Override + public int getDataTypeMaxParameters(String dataTypeName) { + //noinspection HardCodedStringLiteral + if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) { + return 0; + } + //noinspection HardCodedStringLiteral + if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) { + return 0; + } + return super.getDataTypeMaxParameters(dataTypeName); + } + + public String getSystemTableWhereClause(String tableNameColumn) { + List clauses = new ArrayList(Arrays.asList("BIN$", + "AQ$", + "DR$", + "SYS_IOT_OVER", + "MLOG$_", + "RUPD$_", + "WM$_", + "ISEQ$$_", + "USLOG$", + "SYS_FBA")); + + for (int i = 0;i getUserDefinedTypes() { + if (userDefinedTypes == null) { + userDefinedTypes = new HashSet<>(); + if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) { + try { + try { + //noinspection HardCodedStringLiteral + userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class)); + } catch (DatabaseException e) { //fall back to USER_TYPES if the user cannot see ALL_TYPES + //noinspection HardCodedStringLiteral + userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class)); + } + } catch (DatabaseException e) { + //ignore error + } + } + } + + return userDefinedTypes; + } + + @Override + public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) { + //noinspection HardCodedStringLiteral + if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) { + return databaseFunction.toString(); + } + if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof + SequenceCurrentValueFunction)) { + String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction); + // replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval + return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\""); + + } + + return super.generateDatabaseFunctionValue(databaseFunction); + } + + @Override + public ValidationErrors validate() { + ValidationErrors errors = super.validate(); + DatabaseConnection connection = getConnection(); + if ((connection == null) || (connection instanceof OfflineConnection)) { + //noinspection HardCodedStringLiteral + Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database"); + return errors; + } + + if (!canAccessDbaRecycleBin()) { + errors.addWarning(getDbaRecycleBinWarning()); + } + + return errors; + + } + + public String getDbaRecycleBinWarning() { + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral, + // HardCodedStringLiteral + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " + + "constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " + + "referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" + + " issue.\n" + + "\n" + + "The user you used to connect to the database (" + getConnection().getConnectionUserName() + + ") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " + + "Please run the following SQL to set the appropriate permissions, and try running the command again.\n" + + "\n" + + " GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";"; + } + + public boolean canAccessDbaRecycleBin() { + if (canAccessDbaRecycleBin == null) { + DatabaseConnection connection = getConnection(); + if ((connection == null) || (connection instanceof OfflineConnection)) { + return false; + } + + Statement statement = null; + try { + statement = ((JdbcConnection) connection).createStatement(); + @SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1"); + resultSet.close(); //don't need to do anything with the result set, just make sure statement ran. + this.canAccessDbaRecycleBin = true; + } catch (Exception e) { + //noinspection HardCodedStringLiteral + if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) { //ORA-00942: table or view does not exist + this.canAccessDbaRecycleBin = false; + } else { + //noinspection HardCodedStringLiteral + Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e); + this.canAccessDbaRecycleBin = false; + } + } finally { + JdbcUtils.close(null, statement); + } + } + + return canAccessDbaRecycleBin; + } + + @Override + public boolean supportsNotNullConstraintNames() { + return true; + } + + /** + * Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has + * the following form (case-insensitive comparison): + * 1st character: A-Z + * 2..n characters: A-Z0-9$_# + * The maximum length of an identifier differs by Oracle version and object type. + */ + public boolean isValidOracleIdentifier(String identifier, Class type) { + if ((identifier == null) || (identifier.length() < 1)) + return false; + + if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$")) + return false; + + /* + * @todo It seems we currently do not have a class for tablespace identifiers, and all other classes + * we do know seem to be supported as 12cR2 long identifiers, so: + */ + return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH); + } + + /** + * Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this + * is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare + * object types). + * + * @return the maximum length of an object identifier, in bytes + */ + public int getIdentifierMaximumLength() { + try { + if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) { + return SHORT_IDENTIFIERS_LENGTH; + } else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) { + return SHORT_IDENTIFIERS_LENGTH; + } else { + return LONG_IDENTIFIERS_LEGNTH; + } + } catch (DatabaseException ex) { + throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex); + } + + } +} diff --git a/sql/db2/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java b/sql/db2/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java new file mode 100644 index 000000000..cda2492e2 --- /dev/null +++ b/sql/db2/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java @@ -0,0 +1,165 @@ +package liquibase.datatype.core; + +import liquibase.change.core.LoadDataChange; +import liquibase.database.Database; +import liquibase.database.core.*; +import liquibase.datatype.DataTypeInfo; +import liquibase.datatype.DatabaseDataType; +import liquibase.datatype.LiquibaseDataType; +import liquibase.exception.UnexpectedLiquibaseException; +import liquibase.statement.DatabaseFunction; +import liquibase.util.StringUtil; + +import java.util.Locale; +import java.util.regex.Pattern; + +@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT) +public class BooleanType extends LiquibaseDataType { + + @Override + public DatabaseDataType toDatabaseDataType(Database database) { + String originalDefinition = StringUtil.trimToEmpty(getRawDefinition()); + if ((database instanceof Firebird3Database)) { + return new DatabaseDataType("BOOLEAN"); + } + + if ((database instanceof Db2zDatabase) || (database instanceof FirebirdDatabase)) { + return new DatabaseDataType("SMALLINT"); + } else if (database instanceof MSSQLDatabase) { + return new DatabaseDataType(database.escapeDataTypeName("bit")); + } else if (database instanceof MySQLDatabase) { + if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) { + return new DatabaseDataType("BIT", getParameters()); + } + return new DatabaseDataType("BIT", 1); + } else if (database instanceof OracleDatabase) { + return new DatabaseDataType("NUMBER", 1); + } else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) { + return new DatabaseDataType("BIT"); + } else if (database instanceof DerbyDatabase) { + if (((DerbyDatabase) database).supportsBooleanDataType()) { + return new DatabaseDataType("BOOLEAN"); + } else { + return new DatabaseDataType("SMALLINT"); + } + } else if (database instanceof DB2Database) { + if (((DB2Database) database).supportsBooleanDataType()) + return new DatabaseDataType("BOOLEAN"); + else + return new DatabaseDataType("SMALLINT"); + } else if (database instanceof HsqlDatabase) { + return new DatabaseDataType("BOOLEAN"); + } else if (database instanceof PostgresDatabase) { + if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) { + return new DatabaseDataType("BIT", getParameters()); + } + } else if (database instanceof DmDatabase) { // dhb52: DM Support + return new DatabaseDataType("bit"); + } + + return super.toDatabaseDataType(database); + } + + @Override + public String objectToSql(Object value, Database database) { + if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) { + return null; + } + + String returnValue; + if (value instanceof String) { + value = ((String) value).replaceAll("'", ""); + if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) { + returnValue = this.getTrueBooleanValue(database); + } else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals( + ((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) { + returnValue = this.getFalseBooleanValue(database); + } else if (database instanceof PostgresDatabase && Pattern.matches("b?([01])\\1*(::bit|::\"bit\")?", (String) value)) { + returnValue = "b'" + + value.toString() + .replace("b", "") + .replace("\"", "") + .replace("::it", "") + + "'::\"bit\""; + } else { + throw new UnexpectedLiquibaseException("Unknown boolean value: " + value); + } + } else if (value instanceof Long) { + if (Long.valueOf(1).equals(value)) { + returnValue = this.getTrueBooleanValue(database); + } else { + returnValue = this.getFalseBooleanValue(database); + } + } else if (value instanceof Number) { + if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) { + returnValue = this.getTrueBooleanValue(database); + } else { + returnValue = this.getFalseBooleanValue(database); + } + } else if (value instanceof DatabaseFunction) { + return value.toString(); + } else if (value instanceof Boolean) { + if (((Boolean) value)) { + returnValue = this.getTrueBooleanValue(database); + } else { + returnValue = this.getFalseBooleanValue(database); + } + } else { + throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value"); + } + + return returnValue; + } + + protected boolean isNumericBoolean(Database database) { + if (database instanceof Firebird3Database) { + return false; + } + if (database instanceof DerbyDatabase) { + return !((DerbyDatabase) database).supportsBooleanDataType(); + } else if (database instanceof DB2Database) { + return !((DB2Database) database).supportsBooleanDataType(); + } + return (database instanceof Db2zDatabase) + || (database instanceof FirebirdDatabase) + || (database instanceof MSSQLDatabase) + || (database instanceof MySQLDatabase) + || (database instanceof OracleDatabase) + || (database instanceof SQLiteDatabase) + || (database instanceof SybaseASADatabase) + || (database instanceof SybaseDatabase) + || (database instanceof DmDatabase); // dhb52: DM Support + } + + /** + * The database-specific value to use for "false" "boolean" columns. + */ + public String getFalseBooleanValue(Database database) { + if (isNumericBoolean(database)) { + return "0"; + } + if (database instanceof InformixDatabase) { + return "'f'"; + } + return "FALSE"; + } + + /** + * The database-specific value to use for "true" "boolean" columns. + */ + public String getTrueBooleanValue(Database database) { + if (isNumericBoolean(database)) { + return "1"; + } + if (database instanceof InformixDatabase) { + return "'t'"; + } + return "TRUE"; + } + + @Override + public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() { + return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN; + } + +} diff --git a/sql/db2/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java b/sql/db2/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java new file mode 100644 index 000000000..33c52d551 --- /dev/null +++ b/sql/db2/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java @@ -0,0 +1,2068 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.flowable.common.engine.impl; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.Set; + +import javax.naming.InitialContext; +import javax.sql.DataSource; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.builder.xml.XMLConfigBuilder; +import org.apache.ibatis.builder.xml.XMLMapperBuilder; +import org.apache.ibatis.datasource.pooled.PooledDataSource; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; +import org.apache.ibatis.transaction.TransactionFactory; +import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import org.apache.ibatis.transaction.managed.ManagedTransactionFactory; +import org.apache.ibatis.type.ArrayTypeHandler; +import org.apache.ibatis.type.BigDecimalTypeHandler; +import org.apache.ibatis.type.BlobInputStreamTypeHandler; +import org.apache.ibatis.type.BlobTypeHandler; +import org.apache.ibatis.type.BooleanTypeHandler; +import org.apache.ibatis.type.ByteTypeHandler; +import org.apache.ibatis.type.ClobTypeHandler; +import org.apache.ibatis.type.DateOnlyTypeHandler; +import org.apache.ibatis.type.DateTypeHandler; +import org.apache.ibatis.type.DoubleTypeHandler; +import org.apache.ibatis.type.FloatTypeHandler; +import org.apache.ibatis.type.IntegerTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.LongTypeHandler; +import org.apache.ibatis.type.NClobTypeHandler; +import org.apache.ibatis.type.NStringTypeHandler; +import org.apache.ibatis.type.ShortTypeHandler; +import org.apache.ibatis.type.SqlxmlTypeHandler; +import org.apache.ibatis.type.StringTypeHandler; +import org.apache.ibatis.type.TimeOnlyTypeHandler; +import org.apache.ibatis.type.TypeHandlerRegistry; +import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; +import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher; +import org.flowable.common.engine.api.delegate.event.FlowableEventListener; +import org.flowable.common.engine.api.engine.EngineLifecycleListener; +import org.flowable.common.engine.impl.agenda.AgendaOperationRunner; +import org.flowable.common.engine.impl.cfg.CommandExecutorImpl; +import org.flowable.common.engine.impl.cfg.IdGenerator; +import org.flowable.common.engine.impl.cfg.TransactionContextFactory; +import org.flowable.common.engine.impl.cfg.standalone.StandaloneMybatisTransactionContextFactory; +import org.flowable.common.engine.impl.db.CommonDbSchemaManager; +import org.flowable.common.engine.impl.db.DbSqlSessionFactory; +import org.flowable.common.engine.impl.db.LogSqlExecutionTimePlugin; +import org.flowable.common.engine.impl.db.MybatisTypeAliasConfigurator; +import org.flowable.common.engine.impl.db.MybatisTypeHandlerConfigurator; +import org.flowable.common.engine.impl.db.SchemaManager; +import org.flowable.common.engine.impl.event.EventDispatchAction; +import org.flowable.common.engine.impl.event.FlowableEventDispatcherImpl; +import org.flowable.common.engine.impl.interceptor.Command; +import org.flowable.common.engine.impl.interceptor.CommandConfig; +import org.flowable.common.engine.impl.interceptor.CommandContextFactory; +import org.flowable.common.engine.impl.interceptor.CommandContextInterceptor; +import org.flowable.common.engine.impl.interceptor.CommandExecutor; +import org.flowable.common.engine.impl.interceptor.CommandInterceptor; +import org.flowable.common.engine.impl.interceptor.CrDbRetryInterceptor; +import org.flowable.common.engine.impl.interceptor.DefaultCommandInvoker; +import org.flowable.common.engine.impl.interceptor.LogInterceptor; +import org.flowable.common.engine.impl.interceptor.SessionFactory; +import org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor; +import org.flowable.common.engine.impl.lock.LockManager; +import org.flowable.common.engine.impl.lock.LockManagerImpl; +import org.flowable.common.engine.impl.logging.LoggingListener; +import org.flowable.common.engine.impl.logging.LoggingSession; +import org.flowable.common.engine.impl.logging.LoggingSessionFactory; +import org.flowable.common.engine.impl.persistence.GenericManagerFactory; +import org.flowable.common.engine.impl.persistence.StrongUuidGenerator; +import org.flowable.common.engine.impl.persistence.cache.EntityCache; +import org.flowable.common.engine.impl.persistence.cache.EntityCacheImpl; +import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManager; +import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManagerImpl; +import org.flowable.common.engine.impl.persistence.entity.Entity; +import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManager; +import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManagerImpl; +import org.flowable.common.engine.impl.persistence.entity.TableDataManager; +import org.flowable.common.engine.impl.persistence.entity.TableDataManagerImpl; +import org.flowable.common.engine.impl.persistence.entity.data.ByteArrayDataManager; +import org.flowable.common.engine.impl.persistence.entity.data.PropertyDataManager; +import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisByteArrayDataManager; +import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisPropertyDataManager; +import org.flowable.common.engine.impl.runtime.Clock; +import org.flowable.common.engine.impl.service.CommonEngineServiceImpl; +import org.flowable.common.engine.impl.util.DefaultClockImpl; +import org.flowable.common.engine.impl.util.IoUtil; +import org.flowable.common.engine.impl.util.ReflectUtil; +import org.flowable.eventregistry.api.EventRegistryEventConsumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +public abstract class AbstractEngineConfiguration { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + /** The tenant id indicating 'no tenant' */ + public static final String NO_TENANT_ID = ""; + + /** + * Checks the version of the DB schema against the library when the form engine is being created and throws an exception if the versions don't match. + */ + public static final String DB_SCHEMA_UPDATE_FALSE = "false"; + public static final String DB_SCHEMA_UPDATE_CREATE = "create"; + public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"; + + /** + * Creates the schema when the form engine is being created and drops the schema when the form engine is being closed. + */ + public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create"; + + /** + * Upon building of the process engine, a check is performed and an update of the schema is performed if it is necessary. + */ + public static final String DB_SCHEMA_UPDATE_TRUE = "true"; + + protected boolean forceCloseMybatisConnectionPool = true; + + protected String databaseType; + protected String jdbcDriver = "org.h2.Driver"; + protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/flowable"; + protected String jdbcUsername = "sa"; + protected String jdbcPassword = ""; + protected String dataSourceJndiName; + protected int jdbcMaxActiveConnections = 16; + protected int jdbcMaxIdleConnections = 8; + protected int jdbcMaxCheckoutTime; + protected int jdbcMaxWaitTime; + protected boolean jdbcPingEnabled; + protected String jdbcPingQuery; + protected int jdbcPingConnectionNotUsedFor; + protected int jdbcDefaultTransactionIsolationLevel; + protected DataSource dataSource; + protected SchemaManager commonSchemaManager; + protected SchemaManager schemaManager; + protected Command schemaManagementCmd; + + protected String databaseSchemaUpdate = DB_SCHEMA_UPDATE_FALSE; + + /** + * Whether to use a lock when performing the database schema create or update operations. + */ + protected boolean useLockForDatabaseSchemaUpdate = false; + + protected String xmlEncoding = "UTF-8"; + + // COMMAND EXECUTORS /////////////////////////////////////////////// + + protected CommandExecutor commandExecutor; + protected Collection defaultCommandInterceptors; + protected CommandConfig defaultCommandConfig; + protected CommandConfig schemaCommandConfig; + protected CommandContextFactory commandContextFactory; + protected CommandInterceptor commandInvoker; + + protected AgendaOperationRunner agendaOperationRunner = (commandContext, runnable) -> runnable.run(); + + protected List customPreCommandInterceptors; + protected List customPostCommandInterceptors; + protected List commandInterceptors; + + protected Map engineConfigurations = new HashMap<>(); + protected Map serviceConfigurations = new HashMap<>(); + + protected ClassLoader classLoader; + /** + * Either use Class.forName or ClassLoader.loadClass for class loading. See http://forums.activiti.org/content/reflectutilloadclass-and-custom- classloader + */ + protected boolean useClassForNameClassLoading = true; + + protected List engineLifecycleListeners; + + // Event Registry ////////////////////////////////////////////////// + protected Map eventRegistryEventConsumers = new HashMap<>(); + + // MYBATIS SQL SESSION FACTORY ///////////////////////////////////// + + protected boolean isDbHistoryUsed = true; + protected DbSqlSessionFactory dbSqlSessionFactory; + protected SqlSessionFactory sqlSessionFactory; + protected TransactionFactory transactionFactory; + protected TransactionContextFactory transactionContextFactory; + + /** + * If set to true, enables bulk insert (grouping sql inserts together). Default true. + * For some databases (eg DB2+z/OS) needs to be set to false. + */ + protected boolean isBulkInsertEnabled = true; + + /** + * Some databases have a limit of how many parameters one sql insert can have (eg SQL Server, 2000 params (!= insert statements) ). Tweak this parameter in case of exceptions indicating too much + * is being put into one bulk insert, or make it higher if your database can cope with it and there are inserts with a huge amount of data. + *

+ * By default: 100 (55 for mssql server as it has a hard limit of 2000 parameters in a statement) + */ + protected int maxNrOfStatementsInBulkInsert = 100; + + public int DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER = 55; // currently Execution has most params (35). 2000 / 35 = 57. + + protected String mybatisMappingFile; + protected Set> customMybatisMappers; + protected Set customMybatisXMLMappers; + protected List customMybatisInterceptors; + + protected Set dependentEngineMyBatisXmlMappers; + protected List dependentEngineMybatisTypeAliasConfigs; + protected List dependentEngineMybatisTypeHandlerConfigs; + + // SESSION FACTORIES /////////////////////////////////////////////// + protected List customSessionFactories; + protected Map, SessionFactory> sessionFactories; + + protected boolean enableEventDispatcher = true; + protected FlowableEventDispatcher eventDispatcher; + protected List eventListeners; + protected Map> typedEventListeners; + protected List additionalEventDispatchActions; + + protected LoggingListener loggingListener; + + protected boolean transactionsExternallyManaged; + + /** + * Flag that can be set to configure or not a relational database is used. This is useful for custom implementations that do not use relational databases at all. + * + * If true (default), the {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will be used to determine what needs to happen wrt the database schema. + * + * If false, no validation or schema creation will be done. That means that the database schema must have been created 'manually' before but the engine does not validate whether the schema is + * correct. The {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will not be used. + */ + protected boolean usingRelationalDatabase = true; + + /** + * Flag that can be set to configure whether or not a schema is used. This is useful for custom implementations that do not use relational databases at all. + * Setting {@link #usingRelationalDatabase} to true will automatically imply using a schema. + */ + protected boolean usingSchemaMgmt = true; + + /** + * Allows configuring a database table prefix which is used for all runtime operations of the process engine. For example, if you specify a prefix named 'PRE1.', Flowable will query for executions + * in a table named 'PRE1.ACT_RU_EXECUTION_'. + * + *

+ * NOTE: the prefix is not respected by automatic database schema management. If you use {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_CREATE_DROP} or + * {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_TRUE}, Flowable will create the database tables using the default names, regardless of the prefix configured here. + */ + protected String databaseTablePrefix = ""; + + /** + * Escape character for doing wildcard searches. + * + * This will be added at then end of queries that include for example a LIKE clause. For example: SELECT * FROM table WHERE column LIKE '%\%%' ESCAPE '\'; + */ + protected String databaseWildcardEscapeCharacter; + + /** + * database catalog to use + */ + protected String databaseCatalog = ""; + + /** + * In some situations you want to set the schema to use for table checks / generation if the database metadata doesn't return that correctly, see https://jira.codehaus.org/browse/ACT-1220, + * https://jira.codehaus.org/browse/ACT-1062 + */ + protected String databaseSchema; + + /** + * Set to true in case the defined databaseTablePrefix is a schema-name, instead of an actual table name prefix. This is relevant for checking if Flowable-tables exist, the databaseTablePrefix + * will not be used here - since the schema is taken into account already, adding a prefix for the table-check will result in wrong table-names. + */ + protected boolean tablePrefixIsSchema; + + /** + * Set to true if the latest version of a definition should be retrieved, ignoring a possible parent deployment id value + */ + protected boolean alwaysLookupLatestDefinitionVersion; + + /** + * Set to true if by default lookups should fallback to the default tenant (an empty string by default or a defined tenant value) + */ + protected boolean fallbackToDefaultTenant; + + /** + * Default tenant provider that is executed when looking up definitions, in case the global or local fallback to default tenant value is true + */ + protected DefaultTenantProvider defaultTenantProvider = (tenantId, scope, scopeKey) -> NO_TENANT_ID; + + /** + * Enables the MyBatis plugin that logs the execution time of sql statements. + */ + protected boolean enableLogSqlExecutionTime; + + protected Properties databaseTypeMappings = getDefaultDatabaseTypeMappings(); + + /** + * Duration between the checks when acquiring a lock. + */ + protected Duration lockPollRate = Duration.ofSeconds(10); + + /** + * Duration to wait for the DB Schema lock before giving up. + */ + protected Duration schemaLockWaitTime = Duration.ofMinutes(5); + + // DATA MANAGERS ////////////////////////////////////////////////////////////////// + + protected PropertyDataManager propertyDataManager; + protected ByteArrayDataManager byteArrayDataManager; + protected TableDataManager tableDataManager; + + // ENTITY MANAGERS //////////////////////////////////////////////////////////////// + + protected PropertyEntityManager propertyEntityManager; + protected ByteArrayEntityManager byteArrayEntityManager; + + protected List customPreDeployers; + protected List customPostDeployers; + protected List deployers; + + // CONFIGURATORS //////////////////////////////////////////////////////////// + + protected boolean enableConfiguratorServiceLoader = true; // Enabled by default. In certain environments this should be set to false (eg osgi) + protected List configurators; // The injected configurators + protected List allConfigurators; // Including auto-discovered configurators + protected EngineConfigurator idmEngineConfigurator; + protected EngineConfigurator eventRegistryConfigurator; + + public static final String PRODUCT_NAME_POSTGRES = "PostgreSQL"; + public static final String PRODUCT_NAME_CRDB = "CockroachDB"; + + public static final String DATABASE_TYPE_H2 = "h2"; + public static final String DATABASE_TYPE_HSQL = "hsql"; + public static final String DATABASE_TYPE_MYSQL = "mysql"; + public static final String DATABASE_TYPE_ORACLE = "oracle"; + public static final String DATABASE_TYPE_POSTGRES = "postgres"; + public static final String DATABASE_TYPE_MSSQL = "mssql"; + public static final String DATABASE_TYPE_DB2 = "db2"; + public static final String DATABASE_TYPE_COCKROACHDB = "cockroachdb"; + + public static Properties getDefaultDatabaseTypeMappings() { + Properties databaseTypeMappings = new Properties(); + databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2); + databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL); + databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL); + databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL); + databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE); + databaseTypeMappings.setProperty(PRODUCT_NAME_POSTGRES, DATABASE_TYPE_POSTGRES); + databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL); + databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty(PRODUCT_NAME_CRDB, DATABASE_TYPE_COCKROACHDB); + databaseTypeMappings.setProperty("DM DBMS", DATABASE_TYPE_ORACLE); // dhb52: DM support + return databaseTypeMappings; + } + + protected Map beans; + + protected IdGenerator idGenerator; + protected boolean usePrefixId; + + protected Clock clock; + protected ObjectMapper objectMapper; + + // Variables + + public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000; + public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000; + + /** + * Define a max length for storing String variable types in the database. Mainly used for the Oracle NVARCHAR2 limit of 2000 characters + */ + protected int maxLengthStringVariableType = -1; + + protected void initEngineConfigurations() { + addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this); + } + + // DataSource + // /////////////////////////////////////////////////////////////// + + protected void initDataSource() { + if (dataSource == null) { + if (dataSourceJndiName != null) { + try { + dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName); + } catch (Exception e) { + throw new FlowableException("couldn't lookup datasource from " + dataSourceJndiName + ": " + e.getMessage(), e); + } + + } else if (jdbcUrl != null) { + if ((jdbcDriver == null) || (jdbcUsername == null)) { + throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration"); + } + + logger.debug("initializing datasource to db: {}", jdbcUrl); + + if (logger.isInfoEnabled()) { + logger.info("Configuring Datasource with following properties (omitted password for security)"); + logger.info("datasource driver : {}", jdbcDriver); + logger.info("datasource url : {}", jdbcUrl); + logger.info("datasource user name : {}", jdbcUsername); + } + + PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword); + + if (jdbcMaxActiveConnections > 0) { + pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections); + } + if (jdbcMaxIdleConnections > 0) { + pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections); + } + if (jdbcMaxCheckoutTime > 0) { + pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime); + } + if (jdbcMaxWaitTime > 0) { + pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime); + } + if (jdbcPingEnabled) { + pooledDataSource.setPoolPingEnabled(true); + if (jdbcPingQuery != null) { + pooledDataSource.setPoolPingQuery(jdbcPingQuery); + } + pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor); + } + if (jdbcDefaultTransactionIsolationLevel > 0) { + pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel); + } + dataSource = pooledDataSource; + } + } + + if (databaseType == null) { + initDatabaseType(); + } + } + + public void initDatabaseType() { + Connection connection = null; + try { + connection = dataSource.getConnection(); + DatabaseMetaData databaseMetaData = connection.getMetaData(); + String databaseProductName = databaseMetaData.getDatabaseProductName(); + logger.debug("database product name: '{}'", databaseProductName); + + // CRDB does not expose the version through the jdbc driver, so we need to fetch it through version(). + if (PRODUCT_NAME_POSTGRES.equalsIgnoreCase(databaseProductName)) { + try (PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;"); + ResultSet resultSet = preparedStatement.executeQuery()) { + String version = null; + if (resultSet.next()) { + version = resultSet.getString("version"); + } + + if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith(PRODUCT_NAME_CRDB.toLowerCase())) { + databaseProductName = PRODUCT_NAME_CRDB; + logger.info("CockroachDB version '{}' detected", version); + } + } + } + + databaseType = databaseTypeMappings.getProperty(databaseProductName); + if (databaseType == null) { + throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'"); + } + logger.debug("using database type: {}", databaseType); + + } catch (SQLException e) { + throw new RuntimeException("Exception while initializing Database connection", e); + } finally { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + logger.error("Exception while closing the Database connection", e); + } + } + + // Special care for MSSQL, as it has a hard limit of 2000 params per statement (incl bulk statement). + // Especially with executions, with 100 as default, this limit is passed. + if (DATABASE_TYPE_MSSQL.equals(databaseType)) { + maxNrOfStatementsInBulkInsert = DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER; + } + } + + public void initSchemaManager() { + if (this.commonSchemaManager == null) { + this.commonSchemaManager = new CommonDbSchemaManager(); + } + } + + // session factories //////////////////////////////////////////////////////// + + public void addSessionFactory(SessionFactory sessionFactory) { + sessionFactories.put(sessionFactory.getSessionType(), sessionFactory); + } + + public void initCommandContextFactory() { + if (commandContextFactory == null) { + commandContextFactory = new CommandContextFactory(); + } + } + + public void initTransactionContextFactory() { + if (transactionContextFactory == null) { + transactionContextFactory = new StandaloneMybatisTransactionContextFactory(); + } + } + + public void initCommandExecutors() { + initDefaultCommandConfig(); + initSchemaCommandConfig(); + initCommandInvoker(); + initCommandInterceptors(); + initCommandExecutor(); + } + + + public void initDefaultCommandConfig() { + if (defaultCommandConfig == null) { + defaultCommandConfig = new CommandConfig(); + } + } + + public void initSchemaCommandConfig() { + if (schemaCommandConfig == null) { + schemaCommandConfig = new CommandConfig(); + } + } + + public void initCommandInvoker() { + if (commandInvoker == null) { + commandInvoker = new DefaultCommandInvoker(); + } + } + + public void initCommandInterceptors() { + if (commandInterceptors == null) { + commandInterceptors = new ArrayList<>(); + if (customPreCommandInterceptors != null) { + commandInterceptors.addAll(customPreCommandInterceptors); + } + commandInterceptors.addAll(getDefaultCommandInterceptors()); + if (customPostCommandInterceptors != null) { + commandInterceptors.addAll(customPostCommandInterceptors); + } + commandInterceptors.add(commandInvoker); + } + } + + public Collection getDefaultCommandInterceptors() { + if (defaultCommandInterceptors == null) { + List interceptors = new ArrayList<>(); + interceptors.add(new LogInterceptor()); + + if (DATABASE_TYPE_COCKROACHDB.equals(databaseType)) { + interceptors.add(new CrDbRetryInterceptor()); + } + + CommandInterceptor transactionInterceptor = createTransactionInterceptor(); + if (transactionInterceptor != null) { + interceptors.add(transactionInterceptor); + } + + if (commandContextFactory != null) { + String engineCfgKey = getEngineCfgKey(); + CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory, + classLoader, useClassForNameClassLoading, clock, objectMapper); + engineConfigurations.put(engineCfgKey, this); + commandContextInterceptor.setEngineCfgKey(engineCfgKey); + commandContextInterceptor.setEngineConfigurations(engineConfigurations); + interceptors.add(commandContextInterceptor); + } + + if (transactionContextFactory != null) { + interceptors.add(new TransactionContextInterceptor(transactionContextFactory)); + } + + List additionalCommandInterceptors = getAdditionalDefaultCommandInterceptors(); + if (additionalCommandInterceptors != null) { + interceptors.addAll(additionalCommandInterceptors); + } + + defaultCommandInterceptors = interceptors; + } + return defaultCommandInterceptors; + } + + public abstract String getEngineCfgKey(); + + public abstract String getEngineScopeType(); + + public List getAdditionalDefaultCommandInterceptors() { + return null; + } + + public void initCommandExecutor() { + if (commandExecutor == null) { + CommandInterceptor first = initInterceptorChain(commandInterceptors); + commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); + } + } + + public CommandInterceptor initInterceptorChain(List chain) { + if (chain == null || chain.isEmpty()) { + throw new FlowableException("invalid command interceptor chain configuration: " + chain); + } + for (int i = 0; i < chain.size() - 1; i++) { + chain.get(i).setNext(chain.get(i + 1)); + } + return chain.get(0); + } + + public abstract CommandInterceptor createTransactionInterceptor(); + + + public void initBeans() { + if (beans == null) { + beans = new HashMap<>(); + } + } + + // id generator + // ///////////////////////////////////////////////////////////// + + public void initIdGenerator() { + if (idGenerator == null) { + idGenerator = new StrongUuidGenerator(); + } + } + + public void initObjectMapper() { + if (objectMapper == null) { + objectMapper = new ObjectMapper(); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + } + } + + public void initClock() { + if (clock == null) { + clock = new DefaultClockImpl(); + } + } + + // Data managers /////////////////////////////////////////////////////////// + + public void initDataManagers() { + if (propertyDataManager == null) { + propertyDataManager = new MybatisPropertyDataManager(idGenerator); + } + + if (byteArrayDataManager == null) { + byteArrayDataManager = new MybatisByteArrayDataManager(idGenerator); + } + } + + // Entity managers ////////////////////////////////////////////////////////// + + public void initEntityManagers() { + if (propertyEntityManager == null) { + propertyEntityManager = new PropertyEntityManagerImpl(this, propertyDataManager); + } + + if (byteArrayEntityManager == null) { + byteArrayEntityManager = new ByteArrayEntityManagerImpl(byteArrayDataManager, getEngineCfgKey(), this::getEventDispatcher); + } + + if (tableDataManager == null) { + tableDataManager = new TableDataManagerImpl(this); + } + } + + // services + // ///////////////////////////////////////////////////////////////// + + protected void initService(Object service) { + if (service instanceof CommonEngineServiceImpl) { + ((CommonEngineServiceImpl) service).setCommandExecutor(commandExecutor); + } + } + + // myBatis SqlSessionFactory + // //////////////////////////////////////////////// + + public void initSessionFactories() { + if (sessionFactories == null) { + sessionFactories = new HashMap<>(); + + if (usingRelationalDatabase) { + initDbSqlSessionFactory(); + } + + addSessionFactory(new GenericManagerFactory(EntityCache.class, EntityCacheImpl.class)); + + if (isLoggingSessionEnabled()) { + if (!sessionFactories.containsKey(LoggingSession.class)) { + LoggingSessionFactory loggingSessionFactory = new LoggingSessionFactory(); + loggingSessionFactory.setLoggingListener(loggingListener); + loggingSessionFactory.setObjectMapper(objectMapper); + sessionFactories.put(LoggingSession.class, loggingSessionFactory); + } + } + + commandContextFactory.setSessionFactories(sessionFactories); + + } else { + if (usingRelationalDatabase) { + initDbSqlSessionFactoryEntitySettings(); + } + } + + if (customSessionFactories != null) { + for (SessionFactory sessionFactory : customSessionFactories) { + addSessionFactory(sessionFactory); + } + } + } + + public void initDbSqlSessionFactory() { + if (dbSqlSessionFactory == null) { + dbSqlSessionFactory = createDbSqlSessionFactory(); + } + dbSqlSessionFactory.setDatabaseType(databaseType); + dbSqlSessionFactory.setSqlSessionFactory(sqlSessionFactory); + dbSqlSessionFactory.setDbHistoryUsed(isDbHistoryUsed); + dbSqlSessionFactory.setDatabaseTablePrefix(databaseTablePrefix); + dbSqlSessionFactory.setTablePrefixIsSchema(tablePrefixIsSchema); + dbSqlSessionFactory.setDatabaseCatalog(databaseCatalog); + dbSqlSessionFactory.setDatabaseSchema(databaseSchema); + dbSqlSessionFactory.setMaxNrOfStatementsInBulkInsert(maxNrOfStatementsInBulkInsert); + + initDbSqlSessionFactoryEntitySettings(); + + addSessionFactory(dbSqlSessionFactory); + } + + public DbSqlSessionFactory createDbSqlSessionFactory() { + return new DbSqlSessionFactory(usePrefixId); + } + + protected abstract void initDbSqlSessionFactoryEntitySettings(); + + protected void defaultInitDbSqlSessionFactoryEntitySettings(List> insertOrder, List> deleteOrder) { + if (insertOrder != null) { + for (Class clazz : insertOrder) { + dbSqlSessionFactory.getInsertionOrder().add(clazz); + + if (isBulkInsertEnabled) { + dbSqlSessionFactory.getBulkInserteableEntityClasses().add(clazz); + } + } + } + + if (deleteOrder != null) { + for (Class clazz : deleteOrder) { + dbSqlSessionFactory.getDeletionOrder().add(clazz); + } + } + } + + public void initTransactionFactory() { + if (transactionFactory == null) { + if (transactionsExternallyManaged) { + transactionFactory = new ManagedTransactionFactory(); + Properties properties = new Properties(); + properties.put("closeConnection", "false"); + this.transactionFactory.setProperties(properties); + } else { + transactionFactory = new JdbcTransactionFactory(); + } + } + } + + public void initSqlSessionFactory() { + if (sqlSessionFactory == null) { + InputStream inputStream = null; + try { + inputStream = getMyBatisXmlConfigurationStream(); + + Environment environment = new Environment("default", transactionFactory, dataSource); + Reader reader = new InputStreamReader(inputStream); + Properties properties = new Properties(); + properties.put("prefix", databaseTablePrefix); + + String wildcardEscapeClause = ""; + if ((databaseWildcardEscapeCharacter != null) && (databaseWildcardEscapeCharacter.length() != 0)) { + wildcardEscapeClause = " escape '" + databaseWildcardEscapeCharacter + "'"; + } + properties.put("wildcardEscapeClause", wildcardEscapeClause); + + // set default properties + properties.put("limitBefore", ""); + properties.put("limitAfter", ""); + properties.put("limitBetween", ""); + properties.put("limitBeforeNativeQuery", ""); + properties.put("limitAfterNativeQuery", ""); + properties.put("blobType", "BLOB"); + properties.put("boolValue", "TRUE"); + + if (databaseType != null) { + properties.load(getResourceAsStream(pathToEngineDbProperties())); + } + + Configuration configuration = initMybatisConfiguration(environment, reader, properties); + sqlSessionFactory = new DefaultSqlSessionFactory(configuration); + + } catch (Exception e) { + throw new FlowableException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e); + } finally { + IoUtil.closeSilently(inputStream); + } + } else { + // This is needed when the SQL Session Factory is created by another engine. + // When custom XML Mappers are registered with this engine they need to be loaded in the configuration as well + applyCustomMybatisCustomizations(sqlSessionFactory.getConfiguration()); + } + } + + public String pathToEngineDbProperties() { + return "org/flowable/common/db/properties/" + databaseType + ".properties"; + } + + public Configuration initMybatisConfiguration(Environment environment, Reader reader, Properties properties) { + XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties); + Configuration configuration = parser.getConfiguration(); + + if (databaseType != null) { + configuration.setDatabaseId(databaseType); + } + + configuration.setEnvironment(environment); + + initMybatisTypeHandlers(configuration); + initCustomMybatisInterceptors(configuration); + if (isEnableLogSqlExecutionTime()) { + initMyBatisLogSqlExecutionTimePlugin(configuration); + } + + configuration = parseMybatisConfiguration(parser); + return configuration; + } + + public void initCustomMybatisMappers(Configuration configuration) { + if (getCustomMybatisMappers() != null) { + for (Class clazz : getCustomMybatisMappers()) { + if (!configuration.hasMapper(clazz)) { + configuration.addMapper(clazz); + } + } + } + } + + public void initMybatisTypeHandlers(Configuration configuration) { + // When mapping into Map there is currently a problem with MyBatis. + // It will return objects which are driver specific. + // Therefore we are registering the mappings between Object.class and the specific jdbc type here. + // see https://github.com/mybatis/mybatis-3/issues/2216 for more info + TypeHandlerRegistry handlerRegistry = configuration.getTypeHandlerRegistry(); + + handlerRegistry.register(Object.class, JdbcType.BOOLEAN, new BooleanTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.BIT, new BooleanTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.TINYINT, new ByteTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.SMALLINT, new ShortTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.INTEGER, new IntegerTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.FLOAT, new FloatTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.DOUBLE, new DoubleTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.CHAR, new StringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.CLOB, new ClobTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.VARCHAR, new StringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.LONGVARCHAR, new StringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NVARCHAR, new NStringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NCHAR, new NStringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NCLOB, new NClobTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.BIGINT, new LongTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.REAL, new BigDecimalTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.DECIMAL, new BigDecimalTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NUMERIC, new BigDecimalTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.BLOB, new BlobInputStreamTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.LONGVARBINARY, new BlobTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.DATE, new DateOnlyTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.TIME, new TimeOnlyTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.TIMESTAMP, new DateTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.SQLXML, new SqlxmlTypeHandler()); + } + + public void initCustomMybatisInterceptors(Configuration configuration) { + if (customMybatisInterceptors!=null){ + for (Interceptor interceptor :customMybatisInterceptors){ + configuration.addInterceptor(interceptor); + } + } + } + + public void initMyBatisLogSqlExecutionTimePlugin(Configuration configuration) { + configuration.addInterceptor(new LogSqlExecutionTimePlugin()); + } + + public Configuration parseMybatisConfiguration(XMLConfigBuilder parser) { + Configuration configuration = parser.parse(); + + applyCustomMybatisCustomizations(configuration); + return configuration; + } + + protected void applyCustomMybatisCustomizations(Configuration configuration) { + initCustomMybatisMappers(configuration); + + if (dependentEngineMybatisTypeAliasConfigs != null) { + for (MybatisTypeAliasConfigurator typeAliasConfig : dependentEngineMybatisTypeAliasConfigs) { + typeAliasConfig.configure(configuration.getTypeAliasRegistry()); + } + } + if (dependentEngineMybatisTypeHandlerConfigs != null) { + for (MybatisTypeHandlerConfigurator typeHandlerConfig : dependentEngineMybatisTypeHandlerConfigs) { + typeHandlerConfig.configure(configuration.getTypeHandlerRegistry()); + } + } + + parseDependentEngineMybatisXMLMappers(configuration); + parseCustomMybatisXMLMappers(configuration); + } + + public void parseCustomMybatisXMLMappers(Configuration configuration) { + if (getCustomMybatisXMLMappers() != null) { + for (String resource : getCustomMybatisXMLMappers()) { + parseMybatisXmlMapping(configuration, resource); + } + } + } + + public void parseDependentEngineMybatisXMLMappers(Configuration configuration) { + if (getDependentEngineMyBatisXmlMappers() != null) { + for (String resource : getDependentEngineMyBatisXmlMappers()) { + parseMybatisXmlMapping(configuration, resource); + } + } + } + + protected void parseMybatisXmlMapping(Configuration configuration, String resource) { + // see XMLConfigBuilder.mapperElement() + XMLMapperBuilder mapperParser = new XMLMapperBuilder(getResourceAsStream(resource), configuration, resource, configuration.getSqlFragments()); + mapperParser.parse(); + } + + protected InputStream getResourceAsStream(String resource) { + ClassLoader classLoader = getClassLoader(); + if (classLoader != null) { + return getClassLoader().getResourceAsStream(resource); + } else { + return this.getClass().getClassLoader().getResourceAsStream(resource); + } + } + + public void setMybatisMappingFile(String file) { + this.mybatisMappingFile = file; + } + + public String getMybatisMappingFile() { + return mybatisMappingFile; + } + + public abstract InputStream getMyBatisXmlConfigurationStream(); + + public void initConfigurators() { + + allConfigurators = new ArrayList<>(); + allConfigurators.addAll(getEngineSpecificEngineConfigurators()); + + // Configurators that are explicitly added to the config + if (configurators != null) { + allConfigurators.addAll(configurators); + } + + // Auto discovery through ServiceLoader + if (enableConfiguratorServiceLoader) { + ClassLoader classLoader = getClassLoader(); + if (classLoader == null) { + classLoader = ReflectUtil.getClassLoader(); + } + + ServiceLoader configuratorServiceLoader = ServiceLoader.load(EngineConfigurator.class, classLoader); + int nrOfServiceLoadedConfigurators = 0; + for (EngineConfigurator configurator : configuratorServiceLoader) { + allConfigurators.add(configurator); + nrOfServiceLoadedConfigurators++; + } + + if (nrOfServiceLoadedConfigurators > 0) { + logger.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators, nrOfServiceLoadedConfigurators > 1 ? "s" : ""); + } + + if (!allConfigurators.isEmpty()) { + + // Order them according to the priorities (useful for dependent + // configurator) + allConfigurators.sort(new Comparator() { + + @Override + public int compare(EngineConfigurator configurator1, EngineConfigurator configurator2) { + int priority1 = configurator1.getPriority(); + int priority2 = configurator2.getPriority(); + + if (priority1 < priority2) { + return -1; + } else if (priority1 > priority2) { + return 1; + } + return 0; + } + }); + + // Execute the configurators + logger.info("Found {} Engine Configurators in total:", allConfigurators.size()); + for (EngineConfigurator configurator : allConfigurators) { + logger.info("{} (priority:{})", configurator.getClass(), configurator.getPriority()); + } + + } + + } + } + + public void close() { + if (forceCloseMybatisConnectionPool && dataSource instanceof PooledDataSource) { + /* + * When the datasource is created by a Flowable engine (i.e. it's an instance of PooledDataSource), + * the connection pool needs to be closed when closing the engine. + * Note that calling forceCloseAll() multiple times (as is the case when running with multiple engine) is ok. + */ + ((PooledDataSource) dataSource).forceCloseAll(); + } + } + + protected List getEngineSpecificEngineConfigurators() { + // meant to be overridden if needed + return Collections.emptyList(); + } + + public void configuratorsBeforeInit() { + for (EngineConfigurator configurator : allConfigurators) { + logger.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); + configurator.beforeInit(this); + } + } + + public void configuratorsAfterInit() { + for (EngineConfigurator configurator : allConfigurators) { + logger.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); + configurator.configure(this); + } + } + + public LockManager getLockManager(String lockName) { + return new LockManagerImpl(commandExecutor, lockName, getLockPollRate(), getEngineCfgKey()); + } + + // getters and setters + // ////////////////////////////////////////////////////// + + public abstract String getEngineName(); + + public ClassLoader getClassLoader() { + return classLoader; + } + + public AbstractEngineConfiguration setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + return this; + } + + public boolean isUseClassForNameClassLoading() { + return useClassForNameClassLoading; + } + + public AbstractEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) { + this.useClassForNameClassLoading = useClassForNameClassLoading; + return this; + } + + public void addEngineLifecycleListener(EngineLifecycleListener engineLifecycleListener) { + if (this.engineLifecycleListeners == null) { + this.engineLifecycleListeners = new ArrayList<>(); + } + this.engineLifecycleListeners.add(engineLifecycleListener); + } + + public List getEngineLifecycleListeners() { + return engineLifecycleListeners; + } + + public AbstractEngineConfiguration setEngineLifecycleListeners(List engineLifecycleListeners) { + this.engineLifecycleListeners = engineLifecycleListeners; + return this; + } + + public String getDatabaseType() { + return databaseType; + } + + public AbstractEngineConfiguration setDatabaseType(String databaseType) { + this.databaseType = databaseType; + return this; + } + + public DataSource getDataSource() { + return dataSource; + } + + public AbstractEngineConfiguration setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + return this; + } + + public SchemaManager getSchemaManager() { + return schemaManager; + } + + public AbstractEngineConfiguration setSchemaManager(SchemaManager schemaManager) { + this.schemaManager = schemaManager; + return this; + } + + public SchemaManager getCommonSchemaManager() { + return commonSchemaManager; + } + + public AbstractEngineConfiguration setCommonSchemaManager(SchemaManager commonSchemaManager) { + this.commonSchemaManager = commonSchemaManager; + return this; + } + + public Command getSchemaManagementCmd() { + return schemaManagementCmd; + } + + public AbstractEngineConfiguration setSchemaManagementCmd(Command schemaManagementCmd) { + this.schemaManagementCmd = schemaManagementCmd; + return this; + } + + public String getJdbcDriver() { + return jdbcDriver; + } + + public AbstractEngineConfiguration setJdbcDriver(String jdbcDriver) { + this.jdbcDriver = jdbcDriver; + return this; + } + + public String getJdbcUrl() { + return jdbcUrl; + } + + public AbstractEngineConfiguration setJdbcUrl(String jdbcUrl) { + this.jdbcUrl = jdbcUrl; + return this; + } + + public String getJdbcUsername() { + return jdbcUsername; + } + + public AbstractEngineConfiguration setJdbcUsername(String jdbcUsername) { + this.jdbcUsername = jdbcUsername; + return this; + } + + public String getJdbcPassword() { + return jdbcPassword; + } + + public AbstractEngineConfiguration setJdbcPassword(String jdbcPassword) { + this.jdbcPassword = jdbcPassword; + return this; + } + + public int getJdbcMaxActiveConnections() { + return jdbcMaxActiveConnections; + } + + public AbstractEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) { + this.jdbcMaxActiveConnections = jdbcMaxActiveConnections; + return this; + } + + public int getJdbcMaxIdleConnections() { + return jdbcMaxIdleConnections; + } + + public AbstractEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) { + this.jdbcMaxIdleConnections = jdbcMaxIdleConnections; + return this; + } + + public int getJdbcMaxCheckoutTime() { + return jdbcMaxCheckoutTime; + } + + public AbstractEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) { + this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime; + return this; + } + + public int getJdbcMaxWaitTime() { + return jdbcMaxWaitTime; + } + + public AbstractEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) { + this.jdbcMaxWaitTime = jdbcMaxWaitTime; + return this; + } + + public boolean isJdbcPingEnabled() { + return jdbcPingEnabled; + } + + public AbstractEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) { + this.jdbcPingEnabled = jdbcPingEnabled; + return this; + } + + public int getJdbcPingConnectionNotUsedFor() { + return jdbcPingConnectionNotUsedFor; + } + + public AbstractEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingConnectionNotUsedFor) { + this.jdbcPingConnectionNotUsedFor = jdbcPingConnectionNotUsedFor; + return this; + } + + public int getJdbcDefaultTransactionIsolationLevel() { + return jdbcDefaultTransactionIsolationLevel; + } + + public AbstractEngineConfiguration setJdbcDefaultTransactionIsolationLevel(int jdbcDefaultTransactionIsolationLevel) { + this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel; + return this; + } + + public String getJdbcPingQuery() { + return jdbcPingQuery; + } + + public AbstractEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) { + this.jdbcPingQuery = jdbcPingQuery; + return this; + } + + public String getDataSourceJndiName() { + return dataSourceJndiName; + } + + public AbstractEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) { + this.dataSourceJndiName = dataSourceJndiName; + return this; + } + + public CommandConfig getSchemaCommandConfig() { + return schemaCommandConfig; + } + + public AbstractEngineConfiguration setSchemaCommandConfig(CommandConfig schemaCommandConfig) { + this.schemaCommandConfig = schemaCommandConfig; + return this; + } + + public boolean isTransactionsExternallyManaged() { + return transactionsExternallyManaged; + } + + public AbstractEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) { + this.transactionsExternallyManaged = transactionsExternallyManaged; + return this; + } + + public Map getBeans() { + return beans; + } + + public AbstractEngineConfiguration setBeans(Map beans) { + this.beans = beans; + return this; + } + + public IdGenerator getIdGenerator() { + return idGenerator; + } + + public AbstractEngineConfiguration setIdGenerator(IdGenerator idGenerator) { + this.idGenerator = idGenerator; + return this; + } + + public boolean isUsePrefixId() { + return usePrefixId; + } + + public AbstractEngineConfiguration setUsePrefixId(boolean usePrefixId) { + this.usePrefixId = usePrefixId; + return this; + } + + public String getXmlEncoding() { + return xmlEncoding; + } + + public AbstractEngineConfiguration setXmlEncoding(String xmlEncoding) { + this.xmlEncoding = xmlEncoding; + return this; + } + + public CommandConfig getDefaultCommandConfig() { + return defaultCommandConfig; + } + + public AbstractEngineConfiguration setDefaultCommandConfig(CommandConfig defaultCommandConfig) { + this.defaultCommandConfig = defaultCommandConfig; + return this; + } + + public CommandExecutor getCommandExecutor() { + return commandExecutor; + } + + public AbstractEngineConfiguration setCommandExecutor(CommandExecutor commandExecutor) { + this.commandExecutor = commandExecutor; + return this; + } + + public CommandContextFactory getCommandContextFactory() { + return commandContextFactory; + } + + public AbstractEngineConfiguration setCommandContextFactory(CommandContextFactory commandContextFactory) { + this.commandContextFactory = commandContextFactory; + return this; + } + + public CommandInterceptor getCommandInvoker() { + return commandInvoker; + } + + public AbstractEngineConfiguration setCommandInvoker(CommandInterceptor commandInvoker) { + this.commandInvoker = commandInvoker; + return this; + } + + public AgendaOperationRunner getAgendaOperationRunner() { + return agendaOperationRunner; + } + + public AbstractEngineConfiguration setAgendaOperationRunner(AgendaOperationRunner agendaOperationRunner) { + this.agendaOperationRunner = agendaOperationRunner; + return this; + } + + public List getCustomPreCommandInterceptors() { + return customPreCommandInterceptors; + } + + public AbstractEngineConfiguration setCustomPreCommandInterceptors(List customPreCommandInterceptors) { + this.customPreCommandInterceptors = customPreCommandInterceptors; + return this; + } + + public List getCustomPostCommandInterceptors() { + return customPostCommandInterceptors; + } + + public AbstractEngineConfiguration setCustomPostCommandInterceptors(List customPostCommandInterceptors) { + this.customPostCommandInterceptors = customPostCommandInterceptors; + return this; + } + + public List getCommandInterceptors() { + return commandInterceptors; + } + + public AbstractEngineConfiguration setCommandInterceptors(List commandInterceptors) { + this.commandInterceptors = commandInterceptors; + return this; + } + + public Map getEngineConfigurations() { + return engineConfigurations; + } + + public AbstractEngineConfiguration setEngineConfigurations(Map engineConfigurations) { + this.engineConfigurations = engineConfigurations; + return this; + } + + public void addEngineConfiguration(String key, String scopeType, AbstractEngineConfiguration engineConfiguration) { + if (engineConfigurations == null) { + engineConfigurations = new HashMap<>(); + } + engineConfigurations.put(key, engineConfiguration); + engineConfigurations.put(scopeType, engineConfiguration); + } + + public Map getServiceConfigurations() { + return serviceConfigurations; + } + + public AbstractEngineConfiguration setServiceConfigurations(Map serviceConfigurations) { + this.serviceConfigurations = serviceConfigurations; + return this; + } + + public void addServiceConfiguration(String key, AbstractServiceConfiguration serviceConfiguration) { + if (serviceConfigurations == null) { + serviceConfigurations = new HashMap<>(); + } + serviceConfigurations.put(key, serviceConfiguration); + } + + public Map getEventRegistryEventConsumers() { + return eventRegistryEventConsumers; + } + + public AbstractEngineConfiguration setEventRegistryEventConsumers(Map eventRegistryEventConsumers) { + this.eventRegistryEventConsumers = eventRegistryEventConsumers; + return this; + } + + public void addEventRegistryEventConsumer(String key, EventRegistryEventConsumer eventRegistryEventConsumer) { + if (eventRegistryEventConsumers == null) { + eventRegistryEventConsumers = new HashMap<>(); + } + eventRegistryEventConsumers.put(key, eventRegistryEventConsumer); + } + + public AbstractEngineConfiguration setDefaultCommandInterceptors(Collection defaultCommandInterceptors) { + this.defaultCommandInterceptors = defaultCommandInterceptors; + return this; + } + + public SqlSessionFactory getSqlSessionFactory() { + return sqlSessionFactory; + } + + public AbstractEngineConfiguration setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { + this.sqlSessionFactory = sqlSessionFactory; + return this; + } + + public boolean isDbHistoryUsed() { + return isDbHistoryUsed; + } + + public AbstractEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) { + this.isDbHistoryUsed = isDbHistoryUsed; + return this; + } + + public DbSqlSessionFactory getDbSqlSessionFactory() { + return dbSqlSessionFactory; + } + + public AbstractEngineConfiguration setDbSqlSessionFactory(DbSqlSessionFactory dbSqlSessionFactory) { + this.dbSqlSessionFactory = dbSqlSessionFactory; + return this; + } + + public TransactionFactory getTransactionFactory() { + return transactionFactory; + } + + public AbstractEngineConfiguration setTransactionFactory(TransactionFactory transactionFactory) { + this.transactionFactory = transactionFactory; + return this; + } + + public TransactionContextFactory getTransactionContextFactory() { + return transactionContextFactory; + } + + public AbstractEngineConfiguration setTransactionContextFactory(TransactionContextFactory transactionContextFactory) { + this.transactionContextFactory = transactionContextFactory; + return this; + } + + public int getMaxNrOfStatementsInBulkInsert() { + return maxNrOfStatementsInBulkInsert; + } + + public AbstractEngineConfiguration setMaxNrOfStatementsInBulkInsert(int maxNrOfStatementsInBulkInsert) { + this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert; + return this; + } + + public boolean isBulkInsertEnabled() { + return isBulkInsertEnabled; + } + + public AbstractEngineConfiguration setBulkInsertEnabled(boolean isBulkInsertEnabled) { + this.isBulkInsertEnabled = isBulkInsertEnabled; + return this; + } + + public Set> getCustomMybatisMappers() { + return customMybatisMappers; + } + + public AbstractEngineConfiguration setCustomMybatisMappers(Set> customMybatisMappers) { + this.customMybatisMappers = customMybatisMappers; + return this; + } + + public Set getCustomMybatisXMLMappers() { + return customMybatisXMLMappers; + } + + public AbstractEngineConfiguration setCustomMybatisXMLMappers(Set customMybatisXMLMappers) { + this.customMybatisXMLMappers = customMybatisXMLMappers; + return this; + } + + public Set getDependentEngineMyBatisXmlMappers() { + return dependentEngineMyBatisXmlMappers; + } + + public AbstractEngineConfiguration setCustomMybatisInterceptors(List customMybatisInterceptors) { + this.customMybatisInterceptors = customMybatisInterceptors; + return this; + } + + public List getCustomMybatisInterceptors() { + return customMybatisInterceptors; + } + + public AbstractEngineConfiguration setDependentEngineMyBatisXmlMappers(Set dependentEngineMyBatisXmlMappers) { + this.dependentEngineMyBatisXmlMappers = dependentEngineMyBatisXmlMappers; + return this; + } + + public List getDependentEngineMybatisTypeAliasConfigs() { + return dependentEngineMybatisTypeAliasConfigs; + } + + public AbstractEngineConfiguration setDependentEngineMybatisTypeAliasConfigs(List dependentEngineMybatisTypeAliasConfigs) { + this.dependentEngineMybatisTypeAliasConfigs = dependentEngineMybatisTypeAliasConfigs; + return this; + } + + public List getDependentEngineMybatisTypeHandlerConfigs() { + return dependentEngineMybatisTypeHandlerConfigs; + } + + public AbstractEngineConfiguration setDependentEngineMybatisTypeHandlerConfigs(List dependentEngineMybatisTypeHandlerConfigs) { + this.dependentEngineMybatisTypeHandlerConfigs = dependentEngineMybatisTypeHandlerConfigs; + return this; + } + + public List getCustomSessionFactories() { + return customSessionFactories; + } + + public AbstractEngineConfiguration addCustomSessionFactory(SessionFactory sessionFactory) { + if (customSessionFactories == null) { + customSessionFactories = new ArrayList<>(); + } + customSessionFactories.add(sessionFactory); + return this; + } + + public AbstractEngineConfiguration setCustomSessionFactories(List customSessionFactories) { + this.customSessionFactories = customSessionFactories; + return this; + } + + public boolean isUsingRelationalDatabase() { + return usingRelationalDatabase; + } + + public AbstractEngineConfiguration setUsingRelationalDatabase(boolean usingRelationalDatabase) { + this.usingRelationalDatabase = usingRelationalDatabase; + return this; + } + + public boolean isUsingSchemaMgmt() { + return usingSchemaMgmt; + } + + public AbstractEngineConfiguration setUsingSchemaMgmt(boolean usingSchema) { + this.usingSchemaMgmt = usingSchema; + return this; + } + + public String getDatabaseTablePrefix() { + return databaseTablePrefix; + } + + public AbstractEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) { + this.databaseTablePrefix = databaseTablePrefix; + return this; + } + + public String getDatabaseWildcardEscapeCharacter() { + return databaseWildcardEscapeCharacter; + } + + public AbstractEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) { + this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter; + return this; + } + + public String getDatabaseCatalog() { + return databaseCatalog; + } + + public AbstractEngineConfiguration setDatabaseCatalog(String databaseCatalog) { + this.databaseCatalog = databaseCatalog; + return this; + } + + public String getDatabaseSchema() { + return databaseSchema; + } + + public AbstractEngineConfiguration setDatabaseSchema(String databaseSchema) { + this.databaseSchema = databaseSchema; + return this; + } + + public boolean isTablePrefixIsSchema() { + return tablePrefixIsSchema; + } + + public AbstractEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) { + this.tablePrefixIsSchema = tablePrefixIsSchema; + return this; + } + + public boolean isAlwaysLookupLatestDefinitionVersion() { + return alwaysLookupLatestDefinitionVersion; + } + + public AbstractEngineConfiguration setAlwaysLookupLatestDefinitionVersion(boolean alwaysLookupLatestDefinitionVersion) { + this.alwaysLookupLatestDefinitionVersion = alwaysLookupLatestDefinitionVersion; + return this; + } + + public boolean isFallbackToDefaultTenant() { + return fallbackToDefaultTenant; + } + + public AbstractEngineConfiguration setFallbackToDefaultTenant(boolean fallbackToDefaultTenant) { + this.fallbackToDefaultTenant = fallbackToDefaultTenant; + return this; + } + + /** + * @return name of the default tenant + * @deprecated use {@link AbstractEngineConfiguration#getDefaultTenantProvider()} instead + */ + @Deprecated + public String getDefaultTenantValue() { + return getDefaultTenantProvider().getDefaultTenant(null, null, null); + } + + public AbstractEngineConfiguration setDefaultTenantValue(String defaultTenantValue) { + this.defaultTenantProvider = (tenantId, scope, scopeKey) -> defaultTenantValue; + return this; + } + + public DefaultTenantProvider getDefaultTenantProvider() { + return defaultTenantProvider; + } + + public AbstractEngineConfiguration setDefaultTenantProvider(DefaultTenantProvider defaultTenantProvider) { + this.defaultTenantProvider = defaultTenantProvider; + return this; + } + + public boolean isEnableLogSqlExecutionTime() { + return enableLogSqlExecutionTime; + } + + public void setEnableLogSqlExecutionTime(boolean enableLogSqlExecutionTime) { + this.enableLogSqlExecutionTime = enableLogSqlExecutionTime; + } + + public Map, SessionFactory> getSessionFactories() { + return sessionFactories; + } + + public AbstractEngineConfiguration setSessionFactories(Map, SessionFactory> sessionFactories) { + this.sessionFactories = sessionFactories; + return this; + } + + public String getDatabaseSchemaUpdate() { + return databaseSchemaUpdate; + } + + public AbstractEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) { + this.databaseSchemaUpdate = databaseSchemaUpdate; + return this; + } + + public boolean isUseLockForDatabaseSchemaUpdate() { + return useLockForDatabaseSchemaUpdate; + } + + public AbstractEngineConfiguration setUseLockForDatabaseSchemaUpdate(boolean useLockForDatabaseSchemaUpdate) { + this.useLockForDatabaseSchemaUpdate = useLockForDatabaseSchemaUpdate; + return this; + } + + public boolean isEnableEventDispatcher() { + return enableEventDispatcher; + } + + public AbstractEngineConfiguration setEnableEventDispatcher(boolean enableEventDispatcher) { + this.enableEventDispatcher = enableEventDispatcher; + return this; + } + + public FlowableEventDispatcher getEventDispatcher() { + return eventDispatcher; + } + + public AbstractEngineConfiguration setEventDispatcher(FlowableEventDispatcher eventDispatcher) { + this.eventDispatcher = eventDispatcher; + return this; + } + + public List getEventListeners() { + return eventListeners; + } + + public AbstractEngineConfiguration setEventListeners(List eventListeners) { + this.eventListeners = eventListeners; + return this; + } + + public Map> getTypedEventListeners() { + return typedEventListeners; + } + + public AbstractEngineConfiguration setTypedEventListeners(Map> typedEventListeners) { + this.typedEventListeners = typedEventListeners; + return this; + } + + public List getAdditionalEventDispatchActions() { + return additionalEventDispatchActions; + } + + public AbstractEngineConfiguration setAdditionalEventDispatchActions(List additionalEventDispatchActions) { + this.additionalEventDispatchActions = additionalEventDispatchActions; + return this; + } + + public void initEventDispatcher() { + if (this.eventDispatcher == null) { + this.eventDispatcher = new FlowableEventDispatcherImpl(); + } + + initAdditionalEventDispatchActions(); + + this.eventDispatcher.setEnabled(enableEventDispatcher); + + initEventListeners(); + initTypedEventListeners(); + } + + protected void initEventListeners() { + if (eventListeners != null) { + for (FlowableEventListener listenerToAdd : eventListeners) { + this.eventDispatcher.addEventListener(listenerToAdd); + } + } + } + + protected void initAdditionalEventDispatchActions() { + if (this.additionalEventDispatchActions == null) { + this.additionalEventDispatchActions = new ArrayList<>(); + } + } + + protected void initTypedEventListeners() { + if (typedEventListeners != null) { + for (Map.Entry> listenersToAdd : typedEventListeners.entrySet()) { + // Extract types from the given string + FlowableEngineEventType[] types = FlowableEngineEventType.getTypesFromString(listenersToAdd.getKey()); + + for (FlowableEventListener listenerToAdd : listenersToAdd.getValue()) { + this.eventDispatcher.addEventListener(listenerToAdd, types); + } + } + } + } + + public boolean isLoggingSessionEnabled() { + return loggingListener != null; + } + + public LoggingListener getLoggingListener() { + return loggingListener; + } + + public void setLoggingListener(LoggingListener loggingListener) { + this.loggingListener = loggingListener; + } + + public Clock getClock() { + return clock; + } + + public AbstractEngineConfiguration setClock(Clock clock) { + this.clock = clock; + return this; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public AbstractEngineConfiguration setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public int getMaxLengthString() { + if (maxLengthStringVariableType == -1) { + if ("oracle".equalsIgnoreCase(databaseType)) { + return DEFAULT_ORACLE_MAX_LENGTH_STRING; + } else { + return DEFAULT_GENERIC_MAX_LENGTH_STRING; + } + } else { + return maxLengthStringVariableType; + } + } + + public int getMaxLengthStringVariableType() { + return maxLengthStringVariableType; + } + + public AbstractEngineConfiguration setMaxLengthStringVariableType(int maxLengthStringVariableType) { + this.maxLengthStringVariableType = maxLengthStringVariableType; + return this; + } + + public PropertyDataManager getPropertyDataManager() { + return propertyDataManager; + } + + public Duration getLockPollRate() { + return lockPollRate; + } + + public AbstractEngineConfiguration setLockPollRate(Duration lockPollRate) { + this.lockPollRate = lockPollRate; + return this; + } + + public Duration getSchemaLockWaitTime() { + return schemaLockWaitTime; + } + + public void setSchemaLockWaitTime(Duration schemaLockWaitTime) { + this.schemaLockWaitTime = schemaLockWaitTime; + } + + public AbstractEngineConfiguration setPropertyDataManager(PropertyDataManager propertyDataManager) { + this.propertyDataManager = propertyDataManager; + return this; + } + + public PropertyEntityManager getPropertyEntityManager() { + return propertyEntityManager; + } + + public AbstractEngineConfiguration setPropertyEntityManager(PropertyEntityManager propertyEntityManager) { + this.propertyEntityManager = propertyEntityManager; + return this; + } + + public ByteArrayDataManager getByteArrayDataManager() { + return byteArrayDataManager; + } + + public AbstractEngineConfiguration setByteArrayDataManager(ByteArrayDataManager byteArrayDataManager) { + this.byteArrayDataManager = byteArrayDataManager; + return this; + } + + public ByteArrayEntityManager getByteArrayEntityManager() { + return byteArrayEntityManager; + } + + public AbstractEngineConfiguration setByteArrayEntityManager(ByteArrayEntityManager byteArrayEntityManager) { + this.byteArrayEntityManager = byteArrayEntityManager; + return this; + } + + public TableDataManager getTableDataManager() { + return tableDataManager; + } + + public AbstractEngineConfiguration setTableDataManager(TableDataManager tableDataManager) { + this.tableDataManager = tableDataManager; + return this; + } + + public List getDeployers() { + return deployers; + } + + public AbstractEngineConfiguration setDeployers(List deployers) { + this.deployers = deployers; + return this; + } + + public List getCustomPreDeployers() { + return customPreDeployers; + } + + public AbstractEngineConfiguration setCustomPreDeployers(List customPreDeployers) { + this.customPreDeployers = customPreDeployers; + return this; + } + + public List getCustomPostDeployers() { + return customPostDeployers; + } + + public AbstractEngineConfiguration setCustomPostDeployers(List customPostDeployers) { + this.customPostDeployers = customPostDeployers; + return this; + } + + public boolean isEnableConfiguratorServiceLoader() { + return enableConfiguratorServiceLoader; + } + + public AbstractEngineConfiguration setEnableConfiguratorServiceLoader(boolean enableConfiguratorServiceLoader) { + this.enableConfiguratorServiceLoader = enableConfiguratorServiceLoader; + return this; + } + + public List getConfigurators() { + return configurators; + } + + public AbstractEngineConfiguration addConfigurator(EngineConfigurator configurator) { + if (configurators == null) { + configurators = new ArrayList<>(); + } + configurators.add(configurator); + return this; + } + + /** + * @return All {@link EngineConfigurator} instances. Will only contain values after init of the engine. + * Use the {@link #getConfigurators()} or {@link #addConfigurator(EngineConfigurator)} methods otherwise. + */ + public List getAllConfigurators() { + return allConfigurators; + } + + public AbstractEngineConfiguration setConfigurators(List configurators) { + this.configurators = configurators; + return this; + } + + public EngineConfigurator getIdmEngineConfigurator() { + return idmEngineConfigurator; + } + + public AbstractEngineConfiguration setIdmEngineConfigurator(EngineConfigurator idmEngineConfigurator) { + this.idmEngineConfigurator = idmEngineConfigurator; + return this; + } + + public EngineConfigurator getEventRegistryConfigurator() { + return eventRegistryConfigurator; + } + + public AbstractEngineConfiguration setEventRegistryConfigurator(EngineConfigurator eventRegistryConfigurator) { + this.eventRegistryConfigurator = eventRegistryConfigurator; + return this; + } + + public AbstractEngineConfiguration setForceCloseMybatisConnectionPool(boolean forceCloseMybatisConnectionPool) { + this.forceCloseMybatisConnectionPool = forceCloseMybatisConnectionPool; + return this; + } + + public boolean isForceCloseMybatisConnectionPool() { + return forceCloseMybatisConnectionPool; + } +} diff --git a/sql/db2/flowable-patch/src/main/resources/META-INF/package-info.md b/sql/db2/flowable-patch/src/main/resources/META-INF/package-info.md new file mode 100644 index 000000000..1932c7a3f --- /dev/null +++ b/sql/db2/flowable-patch/src/main/resources/META-INF/package-info.md @@ -0,0 +1 @@ +防止IDEA将`.`和`/`混为一谈 \ No newline at end of file diff --git a/sql/db2/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database b/sql/db2/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database new file mode 100644 index 000000000..efbcfcca2 --- /dev/null +++ b/sql/db2/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database @@ -0,0 +1,21 @@ +liquibase.database.core.CockroachDatabase +liquibase.database.core.DB2Database +liquibase.database.core.Db2zDatabase +liquibase.database.core.DerbyDatabase +liquibase.database.core.Firebird3Database +liquibase.database.core.FirebirdDatabase +liquibase.database.core.H2Database +liquibase.database.core.HsqlDatabase +liquibase.database.core.InformixDatabase +liquibase.database.core.Ingres9Database +liquibase.database.core.MSSQLDatabase +liquibase.database.core.MariaDBDatabase +liquibase.database.core.MockDatabase +liquibase.database.core.MySQLDatabase +liquibase.database.core.OracleDatabase +liquibase.database.core.PostgresDatabase +liquibase.database.core.SQLiteDatabase +liquibase.database.core.SybaseASADatabase +liquibase.database.core.SybaseDatabase +liquibase.database.core.DmDatabase +liquibase.database.core.UnsupportedDatabase diff --git a/sql/dm/README.md b/sql/dm/README.md deleted file mode 100644 index e8b39a86a..000000000 --- a/sql/dm/README.md +++ /dev/null @@ -1,3 +0,0 @@ -暂未适配国产 DM 数据库,如果你有需要,可以微信联系 wangwenbin-server 一起建设。 - -你需要把表结构与数据导入到 DM 数据库,我来测试与适配代码。 diff --git a/sql/dm/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java b/sql/dm/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java new file mode 100644 index 000000000..fbc4c6bc1 --- /dev/null +++ b/sql/dm/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java @@ -0,0 +1,598 @@ +package liquibase.database.core; + +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import liquibase.CatalogAndSchema; +import liquibase.Scope; +import liquibase.database.AbstractJdbcDatabase; +import liquibase.database.DatabaseConnection; +import liquibase.database.OfflineConnection; +import liquibase.database.jvm.JdbcConnection; +import liquibase.exception.DatabaseException; +import liquibase.exception.UnexpectedLiquibaseException; +import liquibase.exception.ValidationErrors; +import liquibase.executor.ExecutorService; +import liquibase.statement.DatabaseFunction; +import liquibase.statement.SequenceCurrentValueFunction; +import liquibase.statement.SequenceNextValueFunction; +import liquibase.statement.core.RawCallStatement; +import liquibase.statement.core.RawSqlStatement; +import liquibase.structure.DatabaseObject; +import liquibase.structure.core.Catalog; +import liquibase.structure.core.Index; +import liquibase.structure.core.PrimaryKey; +import liquibase.structure.core.Schema; +import liquibase.util.JdbcUtils; +import liquibase.util.StringUtil; + +public class DmDatabase extends AbstractJdbcDatabase { + private static final String PRODUCT_NAME = "DM DBMS"; + + @Override + protected String getDefaultDatabaseProductName() { + return PRODUCT_NAME; + } + + /** + * Is this AbstractDatabase subclass the correct one to use for the given connection. + * + * @param conn + */ + @Override + public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException { + return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName()); + } + + /** + * If this database understands the given url, return the default driver class name. Otherwise return null. + * + * @param url + */ + @Override + public String getDefaultDriver(String url) { + if(url.startsWith("jdbc:dm")) { + return "dm.jdbc.driver.DmDriver"; + } + + return null; + } + + /** + * Returns an all-lower-case short name of the product. Used for end-user selecting of database type + * such as the DBMS precondition. + */ + @Override + public String getShortName() { + return "dm"; + } + + @Override + public Integer getDefaultPort() { + return 5236; + } + + /** + * Returns whether this database support initially deferrable columns. + */ + @Override + public boolean supportsInitiallyDeferrableColumns() { + return true; + } + + @Override + public boolean supportsTablespaces() { + return true; + } + + @Override + public int getPriority() { + return PRIORITY_DEFAULT; + } + + private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*"); + + protected final int SHORT_IDENTIFIERS_LENGTH = 30; + protected final int LONG_IDENTIFIERS_LEGNTH = 128; + public static final int ORACLE_12C_MAJOR_VERSION = 12; + + private Set reservedWords = new HashSet<>(); + private Set userDefinedTypes; + private Map savedSessionNlsSettings; + + private Boolean canAccessDbaRecycleBin; + private Integer databaseMajorVersion; + private Integer databaseMinorVersion; + + /** + * Default constructor for an object that represents the Oracle Database DBMS. + */ + public DmDatabase() { + super.unquotedObjectsAreUppercased = true; + //noinspection HardCodedStringLiteral + super.setCurrentDateTimeFunction("SYSTIMESTAMP"); + // Setting list of Oracle's native functions + //noinspection HardCodedStringLiteral + dateFunctions.add(new DatabaseFunction("SYSDATE")); + //noinspection HardCodedStringLiteral + dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP")); + //noinspection HardCodedStringLiteral + dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP")); + //noinspection HardCodedStringLiteral + super.sequenceNextValueFunction = "%s.nextval"; + //noinspection HardCodedStringLiteral + super.sequenceCurrentValueFunction = "%s.currval"; + } + + private void tryProxySession(final String url, final Connection con) { + Matcher m = PROXY_USER.matcher(url); + if (m.matches()) { + Properties props = new Properties(); + props.put("PROXY_USER_NAME", m.group(1)); + try { + Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class); + method.setAccessible(true); + method.invoke(con, 1, props); + } catch (Exception e) { + Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage()); + } + } + } + + @Override + public int getDatabaseMajorVersion() throws DatabaseException { + if (databaseMajorVersion == null) { + return super.getDatabaseMajorVersion(); + } else { + return databaseMajorVersion; + } + } + + @Override + public int getDatabaseMinorVersion() throws DatabaseException { + if (databaseMinorVersion == null) { + return super.getDatabaseMinorVersion(); + } else { + return databaseMinorVersion; + } + } + + @Override + public String getJdbcCatalogName(CatalogAndSchema schema) { + return null; + } + + @Override + public String getJdbcSchemaName(CatalogAndSchema schema) { + return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class); + } + + @Override + protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) { + if (StringUtil.isEmpty(generationType)) { + return super.getAutoIncrementClause(); + } + + String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ] + String generationStrategy = generationType; + if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) { + generationStrategy += " ON NULL"; + } + return String.format(autoIncrementClause, generationStrategy); + } + + @Override + public String generatePrimaryKeyName(String tableName) { + if (tableName.length() > 27) { + //noinspection HardCodedStringLiteral + return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27); + } else { + //noinspection HardCodedStringLiteral + return "PK_" + tableName.toUpperCase(Locale.US); + } + } + + @Override + public boolean isReservedWord(String objectName) { + return reservedWords.contains(objectName.toUpperCase()); + } + + @Override + public boolean supportsSequences() { + return true; + } + + /** + * Oracle supports catalogs in liquibase terms + * + * @return false + */ + @Override + public boolean supportsSchemas() { + return false; + } + + @Override + protected String getConnectionCatalogName() throws DatabaseException { + if (getConnection() instanceof OfflineConnection) { + return getConnection().getCatalog(); + } + try { + //noinspection HardCodedStringLiteral + return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class); + } catch (Exception e) { + //noinspection HardCodedStringLiteral + Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e); + } + return null; + } + + @Override + public String getDefaultCatalogName() {//NOPMD + return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US); + } + + /** + *

Returns an Oracle date literal with the same value as a string formatted using ISO 8601.

+ * + *

Convert an ISO8601 date string to one of the following results: + * to_date('1995-05-23', 'YYYY-MM-DD') + * to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')

+ *

+ * Implementation restriction:
+ * Currently, only the following subsets of ISO8601 are supported:
+ *

    + *
  • YYYY-MM-DD
  • + *
  • YYYY-MM-DDThh:mm:ss
  • + *
+ */ + @Override + public String getDateLiteral(String isoDate) { + String normalLiteral = super.getDateLiteral(isoDate); + + if (isDateOnly(isoDate)) { + return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')"; + } else if (isTimeOnly(isoDate)) { + return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')"; + } else if (isTimestamp(isoDate)) { + return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')"; + } else if (isDateTime(isoDate)) { + int seppos = normalLiteral.lastIndexOf('.'); + if (seppos != -1) { + normalLiteral = normalLiteral.substring(0, seppos) + "'"; + } + return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')"; + } + return "UNSUPPORTED:" + isoDate; + } + + @Override + public boolean isSystemObject(DatabaseObject example) { + if (example == null) { + return false; + } + + if (this.isLiquibaseObject(example)) { + return false; + } + + if (example instanceof Schema) { + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) { + return true; + } + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) { + return true; + } + } else if (isSystemObject(example.getSchema())) { + return true; + } + if (example instanceof Catalog) { + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) { + return true; + } + } else if (example.getName() != null) { + //noinspection HardCodedStringLiteral + if (example.getName().startsWith("BIN$")) { //oracle deleted table + boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin(); + if (!filteredInOriginalQuery) { + filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName()); + } + + if (filteredInOriginalQuery) { + return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof + liquibase.statement.UniqueConstraint)); + } else { + return true; + } + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("AQ$")) { //oracle AQ tables + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("DR$")) { //oracle index tables + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("SYS_IOT_OVER")) { //oracle system table + return true; + } else //noinspection HardCodedStringLiteral,HardCodedStringLiteral + if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) { + // CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("MLOG$_")) { //Created by materliaized view logs for every table that is part of a materialized view. Not available for DDL operations. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("RUPD$_")) { //Created by materialized view log tables using primary keys. Not available for DDL operations. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("WM$_")) { //Workspace Manager backup tables. + return true; + } else //noinspection HardCodedStringLiteral + if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) { //This table contains the name of the Java object, the date it was loaded, and has a BLOB column to store the Java object. + return true; + } else //noinspection HardCodedStringLiteral + if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) { //This is a hash table that tracks the loading of Java objects into a schema. + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("ISEQ$$_")) { //System-generated sequence + return true; + } else //noinspection HardCodedStringLiteral + if (example.getName().startsWith("USLOG$")) { //for update materialized view + return true; + } else if (example.getName().startsWith("SYS_FBA")) { //for Flashback tables + return true; + } + } + + return super.isSystemObject(example); + } + + @Override + public boolean supportsAutoIncrement() { + // Oracle supports Identity beginning with version 12c + boolean isAutoIncrementSupported = false; + + try { + if (getDatabaseMajorVersion() >= 12) { + isAutoIncrementSupported = true; + } + + // Returning true will generate create table command with 'IDENTITY' clause, example: + // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) GENERATED BY DEFAULT AS IDENTITY NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey)); + + // While returning false will continue to generate create table command without 'IDENTITY' clause, example: + // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey)); + + } catch (DatabaseException ex) { + isAutoIncrementSupported = false; + } + + return isAutoIncrementSupported; + } + + +// public Set findUniqueConstraints(String schema) throws DatabaseException { +// Set returnSet = new HashSet(); +// +// List maps = new Executor(this).queryForList(new RawSqlStatement("SELECT UC.CONSTRAINT_NAME, UCC.TABLE_NAME, UCC.COLUMN_NAME FROM USER_CONSTRAINTS UC, USER_CONS_COLUMNS UCC WHERE UC.CONSTRAINT_NAME=UCC.CONSTRAINT_NAME AND CONSTRAINT_TYPE='U' ORDER BY UC.CONSTRAINT_NAME")); +// +// UniqueConstraint constraint = null; +// for (Map map : maps) { +// if (constraint == null || !constraint.getName().equals(constraint.getName())) { +// returnSet.add(constraint); +// Table table = new Table((String) map.get("TABLE_NAME")); +// constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table); +// } +// } +// if (constraint != null) { +// returnSet.add(constraint); +// } +// +// return returnSet; +// } + + @Override + public boolean supportsRestrictForeignKeys() { + return false; + } + + @Override + public int getDataTypeMaxParameters(String dataTypeName) { + //noinspection HardCodedStringLiteral + if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) { + return 0; + } + //noinspection HardCodedStringLiteral + if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) { + return 0; + } + return super.getDataTypeMaxParameters(dataTypeName); + } + + public String getSystemTableWhereClause(String tableNameColumn) { + List clauses = new ArrayList(Arrays.asList("BIN$", + "AQ$", + "DR$", + "SYS_IOT_OVER", + "MLOG$_", + "RUPD$_", + "WM$_", + "ISEQ$$_", + "USLOG$", + "SYS_FBA")); + + for (int i = 0;i getUserDefinedTypes() { + if (userDefinedTypes == null) { + userDefinedTypes = new HashSet<>(); + if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) { + try { + try { + //noinspection HardCodedStringLiteral + userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class)); + } catch (DatabaseException e) { //fall back to USER_TYPES if the user cannot see ALL_TYPES + //noinspection HardCodedStringLiteral + userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class)); + } + } catch (DatabaseException e) { + //ignore error + } + } + } + + return userDefinedTypes; + } + + @Override + public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) { + //noinspection HardCodedStringLiteral + if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) { + return databaseFunction.toString(); + } + if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof + SequenceCurrentValueFunction)) { + String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction); + // replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval + return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\""); + + } + + return super.generateDatabaseFunctionValue(databaseFunction); + } + + @Override + public ValidationErrors validate() { + ValidationErrors errors = super.validate(); + DatabaseConnection connection = getConnection(); + if ((connection == null) || (connection instanceof OfflineConnection)) { + //noinspection HardCodedStringLiteral + Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database"); + return errors; + } + + if (!canAccessDbaRecycleBin()) { + errors.addWarning(getDbaRecycleBinWarning()); + } + + return errors; + + } + + public String getDbaRecycleBinWarning() { + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral, + // HardCodedStringLiteral + //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral + return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " + + "constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " + + "referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" + + " issue.\n" + + "\n" + + "The user you used to connect to the database (" + getConnection().getConnectionUserName() + + ") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " + + "Please run the following SQL to set the appropriate permissions, and try running the command again.\n" + + "\n" + + " GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";"; + } + + public boolean canAccessDbaRecycleBin() { + if (canAccessDbaRecycleBin == null) { + DatabaseConnection connection = getConnection(); + if ((connection == null) || (connection instanceof OfflineConnection)) { + return false; + } + + Statement statement = null; + try { + statement = ((JdbcConnection) connection).createStatement(); + @SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1"); + resultSet.close(); //don't need to do anything with the result set, just make sure statement ran. + this.canAccessDbaRecycleBin = true; + } catch (Exception e) { + //noinspection HardCodedStringLiteral + if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) { //ORA-00942: table or view does not exist + this.canAccessDbaRecycleBin = false; + } else { + //noinspection HardCodedStringLiteral + Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e); + this.canAccessDbaRecycleBin = false; + } + } finally { + JdbcUtils.close(null, statement); + } + } + + return canAccessDbaRecycleBin; + } + + @Override + public boolean supportsNotNullConstraintNames() { + return true; + } + + /** + * Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has + * the following form (case-insensitive comparison): + * 1st character: A-Z + * 2..n characters: A-Z0-9$_# + * The maximum length of an identifier differs by Oracle version and object type. + */ + public boolean isValidOracleIdentifier(String identifier, Class type) { + if ((identifier == null) || (identifier.length() < 1)) + return false; + + if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$")) + return false; + + /* + * @todo It seems we currently do not have a class for tablespace identifiers, and all other classes + * we do know seem to be supported as 12cR2 long identifiers, so: + */ + return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH); + } + + /** + * Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this + * is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare + * object types). + * + * @return the maximum length of an object identifier, in bytes + */ + public int getIdentifierMaximumLength() { + try { + if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) { + return SHORT_IDENTIFIERS_LENGTH; + } else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) { + return SHORT_IDENTIFIERS_LENGTH; + } else { + return LONG_IDENTIFIERS_LEGNTH; + } + } catch (DatabaseException ex) { + throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex); + } + + } +} diff --git a/sql/dm/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java b/sql/dm/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java new file mode 100644 index 000000000..cda2492e2 --- /dev/null +++ b/sql/dm/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java @@ -0,0 +1,165 @@ +package liquibase.datatype.core; + +import liquibase.change.core.LoadDataChange; +import liquibase.database.Database; +import liquibase.database.core.*; +import liquibase.datatype.DataTypeInfo; +import liquibase.datatype.DatabaseDataType; +import liquibase.datatype.LiquibaseDataType; +import liquibase.exception.UnexpectedLiquibaseException; +import liquibase.statement.DatabaseFunction; +import liquibase.util.StringUtil; + +import java.util.Locale; +import java.util.regex.Pattern; + +@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT) +public class BooleanType extends LiquibaseDataType { + + @Override + public DatabaseDataType toDatabaseDataType(Database database) { + String originalDefinition = StringUtil.trimToEmpty(getRawDefinition()); + if ((database instanceof Firebird3Database)) { + return new DatabaseDataType("BOOLEAN"); + } + + if ((database instanceof Db2zDatabase) || (database instanceof FirebirdDatabase)) { + return new DatabaseDataType("SMALLINT"); + } else if (database instanceof MSSQLDatabase) { + return new DatabaseDataType(database.escapeDataTypeName("bit")); + } else if (database instanceof MySQLDatabase) { + if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) { + return new DatabaseDataType("BIT", getParameters()); + } + return new DatabaseDataType("BIT", 1); + } else if (database instanceof OracleDatabase) { + return new DatabaseDataType("NUMBER", 1); + } else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) { + return new DatabaseDataType("BIT"); + } else if (database instanceof DerbyDatabase) { + if (((DerbyDatabase) database).supportsBooleanDataType()) { + return new DatabaseDataType("BOOLEAN"); + } else { + return new DatabaseDataType("SMALLINT"); + } + } else if (database instanceof DB2Database) { + if (((DB2Database) database).supportsBooleanDataType()) + return new DatabaseDataType("BOOLEAN"); + else + return new DatabaseDataType("SMALLINT"); + } else if (database instanceof HsqlDatabase) { + return new DatabaseDataType("BOOLEAN"); + } else if (database instanceof PostgresDatabase) { + if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) { + return new DatabaseDataType("BIT", getParameters()); + } + } else if (database instanceof DmDatabase) { // dhb52: DM Support + return new DatabaseDataType("bit"); + } + + return super.toDatabaseDataType(database); + } + + @Override + public String objectToSql(Object value, Database database) { + if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) { + return null; + } + + String returnValue; + if (value instanceof String) { + value = ((String) value).replaceAll("'", ""); + if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) { + returnValue = this.getTrueBooleanValue(database); + } else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals( + ((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) { + returnValue = this.getFalseBooleanValue(database); + } else if (database instanceof PostgresDatabase && Pattern.matches("b?([01])\\1*(::bit|::\"bit\")?", (String) value)) { + returnValue = "b'" + + value.toString() + .replace("b", "") + .replace("\"", "") + .replace("::it", "") + + "'::\"bit\""; + } else { + throw new UnexpectedLiquibaseException("Unknown boolean value: " + value); + } + } else if (value instanceof Long) { + if (Long.valueOf(1).equals(value)) { + returnValue = this.getTrueBooleanValue(database); + } else { + returnValue = this.getFalseBooleanValue(database); + } + } else if (value instanceof Number) { + if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) { + returnValue = this.getTrueBooleanValue(database); + } else { + returnValue = this.getFalseBooleanValue(database); + } + } else if (value instanceof DatabaseFunction) { + return value.toString(); + } else if (value instanceof Boolean) { + if (((Boolean) value)) { + returnValue = this.getTrueBooleanValue(database); + } else { + returnValue = this.getFalseBooleanValue(database); + } + } else { + throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value"); + } + + return returnValue; + } + + protected boolean isNumericBoolean(Database database) { + if (database instanceof Firebird3Database) { + return false; + } + if (database instanceof DerbyDatabase) { + return !((DerbyDatabase) database).supportsBooleanDataType(); + } else if (database instanceof DB2Database) { + return !((DB2Database) database).supportsBooleanDataType(); + } + return (database instanceof Db2zDatabase) + || (database instanceof FirebirdDatabase) + || (database instanceof MSSQLDatabase) + || (database instanceof MySQLDatabase) + || (database instanceof OracleDatabase) + || (database instanceof SQLiteDatabase) + || (database instanceof SybaseASADatabase) + || (database instanceof SybaseDatabase) + || (database instanceof DmDatabase); // dhb52: DM Support + } + + /** + * The database-specific value to use for "false" "boolean" columns. + */ + public String getFalseBooleanValue(Database database) { + if (isNumericBoolean(database)) { + return "0"; + } + if (database instanceof InformixDatabase) { + return "'f'"; + } + return "FALSE"; + } + + /** + * The database-specific value to use for "true" "boolean" columns. + */ + public String getTrueBooleanValue(Database database) { + if (isNumericBoolean(database)) { + return "1"; + } + if (database instanceof InformixDatabase) { + return "'t'"; + } + return "TRUE"; + } + + @Override + public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() { + return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN; + } + +} diff --git a/sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java b/sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java new file mode 100644 index 000000000..33c52d551 --- /dev/null +++ b/sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java @@ -0,0 +1,2068 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.flowable.common.engine.impl; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.ServiceLoader; +import java.util.Set; + +import javax.naming.InitialContext; +import javax.sql.DataSource; + +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.builder.xml.XMLConfigBuilder; +import org.apache.ibatis.builder.xml.XMLMapperBuilder; +import org.apache.ibatis.datasource.pooled.PooledDataSource; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; +import org.apache.ibatis.transaction.TransactionFactory; +import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import org.apache.ibatis.transaction.managed.ManagedTransactionFactory; +import org.apache.ibatis.type.ArrayTypeHandler; +import org.apache.ibatis.type.BigDecimalTypeHandler; +import org.apache.ibatis.type.BlobInputStreamTypeHandler; +import org.apache.ibatis.type.BlobTypeHandler; +import org.apache.ibatis.type.BooleanTypeHandler; +import org.apache.ibatis.type.ByteTypeHandler; +import org.apache.ibatis.type.ClobTypeHandler; +import org.apache.ibatis.type.DateOnlyTypeHandler; +import org.apache.ibatis.type.DateTypeHandler; +import org.apache.ibatis.type.DoubleTypeHandler; +import org.apache.ibatis.type.FloatTypeHandler; +import org.apache.ibatis.type.IntegerTypeHandler; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.LongTypeHandler; +import org.apache.ibatis.type.NClobTypeHandler; +import org.apache.ibatis.type.NStringTypeHandler; +import org.apache.ibatis.type.ShortTypeHandler; +import org.apache.ibatis.type.SqlxmlTypeHandler; +import org.apache.ibatis.type.StringTypeHandler; +import org.apache.ibatis.type.TimeOnlyTypeHandler; +import org.apache.ibatis.type.TypeHandlerRegistry; +import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType; +import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher; +import org.flowable.common.engine.api.delegate.event.FlowableEventListener; +import org.flowable.common.engine.api.engine.EngineLifecycleListener; +import org.flowable.common.engine.impl.agenda.AgendaOperationRunner; +import org.flowable.common.engine.impl.cfg.CommandExecutorImpl; +import org.flowable.common.engine.impl.cfg.IdGenerator; +import org.flowable.common.engine.impl.cfg.TransactionContextFactory; +import org.flowable.common.engine.impl.cfg.standalone.StandaloneMybatisTransactionContextFactory; +import org.flowable.common.engine.impl.db.CommonDbSchemaManager; +import org.flowable.common.engine.impl.db.DbSqlSessionFactory; +import org.flowable.common.engine.impl.db.LogSqlExecutionTimePlugin; +import org.flowable.common.engine.impl.db.MybatisTypeAliasConfigurator; +import org.flowable.common.engine.impl.db.MybatisTypeHandlerConfigurator; +import org.flowable.common.engine.impl.db.SchemaManager; +import org.flowable.common.engine.impl.event.EventDispatchAction; +import org.flowable.common.engine.impl.event.FlowableEventDispatcherImpl; +import org.flowable.common.engine.impl.interceptor.Command; +import org.flowable.common.engine.impl.interceptor.CommandConfig; +import org.flowable.common.engine.impl.interceptor.CommandContextFactory; +import org.flowable.common.engine.impl.interceptor.CommandContextInterceptor; +import org.flowable.common.engine.impl.interceptor.CommandExecutor; +import org.flowable.common.engine.impl.interceptor.CommandInterceptor; +import org.flowable.common.engine.impl.interceptor.CrDbRetryInterceptor; +import org.flowable.common.engine.impl.interceptor.DefaultCommandInvoker; +import org.flowable.common.engine.impl.interceptor.LogInterceptor; +import org.flowable.common.engine.impl.interceptor.SessionFactory; +import org.flowable.common.engine.impl.interceptor.TransactionContextInterceptor; +import org.flowable.common.engine.impl.lock.LockManager; +import org.flowable.common.engine.impl.lock.LockManagerImpl; +import org.flowable.common.engine.impl.logging.LoggingListener; +import org.flowable.common.engine.impl.logging.LoggingSession; +import org.flowable.common.engine.impl.logging.LoggingSessionFactory; +import org.flowable.common.engine.impl.persistence.GenericManagerFactory; +import org.flowable.common.engine.impl.persistence.StrongUuidGenerator; +import org.flowable.common.engine.impl.persistence.cache.EntityCache; +import org.flowable.common.engine.impl.persistence.cache.EntityCacheImpl; +import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManager; +import org.flowable.common.engine.impl.persistence.entity.ByteArrayEntityManagerImpl; +import org.flowable.common.engine.impl.persistence.entity.Entity; +import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManager; +import org.flowable.common.engine.impl.persistence.entity.PropertyEntityManagerImpl; +import org.flowable.common.engine.impl.persistence.entity.TableDataManager; +import org.flowable.common.engine.impl.persistence.entity.TableDataManagerImpl; +import org.flowable.common.engine.impl.persistence.entity.data.ByteArrayDataManager; +import org.flowable.common.engine.impl.persistence.entity.data.PropertyDataManager; +import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisByteArrayDataManager; +import org.flowable.common.engine.impl.persistence.entity.data.impl.MybatisPropertyDataManager; +import org.flowable.common.engine.impl.runtime.Clock; +import org.flowable.common.engine.impl.service.CommonEngineServiceImpl; +import org.flowable.common.engine.impl.util.DefaultClockImpl; +import org.flowable.common.engine.impl.util.IoUtil; +import org.flowable.common.engine.impl.util.ReflectUtil; +import org.flowable.eventregistry.api.EventRegistryEventConsumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +public abstract class AbstractEngineConfiguration { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + /** The tenant id indicating 'no tenant' */ + public static final String NO_TENANT_ID = ""; + + /** + * Checks the version of the DB schema against the library when the form engine is being created and throws an exception if the versions don't match. + */ + public static final String DB_SCHEMA_UPDATE_FALSE = "false"; + public static final String DB_SCHEMA_UPDATE_CREATE = "create"; + public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"; + + /** + * Creates the schema when the form engine is being created and drops the schema when the form engine is being closed. + */ + public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create"; + + /** + * Upon building of the process engine, a check is performed and an update of the schema is performed if it is necessary. + */ + public static final String DB_SCHEMA_UPDATE_TRUE = "true"; + + protected boolean forceCloseMybatisConnectionPool = true; + + protected String databaseType; + protected String jdbcDriver = "org.h2.Driver"; + protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/flowable"; + protected String jdbcUsername = "sa"; + protected String jdbcPassword = ""; + protected String dataSourceJndiName; + protected int jdbcMaxActiveConnections = 16; + protected int jdbcMaxIdleConnections = 8; + protected int jdbcMaxCheckoutTime; + protected int jdbcMaxWaitTime; + protected boolean jdbcPingEnabled; + protected String jdbcPingQuery; + protected int jdbcPingConnectionNotUsedFor; + protected int jdbcDefaultTransactionIsolationLevel; + protected DataSource dataSource; + protected SchemaManager commonSchemaManager; + protected SchemaManager schemaManager; + protected Command schemaManagementCmd; + + protected String databaseSchemaUpdate = DB_SCHEMA_UPDATE_FALSE; + + /** + * Whether to use a lock when performing the database schema create or update operations. + */ + protected boolean useLockForDatabaseSchemaUpdate = false; + + protected String xmlEncoding = "UTF-8"; + + // COMMAND EXECUTORS /////////////////////////////////////////////// + + protected CommandExecutor commandExecutor; + protected Collection defaultCommandInterceptors; + protected CommandConfig defaultCommandConfig; + protected CommandConfig schemaCommandConfig; + protected CommandContextFactory commandContextFactory; + protected CommandInterceptor commandInvoker; + + protected AgendaOperationRunner agendaOperationRunner = (commandContext, runnable) -> runnable.run(); + + protected List customPreCommandInterceptors; + protected List customPostCommandInterceptors; + protected List commandInterceptors; + + protected Map engineConfigurations = new HashMap<>(); + protected Map serviceConfigurations = new HashMap<>(); + + protected ClassLoader classLoader; + /** + * Either use Class.forName or ClassLoader.loadClass for class loading. See http://forums.activiti.org/content/reflectutilloadclass-and-custom- classloader + */ + protected boolean useClassForNameClassLoading = true; + + protected List engineLifecycleListeners; + + // Event Registry ////////////////////////////////////////////////// + protected Map eventRegistryEventConsumers = new HashMap<>(); + + // MYBATIS SQL SESSION FACTORY ///////////////////////////////////// + + protected boolean isDbHistoryUsed = true; + protected DbSqlSessionFactory dbSqlSessionFactory; + protected SqlSessionFactory sqlSessionFactory; + protected TransactionFactory transactionFactory; + protected TransactionContextFactory transactionContextFactory; + + /** + * If set to true, enables bulk insert (grouping sql inserts together). Default true. + * For some databases (eg DB2+z/OS) needs to be set to false. + */ + protected boolean isBulkInsertEnabled = true; + + /** + * Some databases have a limit of how many parameters one sql insert can have (eg SQL Server, 2000 params (!= insert statements) ). Tweak this parameter in case of exceptions indicating too much + * is being put into one bulk insert, or make it higher if your database can cope with it and there are inserts with a huge amount of data. + *

+ * By default: 100 (55 for mssql server as it has a hard limit of 2000 parameters in a statement) + */ + protected int maxNrOfStatementsInBulkInsert = 100; + + public int DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER = 55; // currently Execution has most params (35). 2000 / 35 = 57. + + protected String mybatisMappingFile; + protected Set> customMybatisMappers; + protected Set customMybatisXMLMappers; + protected List customMybatisInterceptors; + + protected Set dependentEngineMyBatisXmlMappers; + protected List dependentEngineMybatisTypeAliasConfigs; + protected List dependentEngineMybatisTypeHandlerConfigs; + + // SESSION FACTORIES /////////////////////////////////////////////// + protected List customSessionFactories; + protected Map, SessionFactory> sessionFactories; + + protected boolean enableEventDispatcher = true; + protected FlowableEventDispatcher eventDispatcher; + protected List eventListeners; + protected Map> typedEventListeners; + protected List additionalEventDispatchActions; + + protected LoggingListener loggingListener; + + protected boolean transactionsExternallyManaged; + + /** + * Flag that can be set to configure or not a relational database is used. This is useful for custom implementations that do not use relational databases at all. + * + * If true (default), the {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will be used to determine what needs to happen wrt the database schema. + * + * If false, no validation or schema creation will be done. That means that the database schema must have been created 'manually' before but the engine does not validate whether the schema is + * correct. The {@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()} value will not be used. + */ + protected boolean usingRelationalDatabase = true; + + /** + * Flag that can be set to configure whether or not a schema is used. This is useful for custom implementations that do not use relational databases at all. + * Setting {@link #usingRelationalDatabase} to true will automatically imply using a schema. + */ + protected boolean usingSchemaMgmt = true; + + /** + * Allows configuring a database table prefix which is used for all runtime operations of the process engine. For example, if you specify a prefix named 'PRE1.', Flowable will query for executions + * in a table named 'PRE1.ACT_RU_EXECUTION_'. + * + *

+ * NOTE: the prefix is not respected by automatic database schema management. If you use {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_CREATE_DROP} or + * {@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_TRUE}, Flowable will create the database tables using the default names, regardless of the prefix configured here. + */ + protected String databaseTablePrefix = ""; + + /** + * Escape character for doing wildcard searches. + * + * This will be added at then end of queries that include for example a LIKE clause. For example: SELECT * FROM table WHERE column LIKE '%\%%' ESCAPE '\'; + */ + protected String databaseWildcardEscapeCharacter; + + /** + * database catalog to use + */ + protected String databaseCatalog = ""; + + /** + * In some situations you want to set the schema to use for table checks / generation if the database metadata doesn't return that correctly, see https://jira.codehaus.org/browse/ACT-1220, + * https://jira.codehaus.org/browse/ACT-1062 + */ + protected String databaseSchema; + + /** + * Set to true in case the defined databaseTablePrefix is a schema-name, instead of an actual table name prefix. This is relevant for checking if Flowable-tables exist, the databaseTablePrefix + * will not be used here - since the schema is taken into account already, adding a prefix for the table-check will result in wrong table-names. + */ + protected boolean tablePrefixIsSchema; + + /** + * Set to true if the latest version of a definition should be retrieved, ignoring a possible parent deployment id value + */ + protected boolean alwaysLookupLatestDefinitionVersion; + + /** + * Set to true if by default lookups should fallback to the default tenant (an empty string by default or a defined tenant value) + */ + protected boolean fallbackToDefaultTenant; + + /** + * Default tenant provider that is executed when looking up definitions, in case the global or local fallback to default tenant value is true + */ + protected DefaultTenantProvider defaultTenantProvider = (tenantId, scope, scopeKey) -> NO_TENANT_ID; + + /** + * Enables the MyBatis plugin that logs the execution time of sql statements. + */ + protected boolean enableLogSqlExecutionTime; + + protected Properties databaseTypeMappings = getDefaultDatabaseTypeMappings(); + + /** + * Duration between the checks when acquiring a lock. + */ + protected Duration lockPollRate = Duration.ofSeconds(10); + + /** + * Duration to wait for the DB Schema lock before giving up. + */ + protected Duration schemaLockWaitTime = Duration.ofMinutes(5); + + // DATA MANAGERS ////////////////////////////////////////////////////////////////// + + protected PropertyDataManager propertyDataManager; + protected ByteArrayDataManager byteArrayDataManager; + protected TableDataManager tableDataManager; + + // ENTITY MANAGERS //////////////////////////////////////////////////////////////// + + protected PropertyEntityManager propertyEntityManager; + protected ByteArrayEntityManager byteArrayEntityManager; + + protected List customPreDeployers; + protected List customPostDeployers; + protected List deployers; + + // CONFIGURATORS //////////////////////////////////////////////////////////// + + protected boolean enableConfiguratorServiceLoader = true; // Enabled by default. In certain environments this should be set to false (eg osgi) + protected List configurators; // The injected configurators + protected List allConfigurators; // Including auto-discovered configurators + protected EngineConfigurator idmEngineConfigurator; + protected EngineConfigurator eventRegistryConfigurator; + + public static final String PRODUCT_NAME_POSTGRES = "PostgreSQL"; + public static final String PRODUCT_NAME_CRDB = "CockroachDB"; + + public static final String DATABASE_TYPE_H2 = "h2"; + public static final String DATABASE_TYPE_HSQL = "hsql"; + public static final String DATABASE_TYPE_MYSQL = "mysql"; + public static final String DATABASE_TYPE_ORACLE = "oracle"; + public static final String DATABASE_TYPE_POSTGRES = "postgres"; + public static final String DATABASE_TYPE_MSSQL = "mssql"; + public static final String DATABASE_TYPE_DB2 = "db2"; + public static final String DATABASE_TYPE_COCKROACHDB = "cockroachdb"; + + public static Properties getDefaultDatabaseTypeMappings() { + Properties databaseTypeMappings = new Properties(); + databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2); + databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL); + databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL); + databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL); + databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE); + databaseTypeMappings.setProperty(PRODUCT_NAME_POSTGRES, DATABASE_TYPE_POSTGRES); + databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL); + databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2); + databaseTypeMappings.setProperty(PRODUCT_NAME_CRDB, DATABASE_TYPE_COCKROACHDB); + databaseTypeMappings.setProperty("DM DBMS", DATABASE_TYPE_ORACLE); // dhb52: DM support + return databaseTypeMappings; + } + + protected Map beans; + + protected IdGenerator idGenerator; + protected boolean usePrefixId; + + protected Clock clock; + protected ObjectMapper objectMapper; + + // Variables + + public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000; + public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000; + + /** + * Define a max length for storing String variable types in the database. Mainly used for the Oracle NVARCHAR2 limit of 2000 characters + */ + protected int maxLengthStringVariableType = -1; + + protected void initEngineConfigurations() { + addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this); + } + + // DataSource + // /////////////////////////////////////////////////////////////// + + protected void initDataSource() { + if (dataSource == null) { + if (dataSourceJndiName != null) { + try { + dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName); + } catch (Exception e) { + throw new FlowableException("couldn't lookup datasource from " + dataSourceJndiName + ": " + e.getMessage(), e); + } + + } else if (jdbcUrl != null) { + if ((jdbcDriver == null) || (jdbcUsername == null)) { + throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration"); + } + + logger.debug("initializing datasource to db: {}", jdbcUrl); + + if (logger.isInfoEnabled()) { + logger.info("Configuring Datasource with following properties (omitted password for security)"); + logger.info("datasource driver : {}", jdbcDriver); + logger.info("datasource url : {}", jdbcUrl); + logger.info("datasource user name : {}", jdbcUsername); + } + + PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword); + + if (jdbcMaxActiveConnections > 0) { + pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections); + } + if (jdbcMaxIdleConnections > 0) { + pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections); + } + if (jdbcMaxCheckoutTime > 0) { + pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime); + } + if (jdbcMaxWaitTime > 0) { + pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime); + } + if (jdbcPingEnabled) { + pooledDataSource.setPoolPingEnabled(true); + if (jdbcPingQuery != null) { + pooledDataSource.setPoolPingQuery(jdbcPingQuery); + } + pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor); + } + if (jdbcDefaultTransactionIsolationLevel > 0) { + pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel); + } + dataSource = pooledDataSource; + } + } + + if (databaseType == null) { + initDatabaseType(); + } + } + + public void initDatabaseType() { + Connection connection = null; + try { + connection = dataSource.getConnection(); + DatabaseMetaData databaseMetaData = connection.getMetaData(); + String databaseProductName = databaseMetaData.getDatabaseProductName(); + logger.debug("database product name: '{}'", databaseProductName); + + // CRDB does not expose the version through the jdbc driver, so we need to fetch it through version(). + if (PRODUCT_NAME_POSTGRES.equalsIgnoreCase(databaseProductName)) { + try (PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;"); + ResultSet resultSet = preparedStatement.executeQuery()) { + String version = null; + if (resultSet.next()) { + version = resultSet.getString("version"); + } + + if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith(PRODUCT_NAME_CRDB.toLowerCase())) { + databaseProductName = PRODUCT_NAME_CRDB; + logger.info("CockroachDB version '{}' detected", version); + } + } + } + + databaseType = databaseTypeMappings.getProperty(databaseProductName); + if (databaseType == null) { + throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'"); + } + logger.debug("using database type: {}", databaseType); + + } catch (SQLException e) { + throw new RuntimeException("Exception while initializing Database connection", e); + } finally { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + logger.error("Exception while closing the Database connection", e); + } + } + + // Special care for MSSQL, as it has a hard limit of 2000 params per statement (incl bulk statement). + // Especially with executions, with 100 as default, this limit is passed. + if (DATABASE_TYPE_MSSQL.equals(databaseType)) { + maxNrOfStatementsInBulkInsert = DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER; + } + } + + public void initSchemaManager() { + if (this.commonSchemaManager == null) { + this.commonSchemaManager = new CommonDbSchemaManager(); + } + } + + // session factories //////////////////////////////////////////////////////// + + public void addSessionFactory(SessionFactory sessionFactory) { + sessionFactories.put(sessionFactory.getSessionType(), sessionFactory); + } + + public void initCommandContextFactory() { + if (commandContextFactory == null) { + commandContextFactory = new CommandContextFactory(); + } + } + + public void initTransactionContextFactory() { + if (transactionContextFactory == null) { + transactionContextFactory = new StandaloneMybatisTransactionContextFactory(); + } + } + + public void initCommandExecutors() { + initDefaultCommandConfig(); + initSchemaCommandConfig(); + initCommandInvoker(); + initCommandInterceptors(); + initCommandExecutor(); + } + + + public void initDefaultCommandConfig() { + if (defaultCommandConfig == null) { + defaultCommandConfig = new CommandConfig(); + } + } + + public void initSchemaCommandConfig() { + if (schemaCommandConfig == null) { + schemaCommandConfig = new CommandConfig(); + } + } + + public void initCommandInvoker() { + if (commandInvoker == null) { + commandInvoker = new DefaultCommandInvoker(); + } + } + + public void initCommandInterceptors() { + if (commandInterceptors == null) { + commandInterceptors = new ArrayList<>(); + if (customPreCommandInterceptors != null) { + commandInterceptors.addAll(customPreCommandInterceptors); + } + commandInterceptors.addAll(getDefaultCommandInterceptors()); + if (customPostCommandInterceptors != null) { + commandInterceptors.addAll(customPostCommandInterceptors); + } + commandInterceptors.add(commandInvoker); + } + } + + public Collection getDefaultCommandInterceptors() { + if (defaultCommandInterceptors == null) { + List interceptors = new ArrayList<>(); + interceptors.add(new LogInterceptor()); + + if (DATABASE_TYPE_COCKROACHDB.equals(databaseType)) { + interceptors.add(new CrDbRetryInterceptor()); + } + + CommandInterceptor transactionInterceptor = createTransactionInterceptor(); + if (transactionInterceptor != null) { + interceptors.add(transactionInterceptor); + } + + if (commandContextFactory != null) { + String engineCfgKey = getEngineCfgKey(); + CommandContextInterceptor commandContextInterceptor = new CommandContextInterceptor(commandContextFactory, + classLoader, useClassForNameClassLoading, clock, objectMapper); + engineConfigurations.put(engineCfgKey, this); + commandContextInterceptor.setEngineCfgKey(engineCfgKey); + commandContextInterceptor.setEngineConfigurations(engineConfigurations); + interceptors.add(commandContextInterceptor); + } + + if (transactionContextFactory != null) { + interceptors.add(new TransactionContextInterceptor(transactionContextFactory)); + } + + List additionalCommandInterceptors = getAdditionalDefaultCommandInterceptors(); + if (additionalCommandInterceptors != null) { + interceptors.addAll(additionalCommandInterceptors); + } + + defaultCommandInterceptors = interceptors; + } + return defaultCommandInterceptors; + } + + public abstract String getEngineCfgKey(); + + public abstract String getEngineScopeType(); + + public List getAdditionalDefaultCommandInterceptors() { + return null; + } + + public void initCommandExecutor() { + if (commandExecutor == null) { + CommandInterceptor first = initInterceptorChain(commandInterceptors); + commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first); + } + } + + public CommandInterceptor initInterceptorChain(List chain) { + if (chain == null || chain.isEmpty()) { + throw new FlowableException("invalid command interceptor chain configuration: " + chain); + } + for (int i = 0; i < chain.size() - 1; i++) { + chain.get(i).setNext(chain.get(i + 1)); + } + return chain.get(0); + } + + public abstract CommandInterceptor createTransactionInterceptor(); + + + public void initBeans() { + if (beans == null) { + beans = new HashMap<>(); + } + } + + // id generator + // ///////////////////////////////////////////////////////////// + + public void initIdGenerator() { + if (idGenerator == null) { + idGenerator = new StrongUuidGenerator(); + } + } + + public void initObjectMapper() { + if (objectMapper == null) { + objectMapper = new ObjectMapper(); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + } + } + + public void initClock() { + if (clock == null) { + clock = new DefaultClockImpl(); + } + } + + // Data managers /////////////////////////////////////////////////////////// + + public void initDataManagers() { + if (propertyDataManager == null) { + propertyDataManager = new MybatisPropertyDataManager(idGenerator); + } + + if (byteArrayDataManager == null) { + byteArrayDataManager = new MybatisByteArrayDataManager(idGenerator); + } + } + + // Entity managers ////////////////////////////////////////////////////////// + + public void initEntityManagers() { + if (propertyEntityManager == null) { + propertyEntityManager = new PropertyEntityManagerImpl(this, propertyDataManager); + } + + if (byteArrayEntityManager == null) { + byteArrayEntityManager = new ByteArrayEntityManagerImpl(byteArrayDataManager, getEngineCfgKey(), this::getEventDispatcher); + } + + if (tableDataManager == null) { + tableDataManager = new TableDataManagerImpl(this); + } + } + + // services + // ///////////////////////////////////////////////////////////////// + + protected void initService(Object service) { + if (service instanceof CommonEngineServiceImpl) { + ((CommonEngineServiceImpl) service).setCommandExecutor(commandExecutor); + } + } + + // myBatis SqlSessionFactory + // //////////////////////////////////////////////// + + public void initSessionFactories() { + if (sessionFactories == null) { + sessionFactories = new HashMap<>(); + + if (usingRelationalDatabase) { + initDbSqlSessionFactory(); + } + + addSessionFactory(new GenericManagerFactory(EntityCache.class, EntityCacheImpl.class)); + + if (isLoggingSessionEnabled()) { + if (!sessionFactories.containsKey(LoggingSession.class)) { + LoggingSessionFactory loggingSessionFactory = new LoggingSessionFactory(); + loggingSessionFactory.setLoggingListener(loggingListener); + loggingSessionFactory.setObjectMapper(objectMapper); + sessionFactories.put(LoggingSession.class, loggingSessionFactory); + } + } + + commandContextFactory.setSessionFactories(sessionFactories); + + } else { + if (usingRelationalDatabase) { + initDbSqlSessionFactoryEntitySettings(); + } + } + + if (customSessionFactories != null) { + for (SessionFactory sessionFactory : customSessionFactories) { + addSessionFactory(sessionFactory); + } + } + } + + public void initDbSqlSessionFactory() { + if (dbSqlSessionFactory == null) { + dbSqlSessionFactory = createDbSqlSessionFactory(); + } + dbSqlSessionFactory.setDatabaseType(databaseType); + dbSqlSessionFactory.setSqlSessionFactory(sqlSessionFactory); + dbSqlSessionFactory.setDbHistoryUsed(isDbHistoryUsed); + dbSqlSessionFactory.setDatabaseTablePrefix(databaseTablePrefix); + dbSqlSessionFactory.setTablePrefixIsSchema(tablePrefixIsSchema); + dbSqlSessionFactory.setDatabaseCatalog(databaseCatalog); + dbSqlSessionFactory.setDatabaseSchema(databaseSchema); + dbSqlSessionFactory.setMaxNrOfStatementsInBulkInsert(maxNrOfStatementsInBulkInsert); + + initDbSqlSessionFactoryEntitySettings(); + + addSessionFactory(dbSqlSessionFactory); + } + + public DbSqlSessionFactory createDbSqlSessionFactory() { + return new DbSqlSessionFactory(usePrefixId); + } + + protected abstract void initDbSqlSessionFactoryEntitySettings(); + + protected void defaultInitDbSqlSessionFactoryEntitySettings(List> insertOrder, List> deleteOrder) { + if (insertOrder != null) { + for (Class clazz : insertOrder) { + dbSqlSessionFactory.getInsertionOrder().add(clazz); + + if (isBulkInsertEnabled) { + dbSqlSessionFactory.getBulkInserteableEntityClasses().add(clazz); + } + } + } + + if (deleteOrder != null) { + for (Class clazz : deleteOrder) { + dbSqlSessionFactory.getDeletionOrder().add(clazz); + } + } + } + + public void initTransactionFactory() { + if (transactionFactory == null) { + if (transactionsExternallyManaged) { + transactionFactory = new ManagedTransactionFactory(); + Properties properties = new Properties(); + properties.put("closeConnection", "false"); + this.transactionFactory.setProperties(properties); + } else { + transactionFactory = new JdbcTransactionFactory(); + } + } + } + + public void initSqlSessionFactory() { + if (sqlSessionFactory == null) { + InputStream inputStream = null; + try { + inputStream = getMyBatisXmlConfigurationStream(); + + Environment environment = new Environment("default", transactionFactory, dataSource); + Reader reader = new InputStreamReader(inputStream); + Properties properties = new Properties(); + properties.put("prefix", databaseTablePrefix); + + String wildcardEscapeClause = ""; + if ((databaseWildcardEscapeCharacter != null) && (databaseWildcardEscapeCharacter.length() != 0)) { + wildcardEscapeClause = " escape '" + databaseWildcardEscapeCharacter + "'"; + } + properties.put("wildcardEscapeClause", wildcardEscapeClause); + + // set default properties + properties.put("limitBefore", ""); + properties.put("limitAfter", ""); + properties.put("limitBetween", ""); + properties.put("limitBeforeNativeQuery", ""); + properties.put("limitAfterNativeQuery", ""); + properties.put("blobType", "BLOB"); + properties.put("boolValue", "TRUE"); + + if (databaseType != null) { + properties.load(getResourceAsStream(pathToEngineDbProperties())); + } + + Configuration configuration = initMybatisConfiguration(environment, reader, properties); + sqlSessionFactory = new DefaultSqlSessionFactory(configuration); + + } catch (Exception e) { + throw new FlowableException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e); + } finally { + IoUtil.closeSilently(inputStream); + } + } else { + // This is needed when the SQL Session Factory is created by another engine. + // When custom XML Mappers are registered with this engine they need to be loaded in the configuration as well + applyCustomMybatisCustomizations(sqlSessionFactory.getConfiguration()); + } + } + + public String pathToEngineDbProperties() { + return "org/flowable/common/db/properties/" + databaseType + ".properties"; + } + + public Configuration initMybatisConfiguration(Environment environment, Reader reader, Properties properties) { + XMLConfigBuilder parser = new XMLConfigBuilder(reader, "", properties); + Configuration configuration = parser.getConfiguration(); + + if (databaseType != null) { + configuration.setDatabaseId(databaseType); + } + + configuration.setEnvironment(environment); + + initMybatisTypeHandlers(configuration); + initCustomMybatisInterceptors(configuration); + if (isEnableLogSqlExecutionTime()) { + initMyBatisLogSqlExecutionTimePlugin(configuration); + } + + configuration = parseMybatisConfiguration(parser); + return configuration; + } + + public void initCustomMybatisMappers(Configuration configuration) { + if (getCustomMybatisMappers() != null) { + for (Class clazz : getCustomMybatisMappers()) { + if (!configuration.hasMapper(clazz)) { + configuration.addMapper(clazz); + } + } + } + } + + public void initMybatisTypeHandlers(Configuration configuration) { + // When mapping into Map there is currently a problem with MyBatis. + // It will return objects which are driver specific. + // Therefore we are registering the mappings between Object.class and the specific jdbc type here. + // see https://github.com/mybatis/mybatis-3/issues/2216 for more info + TypeHandlerRegistry handlerRegistry = configuration.getTypeHandlerRegistry(); + + handlerRegistry.register(Object.class, JdbcType.BOOLEAN, new BooleanTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.BIT, new BooleanTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.TINYINT, new ByteTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.SMALLINT, new ShortTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.INTEGER, new IntegerTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.FLOAT, new FloatTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.DOUBLE, new DoubleTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.CHAR, new StringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.CLOB, new ClobTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.VARCHAR, new StringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.LONGVARCHAR, new StringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NVARCHAR, new NStringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NCHAR, new NStringTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NCLOB, new NClobTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.BIGINT, new LongTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.REAL, new BigDecimalTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.DECIMAL, new BigDecimalTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.NUMERIC, new BigDecimalTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.BLOB, new BlobInputStreamTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.LONGVARBINARY, new BlobTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.DATE, new DateOnlyTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.TIME, new TimeOnlyTypeHandler()); + handlerRegistry.register(Object.class, JdbcType.TIMESTAMP, new DateTypeHandler()); + + handlerRegistry.register(Object.class, JdbcType.SQLXML, new SqlxmlTypeHandler()); + } + + public void initCustomMybatisInterceptors(Configuration configuration) { + if (customMybatisInterceptors!=null){ + for (Interceptor interceptor :customMybatisInterceptors){ + configuration.addInterceptor(interceptor); + } + } + } + + public void initMyBatisLogSqlExecutionTimePlugin(Configuration configuration) { + configuration.addInterceptor(new LogSqlExecutionTimePlugin()); + } + + public Configuration parseMybatisConfiguration(XMLConfigBuilder parser) { + Configuration configuration = parser.parse(); + + applyCustomMybatisCustomizations(configuration); + return configuration; + } + + protected void applyCustomMybatisCustomizations(Configuration configuration) { + initCustomMybatisMappers(configuration); + + if (dependentEngineMybatisTypeAliasConfigs != null) { + for (MybatisTypeAliasConfigurator typeAliasConfig : dependentEngineMybatisTypeAliasConfigs) { + typeAliasConfig.configure(configuration.getTypeAliasRegistry()); + } + } + if (dependentEngineMybatisTypeHandlerConfigs != null) { + for (MybatisTypeHandlerConfigurator typeHandlerConfig : dependentEngineMybatisTypeHandlerConfigs) { + typeHandlerConfig.configure(configuration.getTypeHandlerRegistry()); + } + } + + parseDependentEngineMybatisXMLMappers(configuration); + parseCustomMybatisXMLMappers(configuration); + } + + public void parseCustomMybatisXMLMappers(Configuration configuration) { + if (getCustomMybatisXMLMappers() != null) { + for (String resource : getCustomMybatisXMLMappers()) { + parseMybatisXmlMapping(configuration, resource); + } + } + } + + public void parseDependentEngineMybatisXMLMappers(Configuration configuration) { + if (getDependentEngineMyBatisXmlMappers() != null) { + for (String resource : getDependentEngineMyBatisXmlMappers()) { + parseMybatisXmlMapping(configuration, resource); + } + } + } + + protected void parseMybatisXmlMapping(Configuration configuration, String resource) { + // see XMLConfigBuilder.mapperElement() + XMLMapperBuilder mapperParser = new XMLMapperBuilder(getResourceAsStream(resource), configuration, resource, configuration.getSqlFragments()); + mapperParser.parse(); + } + + protected InputStream getResourceAsStream(String resource) { + ClassLoader classLoader = getClassLoader(); + if (classLoader != null) { + return getClassLoader().getResourceAsStream(resource); + } else { + return this.getClass().getClassLoader().getResourceAsStream(resource); + } + } + + public void setMybatisMappingFile(String file) { + this.mybatisMappingFile = file; + } + + public String getMybatisMappingFile() { + return mybatisMappingFile; + } + + public abstract InputStream getMyBatisXmlConfigurationStream(); + + public void initConfigurators() { + + allConfigurators = new ArrayList<>(); + allConfigurators.addAll(getEngineSpecificEngineConfigurators()); + + // Configurators that are explicitly added to the config + if (configurators != null) { + allConfigurators.addAll(configurators); + } + + // Auto discovery through ServiceLoader + if (enableConfiguratorServiceLoader) { + ClassLoader classLoader = getClassLoader(); + if (classLoader == null) { + classLoader = ReflectUtil.getClassLoader(); + } + + ServiceLoader configuratorServiceLoader = ServiceLoader.load(EngineConfigurator.class, classLoader); + int nrOfServiceLoadedConfigurators = 0; + for (EngineConfigurator configurator : configuratorServiceLoader) { + allConfigurators.add(configurator); + nrOfServiceLoadedConfigurators++; + } + + if (nrOfServiceLoadedConfigurators > 0) { + logger.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators, nrOfServiceLoadedConfigurators > 1 ? "s" : ""); + } + + if (!allConfigurators.isEmpty()) { + + // Order them according to the priorities (useful for dependent + // configurator) + allConfigurators.sort(new Comparator() { + + @Override + public int compare(EngineConfigurator configurator1, EngineConfigurator configurator2) { + int priority1 = configurator1.getPriority(); + int priority2 = configurator2.getPriority(); + + if (priority1 < priority2) { + return -1; + } else if (priority1 > priority2) { + return 1; + } + return 0; + } + }); + + // Execute the configurators + logger.info("Found {} Engine Configurators in total:", allConfigurators.size()); + for (EngineConfigurator configurator : allConfigurators) { + logger.info("{} (priority:{})", configurator.getClass(), configurator.getPriority()); + } + + } + + } + } + + public void close() { + if (forceCloseMybatisConnectionPool && dataSource instanceof PooledDataSource) { + /* + * When the datasource is created by a Flowable engine (i.e. it's an instance of PooledDataSource), + * the connection pool needs to be closed when closing the engine. + * Note that calling forceCloseAll() multiple times (as is the case when running with multiple engine) is ok. + */ + ((PooledDataSource) dataSource).forceCloseAll(); + } + } + + protected List getEngineSpecificEngineConfigurators() { + // meant to be overridden if needed + return Collections.emptyList(); + } + + public void configuratorsBeforeInit() { + for (EngineConfigurator configurator : allConfigurators) { + logger.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); + configurator.beforeInit(this); + } + } + + public void configuratorsAfterInit() { + for (EngineConfigurator configurator : allConfigurators) { + logger.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority()); + configurator.configure(this); + } + } + + public LockManager getLockManager(String lockName) { + return new LockManagerImpl(commandExecutor, lockName, getLockPollRate(), getEngineCfgKey()); + } + + // getters and setters + // ////////////////////////////////////////////////////// + + public abstract String getEngineName(); + + public ClassLoader getClassLoader() { + return classLoader; + } + + public AbstractEngineConfiguration setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + return this; + } + + public boolean isUseClassForNameClassLoading() { + return useClassForNameClassLoading; + } + + public AbstractEngineConfiguration setUseClassForNameClassLoading(boolean useClassForNameClassLoading) { + this.useClassForNameClassLoading = useClassForNameClassLoading; + return this; + } + + public void addEngineLifecycleListener(EngineLifecycleListener engineLifecycleListener) { + if (this.engineLifecycleListeners == null) { + this.engineLifecycleListeners = new ArrayList<>(); + } + this.engineLifecycleListeners.add(engineLifecycleListener); + } + + public List getEngineLifecycleListeners() { + return engineLifecycleListeners; + } + + public AbstractEngineConfiguration setEngineLifecycleListeners(List engineLifecycleListeners) { + this.engineLifecycleListeners = engineLifecycleListeners; + return this; + } + + public String getDatabaseType() { + return databaseType; + } + + public AbstractEngineConfiguration setDatabaseType(String databaseType) { + this.databaseType = databaseType; + return this; + } + + public DataSource getDataSource() { + return dataSource; + } + + public AbstractEngineConfiguration setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + return this; + } + + public SchemaManager getSchemaManager() { + return schemaManager; + } + + public AbstractEngineConfiguration setSchemaManager(SchemaManager schemaManager) { + this.schemaManager = schemaManager; + return this; + } + + public SchemaManager getCommonSchemaManager() { + return commonSchemaManager; + } + + public AbstractEngineConfiguration setCommonSchemaManager(SchemaManager commonSchemaManager) { + this.commonSchemaManager = commonSchemaManager; + return this; + } + + public Command getSchemaManagementCmd() { + return schemaManagementCmd; + } + + public AbstractEngineConfiguration setSchemaManagementCmd(Command schemaManagementCmd) { + this.schemaManagementCmd = schemaManagementCmd; + return this; + } + + public String getJdbcDriver() { + return jdbcDriver; + } + + public AbstractEngineConfiguration setJdbcDriver(String jdbcDriver) { + this.jdbcDriver = jdbcDriver; + return this; + } + + public String getJdbcUrl() { + return jdbcUrl; + } + + public AbstractEngineConfiguration setJdbcUrl(String jdbcUrl) { + this.jdbcUrl = jdbcUrl; + return this; + } + + public String getJdbcUsername() { + return jdbcUsername; + } + + public AbstractEngineConfiguration setJdbcUsername(String jdbcUsername) { + this.jdbcUsername = jdbcUsername; + return this; + } + + public String getJdbcPassword() { + return jdbcPassword; + } + + public AbstractEngineConfiguration setJdbcPassword(String jdbcPassword) { + this.jdbcPassword = jdbcPassword; + return this; + } + + public int getJdbcMaxActiveConnections() { + return jdbcMaxActiveConnections; + } + + public AbstractEngineConfiguration setJdbcMaxActiveConnections(int jdbcMaxActiveConnections) { + this.jdbcMaxActiveConnections = jdbcMaxActiveConnections; + return this; + } + + public int getJdbcMaxIdleConnections() { + return jdbcMaxIdleConnections; + } + + public AbstractEngineConfiguration setJdbcMaxIdleConnections(int jdbcMaxIdleConnections) { + this.jdbcMaxIdleConnections = jdbcMaxIdleConnections; + return this; + } + + public int getJdbcMaxCheckoutTime() { + return jdbcMaxCheckoutTime; + } + + public AbstractEngineConfiguration setJdbcMaxCheckoutTime(int jdbcMaxCheckoutTime) { + this.jdbcMaxCheckoutTime = jdbcMaxCheckoutTime; + return this; + } + + public int getJdbcMaxWaitTime() { + return jdbcMaxWaitTime; + } + + public AbstractEngineConfiguration setJdbcMaxWaitTime(int jdbcMaxWaitTime) { + this.jdbcMaxWaitTime = jdbcMaxWaitTime; + return this; + } + + public boolean isJdbcPingEnabled() { + return jdbcPingEnabled; + } + + public AbstractEngineConfiguration setJdbcPingEnabled(boolean jdbcPingEnabled) { + this.jdbcPingEnabled = jdbcPingEnabled; + return this; + } + + public int getJdbcPingConnectionNotUsedFor() { + return jdbcPingConnectionNotUsedFor; + } + + public AbstractEngineConfiguration setJdbcPingConnectionNotUsedFor(int jdbcPingConnectionNotUsedFor) { + this.jdbcPingConnectionNotUsedFor = jdbcPingConnectionNotUsedFor; + return this; + } + + public int getJdbcDefaultTransactionIsolationLevel() { + return jdbcDefaultTransactionIsolationLevel; + } + + public AbstractEngineConfiguration setJdbcDefaultTransactionIsolationLevel(int jdbcDefaultTransactionIsolationLevel) { + this.jdbcDefaultTransactionIsolationLevel = jdbcDefaultTransactionIsolationLevel; + return this; + } + + public String getJdbcPingQuery() { + return jdbcPingQuery; + } + + public AbstractEngineConfiguration setJdbcPingQuery(String jdbcPingQuery) { + this.jdbcPingQuery = jdbcPingQuery; + return this; + } + + public String getDataSourceJndiName() { + return dataSourceJndiName; + } + + public AbstractEngineConfiguration setDataSourceJndiName(String dataSourceJndiName) { + this.dataSourceJndiName = dataSourceJndiName; + return this; + } + + public CommandConfig getSchemaCommandConfig() { + return schemaCommandConfig; + } + + public AbstractEngineConfiguration setSchemaCommandConfig(CommandConfig schemaCommandConfig) { + this.schemaCommandConfig = schemaCommandConfig; + return this; + } + + public boolean isTransactionsExternallyManaged() { + return transactionsExternallyManaged; + } + + public AbstractEngineConfiguration setTransactionsExternallyManaged(boolean transactionsExternallyManaged) { + this.transactionsExternallyManaged = transactionsExternallyManaged; + return this; + } + + public Map getBeans() { + return beans; + } + + public AbstractEngineConfiguration setBeans(Map beans) { + this.beans = beans; + return this; + } + + public IdGenerator getIdGenerator() { + return idGenerator; + } + + public AbstractEngineConfiguration setIdGenerator(IdGenerator idGenerator) { + this.idGenerator = idGenerator; + return this; + } + + public boolean isUsePrefixId() { + return usePrefixId; + } + + public AbstractEngineConfiguration setUsePrefixId(boolean usePrefixId) { + this.usePrefixId = usePrefixId; + return this; + } + + public String getXmlEncoding() { + return xmlEncoding; + } + + public AbstractEngineConfiguration setXmlEncoding(String xmlEncoding) { + this.xmlEncoding = xmlEncoding; + return this; + } + + public CommandConfig getDefaultCommandConfig() { + return defaultCommandConfig; + } + + public AbstractEngineConfiguration setDefaultCommandConfig(CommandConfig defaultCommandConfig) { + this.defaultCommandConfig = defaultCommandConfig; + return this; + } + + public CommandExecutor getCommandExecutor() { + return commandExecutor; + } + + public AbstractEngineConfiguration setCommandExecutor(CommandExecutor commandExecutor) { + this.commandExecutor = commandExecutor; + return this; + } + + public CommandContextFactory getCommandContextFactory() { + return commandContextFactory; + } + + public AbstractEngineConfiguration setCommandContextFactory(CommandContextFactory commandContextFactory) { + this.commandContextFactory = commandContextFactory; + return this; + } + + public CommandInterceptor getCommandInvoker() { + return commandInvoker; + } + + public AbstractEngineConfiguration setCommandInvoker(CommandInterceptor commandInvoker) { + this.commandInvoker = commandInvoker; + return this; + } + + public AgendaOperationRunner getAgendaOperationRunner() { + return agendaOperationRunner; + } + + public AbstractEngineConfiguration setAgendaOperationRunner(AgendaOperationRunner agendaOperationRunner) { + this.agendaOperationRunner = agendaOperationRunner; + return this; + } + + public List getCustomPreCommandInterceptors() { + return customPreCommandInterceptors; + } + + public AbstractEngineConfiguration setCustomPreCommandInterceptors(List customPreCommandInterceptors) { + this.customPreCommandInterceptors = customPreCommandInterceptors; + return this; + } + + public List getCustomPostCommandInterceptors() { + return customPostCommandInterceptors; + } + + public AbstractEngineConfiguration setCustomPostCommandInterceptors(List customPostCommandInterceptors) { + this.customPostCommandInterceptors = customPostCommandInterceptors; + return this; + } + + public List getCommandInterceptors() { + return commandInterceptors; + } + + public AbstractEngineConfiguration setCommandInterceptors(List commandInterceptors) { + this.commandInterceptors = commandInterceptors; + return this; + } + + public Map getEngineConfigurations() { + return engineConfigurations; + } + + public AbstractEngineConfiguration setEngineConfigurations(Map engineConfigurations) { + this.engineConfigurations = engineConfigurations; + return this; + } + + public void addEngineConfiguration(String key, String scopeType, AbstractEngineConfiguration engineConfiguration) { + if (engineConfigurations == null) { + engineConfigurations = new HashMap<>(); + } + engineConfigurations.put(key, engineConfiguration); + engineConfigurations.put(scopeType, engineConfiguration); + } + + public Map getServiceConfigurations() { + return serviceConfigurations; + } + + public AbstractEngineConfiguration setServiceConfigurations(Map serviceConfigurations) { + this.serviceConfigurations = serviceConfigurations; + return this; + } + + public void addServiceConfiguration(String key, AbstractServiceConfiguration serviceConfiguration) { + if (serviceConfigurations == null) { + serviceConfigurations = new HashMap<>(); + } + serviceConfigurations.put(key, serviceConfiguration); + } + + public Map getEventRegistryEventConsumers() { + return eventRegistryEventConsumers; + } + + public AbstractEngineConfiguration setEventRegistryEventConsumers(Map eventRegistryEventConsumers) { + this.eventRegistryEventConsumers = eventRegistryEventConsumers; + return this; + } + + public void addEventRegistryEventConsumer(String key, EventRegistryEventConsumer eventRegistryEventConsumer) { + if (eventRegistryEventConsumers == null) { + eventRegistryEventConsumers = new HashMap<>(); + } + eventRegistryEventConsumers.put(key, eventRegistryEventConsumer); + } + + public AbstractEngineConfiguration setDefaultCommandInterceptors(Collection defaultCommandInterceptors) { + this.defaultCommandInterceptors = defaultCommandInterceptors; + return this; + } + + public SqlSessionFactory getSqlSessionFactory() { + return sqlSessionFactory; + } + + public AbstractEngineConfiguration setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { + this.sqlSessionFactory = sqlSessionFactory; + return this; + } + + public boolean isDbHistoryUsed() { + return isDbHistoryUsed; + } + + public AbstractEngineConfiguration setDbHistoryUsed(boolean isDbHistoryUsed) { + this.isDbHistoryUsed = isDbHistoryUsed; + return this; + } + + public DbSqlSessionFactory getDbSqlSessionFactory() { + return dbSqlSessionFactory; + } + + public AbstractEngineConfiguration setDbSqlSessionFactory(DbSqlSessionFactory dbSqlSessionFactory) { + this.dbSqlSessionFactory = dbSqlSessionFactory; + return this; + } + + public TransactionFactory getTransactionFactory() { + return transactionFactory; + } + + public AbstractEngineConfiguration setTransactionFactory(TransactionFactory transactionFactory) { + this.transactionFactory = transactionFactory; + return this; + } + + public TransactionContextFactory getTransactionContextFactory() { + return transactionContextFactory; + } + + public AbstractEngineConfiguration setTransactionContextFactory(TransactionContextFactory transactionContextFactory) { + this.transactionContextFactory = transactionContextFactory; + return this; + } + + public int getMaxNrOfStatementsInBulkInsert() { + return maxNrOfStatementsInBulkInsert; + } + + public AbstractEngineConfiguration setMaxNrOfStatementsInBulkInsert(int maxNrOfStatementsInBulkInsert) { + this.maxNrOfStatementsInBulkInsert = maxNrOfStatementsInBulkInsert; + return this; + } + + public boolean isBulkInsertEnabled() { + return isBulkInsertEnabled; + } + + public AbstractEngineConfiguration setBulkInsertEnabled(boolean isBulkInsertEnabled) { + this.isBulkInsertEnabled = isBulkInsertEnabled; + return this; + } + + public Set> getCustomMybatisMappers() { + return customMybatisMappers; + } + + public AbstractEngineConfiguration setCustomMybatisMappers(Set> customMybatisMappers) { + this.customMybatisMappers = customMybatisMappers; + return this; + } + + public Set getCustomMybatisXMLMappers() { + return customMybatisXMLMappers; + } + + public AbstractEngineConfiguration setCustomMybatisXMLMappers(Set customMybatisXMLMappers) { + this.customMybatisXMLMappers = customMybatisXMLMappers; + return this; + } + + public Set getDependentEngineMyBatisXmlMappers() { + return dependentEngineMyBatisXmlMappers; + } + + public AbstractEngineConfiguration setCustomMybatisInterceptors(List customMybatisInterceptors) { + this.customMybatisInterceptors = customMybatisInterceptors; + return this; + } + + public List getCustomMybatisInterceptors() { + return customMybatisInterceptors; + } + + public AbstractEngineConfiguration setDependentEngineMyBatisXmlMappers(Set dependentEngineMyBatisXmlMappers) { + this.dependentEngineMyBatisXmlMappers = dependentEngineMyBatisXmlMappers; + return this; + } + + public List getDependentEngineMybatisTypeAliasConfigs() { + return dependentEngineMybatisTypeAliasConfigs; + } + + public AbstractEngineConfiguration setDependentEngineMybatisTypeAliasConfigs(List dependentEngineMybatisTypeAliasConfigs) { + this.dependentEngineMybatisTypeAliasConfigs = dependentEngineMybatisTypeAliasConfigs; + return this; + } + + public List getDependentEngineMybatisTypeHandlerConfigs() { + return dependentEngineMybatisTypeHandlerConfigs; + } + + public AbstractEngineConfiguration setDependentEngineMybatisTypeHandlerConfigs(List dependentEngineMybatisTypeHandlerConfigs) { + this.dependentEngineMybatisTypeHandlerConfigs = dependentEngineMybatisTypeHandlerConfigs; + return this; + } + + public List getCustomSessionFactories() { + return customSessionFactories; + } + + public AbstractEngineConfiguration addCustomSessionFactory(SessionFactory sessionFactory) { + if (customSessionFactories == null) { + customSessionFactories = new ArrayList<>(); + } + customSessionFactories.add(sessionFactory); + return this; + } + + public AbstractEngineConfiguration setCustomSessionFactories(List customSessionFactories) { + this.customSessionFactories = customSessionFactories; + return this; + } + + public boolean isUsingRelationalDatabase() { + return usingRelationalDatabase; + } + + public AbstractEngineConfiguration setUsingRelationalDatabase(boolean usingRelationalDatabase) { + this.usingRelationalDatabase = usingRelationalDatabase; + return this; + } + + public boolean isUsingSchemaMgmt() { + return usingSchemaMgmt; + } + + public AbstractEngineConfiguration setUsingSchemaMgmt(boolean usingSchema) { + this.usingSchemaMgmt = usingSchema; + return this; + } + + public String getDatabaseTablePrefix() { + return databaseTablePrefix; + } + + public AbstractEngineConfiguration setDatabaseTablePrefix(String databaseTablePrefix) { + this.databaseTablePrefix = databaseTablePrefix; + return this; + } + + public String getDatabaseWildcardEscapeCharacter() { + return databaseWildcardEscapeCharacter; + } + + public AbstractEngineConfiguration setDatabaseWildcardEscapeCharacter(String databaseWildcardEscapeCharacter) { + this.databaseWildcardEscapeCharacter = databaseWildcardEscapeCharacter; + return this; + } + + public String getDatabaseCatalog() { + return databaseCatalog; + } + + public AbstractEngineConfiguration setDatabaseCatalog(String databaseCatalog) { + this.databaseCatalog = databaseCatalog; + return this; + } + + public String getDatabaseSchema() { + return databaseSchema; + } + + public AbstractEngineConfiguration setDatabaseSchema(String databaseSchema) { + this.databaseSchema = databaseSchema; + return this; + } + + public boolean isTablePrefixIsSchema() { + return tablePrefixIsSchema; + } + + public AbstractEngineConfiguration setTablePrefixIsSchema(boolean tablePrefixIsSchema) { + this.tablePrefixIsSchema = tablePrefixIsSchema; + return this; + } + + public boolean isAlwaysLookupLatestDefinitionVersion() { + return alwaysLookupLatestDefinitionVersion; + } + + public AbstractEngineConfiguration setAlwaysLookupLatestDefinitionVersion(boolean alwaysLookupLatestDefinitionVersion) { + this.alwaysLookupLatestDefinitionVersion = alwaysLookupLatestDefinitionVersion; + return this; + } + + public boolean isFallbackToDefaultTenant() { + return fallbackToDefaultTenant; + } + + public AbstractEngineConfiguration setFallbackToDefaultTenant(boolean fallbackToDefaultTenant) { + this.fallbackToDefaultTenant = fallbackToDefaultTenant; + return this; + } + + /** + * @return name of the default tenant + * @deprecated use {@link AbstractEngineConfiguration#getDefaultTenantProvider()} instead + */ + @Deprecated + public String getDefaultTenantValue() { + return getDefaultTenantProvider().getDefaultTenant(null, null, null); + } + + public AbstractEngineConfiguration setDefaultTenantValue(String defaultTenantValue) { + this.defaultTenantProvider = (tenantId, scope, scopeKey) -> defaultTenantValue; + return this; + } + + public DefaultTenantProvider getDefaultTenantProvider() { + return defaultTenantProvider; + } + + public AbstractEngineConfiguration setDefaultTenantProvider(DefaultTenantProvider defaultTenantProvider) { + this.defaultTenantProvider = defaultTenantProvider; + return this; + } + + public boolean isEnableLogSqlExecutionTime() { + return enableLogSqlExecutionTime; + } + + public void setEnableLogSqlExecutionTime(boolean enableLogSqlExecutionTime) { + this.enableLogSqlExecutionTime = enableLogSqlExecutionTime; + } + + public Map, SessionFactory> getSessionFactories() { + return sessionFactories; + } + + public AbstractEngineConfiguration setSessionFactories(Map, SessionFactory> sessionFactories) { + this.sessionFactories = sessionFactories; + return this; + } + + public String getDatabaseSchemaUpdate() { + return databaseSchemaUpdate; + } + + public AbstractEngineConfiguration setDatabaseSchemaUpdate(String databaseSchemaUpdate) { + this.databaseSchemaUpdate = databaseSchemaUpdate; + return this; + } + + public boolean isUseLockForDatabaseSchemaUpdate() { + return useLockForDatabaseSchemaUpdate; + } + + public AbstractEngineConfiguration setUseLockForDatabaseSchemaUpdate(boolean useLockForDatabaseSchemaUpdate) { + this.useLockForDatabaseSchemaUpdate = useLockForDatabaseSchemaUpdate; + return this; + } + + public boolean isEnableEventDispatcher() { + return enableEventDispatcher; + } + + public AbstractEngineConfiguration setEnableEventDispatcher(boolean enableEventDispatcher) { + this.enableEventDispatcher = enableEventDispatcher; + return this; + } + + public FlowableEventDispatcher getEventDispatcher() { + return eventDispatcher; + } + + public AbstractEngineConfiguration setEventDispatcher(FlowableEventDispatcher eventDispatcher) { + this.eventDispatcher = eventDispatcher; + return this; + } + + public List getEventListeners() { + return eventListeners; + } + + public AbstractEngineConfiguration setEventListeners(List eventListeners) { + this.eventListeners = eventListeners; + return this; + } + + public Map> getTypedEventListeners() { + return typedEventListeners; + } + + public AbstractEngineConfiguration setTypedEventListeners(Map> typedEventListeners) { + this.typedEventListeners = typedEventListeners; + return this; + } + + public List getAdditionalEventDispatchActions() { + return additionalEventDispatchActions; + } + + public AbstractEngineConfiguration setAdditionalEventDispatchActions(List additionalEventDispatchActions) { + this.additionalEventDispatchActions = additionalEventDispatchActions; + return this; + } + + public void initEventDispatcher() { + if (this.eventDispatcher == null) { + this.eventDispatcher = new FlowableEventDispatcherImpl(); + } + + initAdditionalEventDispatchActions(); + + this.eventDispatcher.setEnabled(enableEventDispatcher); + + initEventListeners(); + initTypedEventListeners(); + } + + protected void initEventListeners() { + if (eventListeners != null) { + for (FlowableEventListener listenerToAdd : eventListeners) { + this.eventDispatcher.addEventListener(listenerToAdd); + } + } + } + + protected void initAdditionalEventDispatchActions() { + if (this.additionalEventDispatchActions == null) { + this.additionalEventDispatchActions = new ArrayList<>(); + } + } + + protected void initTypedEventListeners() { + if (typedEventListeners != null) { + for (Map.Entry> listenersToAdd : typedEventListeners.entrySet()) { + // Extract types from the given string + FlowableEngineEventType[] types = FlowableEngineEventType.getTypesFromString(listenersToAdd.getKey()); + + for (FlowableEventListener listenerToAdd : listenersToAdd.getValue()) { + this.eventDispatcher.addEventListener(listenerToAdd, types); + } + } + } + } + + public boolean isLoggingSessionEnabled() { + return loggingListener != null; + } + + public LoggingListener getLoggingListener() { + return loggingListener; + } + + public void setLoggingListener(LoggingListener loggingListener) { + this.loggingListener = loggingListener; + } + + public Clock getClock() { + return clock; + } + + public AbstractEngineConfiguration setClock(Clock clock) { + this.clock = clock; + return this; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public AbstractEngineConfiguration setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + return this; + } + + public int getMaxLengthString() { + if (maxLengthStringVariableType == -1) { + if ("oracle".equalsIgnoreCase(databaseType)) { + return DEFAULT_ORACLE_MAX_LENGTH_STRING; + } else { + return DEFAULT_GENERIC_MAX_LENGTH_STRING; + } + } else { + return maxLengthStringVariableType; + } + } + + public int getMaxLengthStringVariableType() { + return maxLengthStringVariableType; + } + + public AbstractEngineConfiguration setMaxLengthStringVariableType(int maxLengthStringVariableType) { + this.maxLengthStringVariableType = maxLengthStringVariableType; + return this; + } + + public PropertyDataManager getPropertyDataManager() { + return propertyDataManager; + } + + public Duration getLockPollRate() { + return lockPollRate; + } + + public AbstractEngineConfiguration setLockPollRate(Duration lockPollRate) { + this.lockPollRate = lockPollRate; + return this; + } + + public Duration getSchemaLockWaitTime() { + return schemaLockWaitTime; + } + + public void setSchemaLockWaitTime(Duration schemaLockWaitTime) { + this.schemaLockWaitTime = schemaLockWaitTime; + } + + public AbstractEngineConfiguration setPropertyDataManager(PropertyDataManager propertyDataManager) { + this.propertyDataManager = propertyDataManager; + return this; + } + + public PropertyEntityManager getPropertyEntityManager() { + return propertyEntityManager; + } + + public AbstractEngineConfiguration setPropertyEntityManager(PropertyEntityManager propertyEntityManager) { + this.propertyEntityManager = propertyEntityManager; + return this; + } + + public ByteArrayDataManager getByteArrayDataManager() { + return byteArrayDataManager; + } + + public AbstractEngineConfiguration setByteArrayDataManager(ByteArrayDataManager byteArrayDataManager) { + this.byteArrayDataManager = byteArrayDataManager; + return this; + } + + public ByteArrayEntityManager getByteArrayEntityManager() { + return byteArrayEntityManager; + } + + public AbstractEngineConfiguration setByteArrayEntityManager(ByteArrayEntityManager byteArrayEntityManager) { + this.byteArrayEntityManager = byteArrayEntityManager; + return this; + } + + public TableDataManager getTableDataManager() { + return tableDataManager; + } + + public AbstractEngineConfiguration setTableDataManager(TableDataManager tableDataManager) { + this.tableDataManager = tableDataManager; + return this; + } + + public List getDeployers() { + return deployers; + } + + public AbstractEngineConfiguration setDeployers(List deployers) { + this.deployers = deployers; + return this; + } + + public List getCustomPreDeployers() { + return customPreDeployers; + } + + public AbstractEngineConfiguration setCustomPreDeployers(List customPreDeployers) { + this.customPreDeployers = customPreDeployers; + return this; + } + + public List getCustomPostDeployers() { + return customPostDeployers; + } + + public AbstractEngineConfiguration setCustomPostDeployers(List customPostDeployers) { + this.customPostDeployers = customPostDeployers; + return this; + } + + public boolean isEnableConfiguratorServiceLoader() { + return enableConfiguratorServiceLoader; + } + + public AbstractEngineConfiguration setEnableConfiguratorServiceLoader(boolean enableConfiguratorServiceLoader) { + this.enableConfiguratorServiceLoader = enableConfiguratorServiceLoader; + return this; + } + + public List getConfigurators() { + return configurators; + } + + public AbstractEngineConfiguration addConfigurator(EngineConfigurator configurator) { + if (configurators == null) { + configurators = new ArrayList<>(); + } + configurators.add(configurator); + return this; + } + + /** + * @return All {@link EngineConfigurator} instances. Will only contain values after init of the engine. + * Use the {@link #getConfigurators()} or {@link #addConfigurator(EngineConfigurator)} methods otherwise. + */ + public List getAllConfigurators() { + return allConfigurators; + } + + public AbstractEngineConfiguration setConfigurators(List configurators) { + this.configurators = configurators; + return this; + } + + public EngineConfigurator getIdmEngineConfigurator() { + return idmEngineConfigurator; + } + + public AbstractEngineConfiguration setIdmEngineConfigurator(EngineConfigurator idmEngineConfigurator) { + this.idmEngineConfigurator = idmEngineConfigurator; + return this; + } + + public EngineConfigurator getEventRegistryConfigurator() { + return eventRegistryConfigurator; + } + + public AbstractEngineConfiguration setEventRegistryConfigurator(EngineConfigurator eventRegistryConfigurator) { + this.eventRegistryConfigurator = eventRegistryConfigurator; + return this; + } + + public AbstractEngineConfiguration setForceCloseMybatisConnectionPool(boolean forceCloseMybatisConnectionPool) { + this.forceCloseMybatisConnectionPool = forceCloseMybatisConnectionPool; + return this; + } + + public boolean isForceCloseMybatisConnectionPool() { + return forceCloseMybatisConnectionPool; + } +} diff --git a/sql/dm/flowable-patch/src/main/resources/META-INF/package-info.md b/sql/dm/flowable-patch/src/main/resources/META-INF/package-info.md new file mode 100644 index 000000000..1932c7a3f --- /dev/null +++ b/sql/dm/flowable-patch/src/main/resources/META-INF/package-info.md @@ -0,0 +1 @@ +防止IDEA将`.`和`/`混为一谈 \ No newline at end of file diff --git a/sql/dm/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database b/sql/dm/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database new file mode 100644 index 000000000..efbcfcca2 --- /dev/null +++ b/sql/dm/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database @@ -0,0 +1,21 @@ +liquibase.database.core.CockroachDatabase +liquibase.database.core.DB2Database +liquibase.database.core.Db2zDatabase +liquibase.database.core.DerbyDatabase +liquibase.database.core.Firebird3Database +liquibase.database.core.FirebirdDatabase +liquibase.database.core.H2Database +liquibase.database.core.HsqlDatabase +liquibase.database.core.InformixDatabase +liquibase.database.core.Ingres9Database +liquibase.database.core.MSSQLDatabase +liquibase.database.core.MariaDBDatabase +liquibase.database.core.MockDatabase +liquibase.database.core.MySQLDatabase +liquibase.database.core.OracleDatabase +liquibase.database.core.PostgresDatabase +liquibase.database.core.SQLiteDatabase +liquibase.database.core.SybaseASADatabase +liquibase.database.core.SybaseDatabase +liquibase.database.core.DmDatabase +liquibase.database.core.UnsupportedDatabase diff --git a/sql/dm/ruoyi-vue-pro-dm8.sql b/sql/dm/ruoyi-vue-pro-dm8.sql index 8128c647e..e5369739e 100644 --- a/sql/dm/ruoyi-vue-pro-dm8.sql +++ b/sql/dm/ruoyi-vue-pro-dm8.sql @@ -3941,7 +3941,7 @@ CREATE TABLE "RUOYI_VUE_PRO"."SYSTEM_TENANT" "CONTACT_MOBILE" VARCHAR(500) NULL, "STATUS" TINYINT DEFAULT 0 NOT NULL, - "DOMAIN" VARCHAR(256) DEFAULT '' + "WEBSITE" VARCHAR(256) DEFAULT '' NULL, "PACKAGE_ID" BIGINT NOT NULL, "EXPIRE_TIME" TIMESTAMP(0) NOT NULL, @@ -4943,9 +4943,9 @@ SET IDENTITY_INSERT "RUOYI_VUE_PRO"."SYSTEM_SOCIAL_USER" OFF; SET IDENTITY_INSERT "RUOYI_VUE_PRO"."SYSTEM_SOCIAL_USER_BIND" ON; SET IDENTITY_INSERT "RUOYI_VUE_PRO"."SYSTEM_SOCIAL_USER_BIND" OFF; SET IDENTITY_INSERT "RUOYI_VUE_PRO"."SYSTEM_TENANT" ON; -INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_TENANT"("ID","NAME","CONTACT_USER_ID","CONTACT_NAME","CONTACT_MOBILE","STATUS","DOMAIN","PACKAGE_ID","EXPIRE_TIME","ACCOUNT_COUNT","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(1,'芋道源码',null,'芋艿','17321315478',0,'https://www.iocoder.cn',0,'2099-02-19 17:14:16',9999,'1','2021-01-05 17:03:47','1','2022-02-23 12:15:11',0); -INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_TENANT"("ID","NAME","CONTACT_USER_ID","CONTACT_NAME","CONTACT_MOBILE","STATUS","DOMAIN","PACKAGE_ID","EXPIRE_TIME","ACCOUNT_COUNT","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(121,'小租户',110,'小王2','15601691300',0,'http://www.iocoder.cn',111,'2024-03-11 00:00:00',20,'1','2022-02-22 00:56:14','1','2022-05-17 10:03:59',0); -INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_TENANT"("ID","NAME","CONTACT_USER_ID","CONTACT_NAME","CONTACT_MOBILE","STATUS","DOMAIN","PACKAGE_ID","EXPIRE_TIME","ACCOUNT_COUNT","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(122,'测试租户',113,'芋道','15601691300',0,'https://www.iocoder.cn',111,'2022-04-30 00:00:00',50,'1','2022-03-07 21:37:58','1','2022-03-07 21:37:58',0); +INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_TENANT"("ID","NAME","CONTACT_USER_ID","CONTACT_NAME","CONTACT_MOBILE","STATUS","WEBSITE","PACKAGE_ID","EXPIRE_TIME","ACCOUNT_COUNT","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(1,'芋道源码',null,'芋艿','17321315478',0,'https://www.iocoder.cn',0,'2099-02-19 17:14:16',9999,'1','2021-01-05 17:03:47','1','2022-02-23 12:15:11',0); +INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_TENANT"("ID","NAME","CONTACT_USER_ID","CONTACT_NAME","CONTACT_MOBILE","STATUS","WEBSITE","PACKAGE_ID","EXPIRE_TIME","ACCOUNT_COUNT","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(121,'小租户',110,'小王2','15601691300',0,'http://www.iocoder.cn',111,'2024-03-11 00:00:00',20,'1','2022-02-22 00:56:14','1','2022-05-17 10:03:59',0); +INSERT INTO "RUOYI_VUE_PRO"."SYSTEM_TENANT"("ID","NAME","CONTACT_USER_ID","CONTACT_NAME","CONTACT_MOBILE","STATUS","WEBSITE","PACKAGE_ID","EXPIRE_TIME","ACCOUNT_COUNT","CREATOR","CREATE_TIME","UPDATER","UPDATE_TIME","DELETED") VALUES(122,'测试租户',113,'芋道','15601691300',0,'https://www.iocoder.cn',111,'2022-04-30 00:00:00',50,'1','2022-03-07 21:37:58','1','2022-03-07 21:37:58',0); SET IDENTITY_INSERT "RUOYI_VUE_PRO"."SYSTEM_TENANT" OFF; SET IDENTITY_INSERT "RUOYI_VUE_PRO"."SYSTEM_TENANT_PACKAGE" ON; @@ -5674,7 +5674,7 @@ COMMENT ON COLUMN "RUOYI_VUE_PRO"."SYSTEM_TENANT"."CONTACT_MOBILE" IS '联系手 COMMENT ON COLUMN "RUOYI_VUE_PRO"."SYSTEM_TENANT"."STATUS" IS '租户状态(0正常 1停用)'; -COMMENT ON COLUMN "RUOYI_VUE_PRO"."SYSTEM_TENANT"."DOMAIN" IS '绑定域名'; +COMMENT ON COLUMN "RUOYI_VUE_PRO"."SYSTEM_TENANT"."WEBSITE" IS '绑定域名'; COMMENT ON COLUMN "RUOYI_VUE_PRO"."SYSTEM_TENANT"."PACKAGE_ID" IS '租户套餐编号'; diff --git a/sql/mysql/optinal/crm.sql b/sql/mysql/optinal/crm.sql new file mode 100644 index 000000000..135826585 --- /dev/null +++ b/sql/mysql/optinal/crm.sql @@ -0,0 +1,3 @@ +SET NAMES utf8mb4; +-- `ruoyi-vue-pro`.crm_contact definition + diff --git a/sql/mysql/optinal/crm_data.sql b/sql/mysql/optinal/crm_data.sql new file mode 100644 index 000000000..b5be1e691 --- /dev/null +++ b/sql/mysql/optinal/crm_data.sql @@ -0,0 +1,20 @@ + +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (184, '回款管理审批状态', 'crm_receivable_check_status', 0, '回款管理审批状态(0 未审核 1 审核通过 2 审核拒绝 3 审核中 4 已撤回)', '1', '2023-10-18 21:44:24', '1', '2023-10-18 21:44:24', b'0', '1970-01-01 00:00:00'); + +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (185, '回款管理-回款方式', 'crm_return_type', 0, '回款管理-回款方式', '1', '2023-10-18 21:54:10', '1', '2023-10-18 21:54:10', b'0', '1970-01-01 00:00:00'); + + +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1389, 0, '未审核', '0', 'crm_receivable_check_status', 0, 'default', '', '0 未审核 ', '1', '2023-10-18 21:46:00', '1', '2023-10-18 21:47:16', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1390, 1, '审核通过', '1', 'crm_receivable_check_status', 0, 'default', '', '1 审核通过', '1', '2023-10-18 21:46:18', '1', '2023-10-18 21:47:08', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1391, 2, '审核拒绝', '2', 'crm_receivable_check_status', 0, 'default', '', ' 2 审核拒绝', '1', '2023-10-18 21:46:58', '1', '2023-10-18 21:47:21', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1392, 3, '审核中', '3', 'crm_receivable_check_status', 0, 'default', '', ' 3 审核中', '1', '2023-10-18 21:47:35', '1', '2023-10-18 21:47:35', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1393, 4, '已撤回', '4', 'crm_receivable_check_status', 0, 'default', '', ' 4 已撤回', '1', '2023-10-18 21:47:46', '1', '2023-10-18 21:47:46', b'0'); + +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1394, 1, '支票', '1', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:29', '1', '2023-10-18 21:54:29', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1395, 2, '现金', '2', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:41', '1', '2023-10-18 21:54:41', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1396, 3, '邮政汇款', '3', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:53', '1', '2023-10-18 21:54:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1397, 4, '电汇', '4', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:07', '1', '2023-10-18 21:55:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1398, 5, '网上转账', '5', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:24', '1', '2023-10-18 21:55:24', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1399, 6, '支付宝', '6', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:38', '1', '2023-10-18 21:55:38', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1400, 7, '微信支付', '7', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:53', '1', '2023-10-18 21:55:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1401, 8, '其他', '8', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:56:06', '1', '2023-10-18 21:56:06', b'0'); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/null/.gitkeep b/sql/mysql/optinal/crm_menu.sql similarity index 100% rename from yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/null/.gitkeep rename to sql/mysql/optinal/crm_menu.sql diff --git a/sql/mysql/optinal/mall.sql b/sql/mysql/optinal/mall.sql new file mode 100644 index 000000000..e69de29bb diff --git a/sql/mysql/pay_wallet.sql b/sql/mysql/optinal/pay_wallet.sql similarity index 56% rename from sql/mysql/pay_wallet.sql rename to sql/mysql/optinal/pay_wallet.sql index e69b97b7b..1e9f1d255 100644 --- a/sql/mysql/pay_wallet.sql +++ b/sql/mysql/optinal/pay_wallet.sql @@ -5,18 +5,26 @@ DROP TABLE IF EXISTS `pay_transfer`; CREATE TABLE `pay_transfer` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `type` int NOT NULL COMMENT '类型', + `no` varchar(64) NOT NULL COMMENT '转账单号', `app_id` bigint NOT NULL COMMENT '应用编号', - `merchant_order_id` varchar(64) NOT NULL COMMENT '商户订单编号', - `price` int NOT NULL COMMENT '转账金额,单位:分', - `subject` varchar(512) NOT NULL COMMENT '转账标题', - `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同', + `channel_id` bigint NOT NULL COMMENT '转账渠道编号', + `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码', + `merchant_transfer_id` varchar(64) NOT NULL COMMENT '商户转账单编号', + `type` int NOT NULL COMMENT '类型', `status` tinyint NOT NULL COMMENT '转账状态', `success_time` datetime NULL COMMENT '转账成功时间', - `extension_id` bigint NULL COMMENT '转账渠道编号', - `no` varchar(64) NULL COMMENT '转账单号', - `channel_id` bigint NULL COMMENT '转账渠道编号', - `channel_code` varchar(32) NULL COMMENT '转账渠道编码', + `price` int NOT NULL COMMENT '转账金额,单位:分', + `subject` varchar(512) NOT NULL COMMENT '转账标题', + `user_name` varchar(64) NULL COMMENT '收款人姓名', + `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号', + `openid` varchar(64) NULL COMMENT '微信 openId', + `notify_url` varchar(1024) NOT NULL COMMENT '异步通知商户地址', + `user_ip` varchar(50) NOT NULL COMMENT '用户 IP', + `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '渠道的额外参数', + `channel_transfer_no` varchar(64) NULL DEFAULT NULL COMMENT '渠道转账单号', + `channel_error_code` varchar(128) NULL DEFAULT NULL COMMENT '调用渠道的错误码', + `channel_error_msg` varchar(256) NULL DEFAULT NULL COMMENT '调用渠道的错误提示', + `channel_notify_data` varchar(4096) NULL DEFAULT NULL COMMENT '渠道的同步/异步通知的内容', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', @@ -26,39 +34,18 @@ CREATE TABLE `pay_transfer` PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB COMMENT='转账单表'; --- ---------------------------- --- 转账扩展单 --- ---------------------------- -DROP TABLE IF EXISTS `pay_transfer_extension`; -CREATE TABLE `pay_transfer_extension` -( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `no` varchar(64) NOT NULL COMMENT '转账单号', - `transfer_id` bigint NOT NULL COMMENT '转账单编号', - `channel_id` bigint NOT NULL COMMENT '转账渠道编号', - `channel_code` varchar(32) NOT NULL COMMENT '转账渠道编码', - `channel_extras` varchar(512) NULL DEFAULT NULL COMMENT '支付渠道的额外参数', - `status` tinyint NOT NULL COMMENT '转账状态', - `channel_notify_data` varchar(4096) NULL DEFAULT NULL COMMENT '支付渠道异步通知的内容', - `creator` varchar(64) NULL DEFAULT '' COMMENT '创建者', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) NULL DEFAULT '' COMMENT '更新者', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB COMMENT='转账拓展单表'; - -- ---------------------------- -- Table structure for pay_demo_transfer -- ---------------------------- DROP TABLE IF EXISTS `pay_demo_transfer`; CREATE TABLE `pay_demo_transfer` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单编号', - `user_id` bigint UNSIGNED NOT NULL COMMENT '用户编号', - `price` int NOT NULL COMMENT '转账金额,单位:分', + `app_id` bigint NOT NULL COMMENT '应用编号', `type` int NOT NULL COMMENT '转账类型', - `payee_info` varchar(512) NOT NULL COMMENT '收款人信息,不同类型和渠道不同', + `price` int NOT NULL COMMENT '转账金额,单位:分', + `user_name` varchar(64) NULL COMMENT '收款人姓名', + `alipay_logon_id` varchar(64) NULL COMMENT '支付宝登录号', + `openid` varchar(64) NULL COMMENT '微信 openId', `transfer_status` tinyint NOT NULL DEFAULT 0 COMMENT '转账状态', `pay_transfer_id` bigint NULL DEFAULT NULL COMMENT '转账订单编号', `pay_channel_code` varchar(16) NULL DEFAULT NULL COMMENT '转账支付成功渠道', @@ -70,11 +57,11 @@ CREATE TABLE `pay_demo_transfer` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB COMMENT = '示例业务转账订单\n'; +) ENGINE = InnoDB COMMENT = '示例业务转账订单'; -ALTER TABLE `pay_channel` - MODIFY COLUMN `config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置' AFTER `app_id`; +-- ALTER TABLE `pay_channel` +-- MODIFY COLUMN `config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付渠道配置' AFTER `app_id`; -- ---------------------------- -- 充值套餐表 @@ -203,3 +190,67 @@ VALUES ( '', '', '', 0 ); +-- 支付实战和转账实战数据库脚本 + +update system_menu set deleted = 1 where id = 2161; + +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '接入示例', '', 1, 99, 1117, + 'demo', 'ep:caret-right', '', 0, '' + ); + +SELECT @parentId1 := LAST_INSERT_ID(); + +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '支付实战', '', 2, 1, @parentId1, + 'demo-order', 'fa:leaf', 'pay/demo/order/index', 0, NULL + ); + +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '转账实战', '', 2, 1, @parentId1, + 'demo-transfer', 'fa:leaf', 'pay/demo/transfer/index', 0, NULL + ); + +-- 转账状态和转账类型数据字典 +INSERT INTO `system_dict_type`(`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES ('支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type`(`name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES ('转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', b'0', '1970-01-01 00:00:00'); + +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '钱包余额', '4', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:37', '1', '2023-10-28 16:28:37', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, '银行卡', '3', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:28:21', '1', '2023-10-28 16:28:21', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '微信余额', '2', 'pay_transfer_type', 0, 'info', '', '', '1', '2023-10-28 16:28:07', '1', '2023-10-28 16:28:07', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '支付宝余额', '1', 'pay_transfer_type', 0, 'default', '', '', '1', '2023-10-28 16:27:44', '1', '2023-10-28 16:27:44', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (4, '转账失败', '30', 'pay_transfer_status', 0, 'warning', '', '', '1', '2023-10-28 16:24:16', '1', '2023-10-28 16:24:16', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23:12', b'0'); +INSERT INTO `system_dict_data`(`sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23:22', b'0'); + +-- 转账订单菜单脚本 + +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '转账订单', '', 2, 3, 1117, + 'transfer', 'ep:credit-card', 'pay/transfer/index', 0, 'PayTransfer' + ); + +-- 转账通知脚本 + +ALTER TABLE `pay_app` + ADD COLUMN `transfer_notify_url` varchar(1024) NOT NULL COMMENT '转账结果的回调地址' AFTER `refund_notify_url`; +ALTER TABLE `pay_notify_task` + MODIFY COLUMN `merchant_order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '商户订单编号' AFTER `status`, + ADD COLUMN `merchant_transfer_id` varchar(64) COMMENT '商户转账单编号' AFTER `merchant_order_id`; \ No newline at end of file diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index f93b87120..50ae2fbd3 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -3,15 +3,15 @@ Source Server : 127.0.0.1 MySQL Source Server Type : MySQL - Source Server Version : 80034 - Source Host : localhost:3306 + Source Server Version : 80200 (8.2.0) + Source Host : 127.0.0.1:3306 Source Schema : ruoyi-vue-pro Target Server Type : MySQL - Target Server Version : 80034 + Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 04/11/2023 20:42:49 + Date: 30/11/2023 21:13:06 */ SET NAMES utf8mb4; @@ -385,7 +385,7 @@ CREATE TABLE `infra_api_error_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1781 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 2018 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -423,7 +423,7 @@ CREATE TABLE `infra_codegen_column` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1804 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 2000 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; -- ---------------------------- -- Records of infra_codegen_column @@ -450,13 +450,18 @@ CREATE TABLE `infra_codegen_table` ( `template_type` tinyint NOT NULL DEFAULT 1 COMMENT '模板类型', `front_type` tinyint NOT NULL COMMENT '前端类型', `parent_menu_id` bigint NULL DEFAULT NULL COMMENT '父菜单编号', + `master_table_id` bigint NULL DEFAULT NULL COMMENT '主表的编号', + `sub_join_column_id` bigint NULL DEFAULT NULL COMMENT '子表关联主表的字段编号', + `sub_join_many` bit(1) NULL DEFAULT NULL COMMENT '主表与子表是否一对多', + `tree_parent_column_id` bigint NULL DEFAULT NULL COMMENT '树表的父字段编号', + `tree_name_column_id` bigint NULL DEFAULT NULL COMMENT '树表的名字字段编号', `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 136 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 155 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; -- ---------------------------- -- Records of infra_codegen_table @@ -521,6 +526,151 @@ CREATE TABLE `infra_data_source_config` ( BEGIN; COMMIT; +-- ---------------------------- +-- Table structure for infra_demo01_contact +-- ---------------------------- +DROP TABLE IF EXISTS `infra_demo01_contact`; +CREATE TABLE `infra_demo01_contact` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', + `sex` tinyint(1) NOT NULL COMMENT '性别', + `birthday` datetime NOT NULL COMMENT '出生年', + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '简介', + `avatar` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '示例联系人表'; + +-- ---------------------------- +-- Records of infra_demo01_contact +-- ---------------------------- +BEGIN; +INSERT INTO `infra_demo01_contact` (`id`, `name`, `sex`, `birthday`, `description`, `avatar`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '土豆', 2, '2023-11-07 00:00:00', '

天蚕土豆!呀

', 'http://127.0.0.1:48080/admin-api/infra/file/4/get/46f8fa1a37db3f3960d8910ff2fe3962ab3b2db87cf2f8ccb4dc8145b8bdf237.jpeg', '1', '2023-11-15 23:34:30', '1', '2023-11-15 23:47:39', b'0', 1); +COMMIT; + +-- ---------------------------- +-- Table structure for infra_demo02_category +-- ---------------------------- +DROP TABLE IF EXISTS `infra_demo02_category`; +CREATE TABLE `infra_demo02_category` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', + `parent_id` bigint NOT NULL COMMENT '父级编号', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '示例分类表'; + +-- ---------------------------- +-- Records of infra_demo02_category +-- ---------------------------- +BEGIN; +INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '土豆', 0, '1', '2023-11-15 23:34:30', '1', '2023-11-16 20:24:23', b'0', 1); +INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '番茄', 0, '1', '2023-11-16 20:24:00', '1', '2023-11-16 20:24:15', b'0', 1); +INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, '怪怪', 0, '1', '2023-11-16 20:24:32', '1', '2023-11-16 20:24:32', b'0', 1); +INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, '小番茄', 2, '1', '2023-11-16 20:24:39', '1', '2023-11-16 20:24:39', b'0', 1); +INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, '大番茄', 2, '1', '2023-11-16 20:24:46', '1', '2023-11-16 20:24:46', b'0', 1); +INSERT INTO `infra_demo02_category` (`id`, `name`, `parent_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, '11', 3, '1', '2023-11-24 19:29:34', '1', '2023-11-24 19:29:34', b'0', 1); +COMMIT; + +-- ---------------------------- +-- Table structure for infra_demo03_course +-- ---------------------------- +DROP TABLE IF EXISTS `infra_demo03_course`; +CREATE TABLE `infra_demo03_course` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `student_id` bigint NOT NULL COMMENT '学生编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', + `score` tinyint NOT NULL COMMENT '分数', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生课程表'; + +-- ---------------------------- +-- Records of infra_demo03_course +-- ---------------------------- +BEGIN; +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 2, '语文', 66, '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', b'0', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (3, 2, '数学', 22, '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', b'0', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:44:40', b'1', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:44:40', b'1', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:47:09', b'1', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 15:47:09', b'1', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (10, 5, '体育', 23, '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', b'0', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (11, 5, '计算机', 11, '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', b'0', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (12, 2, '电脑', 33, '1', '2023-11-17 00:20:42', '1', '2023-11-16 16:20:45', b'1', 1); +INSERT INTO `infra_demo03_course` (`id`, `student_id`, `name`, `score`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (13, 9, '滑雪', 12, '1', '2023-11-17 13:13:20', '1', '2023-11-17 13:13:20', b'0', 1); +COMMIT; + +-- ---------------------------- +-- Table structure for infra_demo03_grade +-- ---------------------------- +DROP TABLE IF EXISTS `infra_demo03_grade`; +CREATE TABLE `infra_demo03_grade` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `student_id` bigint NOT NULL COMMENT '学生编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', + `teacher` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '班主任', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生班级表'; + +-- ---------------------------- +-- Records of infra_demo03_grade +-- ---------------------------- +BEGIN; +INSERT INTO `infra_demo03_grade` (`id`, `student_id`, `name`, `teacher`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (7, 2, '三年 2 班', '周杰伦', '1', '2023-11-16 23:21:49', '1', '2023-11-16 23:21:49', b'0', 1); +INSERT INTO `infra_demo03_grade` (`id`, `student_id`, `name`, `teacher`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (8, 5, '华为', '遥遥领先', '1', '2023-11-16 23:22:46', '1', '2023-11-16 23:47:10', b'0', 1); +INSERT INTO `infra_demo03_grade` (`id`, `student_id`, `name`, `teacher`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, 9, '小图', '小娃111', '1', '2023-11-17 13:10:23', '1', '2023-11-17 13:10:23', b'0', 1); +COMMIT; + +-- ---------------------------- +-- Table structure for infra_demo03_student +-- ---------------------------- +DROP TABLE IF EXISTS `infra_demo03_student`; +CREATE TABLE `infra_demo03_student` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', + `sex` tinyint NOT NULL COMMENT '性别', + `birthday` datetime NOT NULL COMMENT '出生日期', + `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '简介', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '学生表'; + +-- ---------------------------- +-- Records of infra_demo03_student +-- ---------------------------- +BEGIN; +INSERT INTO `infra_demo03_student` (`id`, `name`, `sex`, `birthday`, `description`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '小白', 1, '2023-11-16 00:00:00', '

厉害

', '1', '2023-11-16 23:21:49', '1', '2023-11-17 16:49:06', b'0', 1); +INSERT INTO `infra_demo03_student` (`id`, `name`, `sex`, `birthday`, `description`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (5, '大黑', 2, '2023-11-13 00:00:00', '

你在教我做事?

', '1', '2023-11-16 23:22:46', '1', '2023-11-17 16:49:07', b'0', 1); +INSERT INTO `infra_demo03_student` (`id`, `name`, `sex`, `birthday`, `description`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (9, '小花', 1, '2023-11-07 00:00:00', '

哈哈哈

', '1', '2023-11-17 00:04:47', '1', '2023-11-17 16:49:08', b'0', 1); +COMMIT; + -- ---------------------------- -- Table structure for infra_file -- ---------------------------- @@ -539,7 +689,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1108 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1128 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -588,7 +738,7 @@ CREATE TABLE `infra_file_content` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 202 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 221 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file_content @@ -616,7 +766,7 @@ CREATE TABLE `infra_job` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 27 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表'; +) ENGINE = InnoDB AUTO_INCREMENT = 28 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务表'; -- ---------------------------- -- Records of infra_job @@ -657,7 +807,7 @@ CREATE TABLE `infra_job_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 232 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; +) ENGINE = InnoDB AUTO_INCREMENT = 233 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; -- ---------------------------- -- Records of infra_job_log @@ -665,31 +815,6 @@ CREATE TABLE `infra_job_log` ( BEGIN; COMMIT; --- ---------------------------- --- Table structure for infra_test_demo --- ---------------------------- -DROP TABLE IF EXISTS `infra_test_demo`; -CREATE TABLE `infra_test_demo` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '编号', - `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名字', - `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态', - `type` tinyint NOT NULL COMMENT '类型', - `category` tinyint NOT NULL COMMENT '分类', - `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', - `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; - --- ---------------------------- --- Records of infra_test_demo --- ---------------------------- -BEGIN; -COMMIT; - -- ---------------------------- -- Table structure for member_address -- ---------------------------- @@ -710,7 +835,7 @@ CREATE TABLE `member_address` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_userId`(`user_id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址'; +) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '用户收件地址'; -- ---------------------------- -- Records of member_address @@ -769,7 +894,7 @@ CREATE TABLE `member_experience_record` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员经验记录-用户编号', INDEX `idx_user_biz_type`(`user_id` ASC, `biz_type` ASC) USING BTREE COMMENT '会员经验记录-用户业务类型' -) ENGINE = InnoDB AUTO_INCREMENT = 41 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员经验记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 42 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员经验记录'; -- ---------------------------- -- Records of member_experience_record @@ -827,7 +952,7 @@ CREATE TABLE `member_group` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户分组'; +) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户分组'; -- ---------------------------- -- Records of member_group @@ -855,7 +980,7 @@ CREATE TABLE `member_level` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级'; +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级'; -- ---------------------------- -- Records of member_level @@ -885,7 +1010,7 @@ CREATE TABLE `member_level_record` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员等级记录-用户编号' -) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录'; -- ---------------------------- -- Records of member_level_record @@ -915,7 +1040,7 @@ CREATE TABLE `member_point_record` ( PRIMARY KEY (`id`) USING BTREE, INDEX `index_userId`(`user_id` ASC) USING BTREE, INDEX `index_title`(`title` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 60 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户积分记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 61 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户积分记录'; -- ---------------------------- -- Records of member_point_record @@ -1055,7 +1180,7 @@ CREATE TABLE `member_tag` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员标签'; +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员标签'; -- ---------------------------- -- Records of member_tag @@ -1097,7 +1222,7 @@ CREATE TABLE `member_user` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 249 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员用户'; +) ENGINE = InnoDB AUTO_INCREMENT = 250 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '会员用户'; -- ---------------------------- -- Records of member_user @@ -1131,7 +1256,7 @@ CREATE TABLE `system_dept` ( -- Records of system_dept -- ---------------------------- BEGIN; -INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-06-19 00:29:10', b'0', 1); +INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, '芋道源码', 0, 0, 1, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2023-11-14 23:30:36', b'0', 1); INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (101, '深圳总公司', 100, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '1', '2022-05-16 20:25:23', b'0', 1); INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (102, '长沙分公司', 100, 2, NULL, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '', '2021-12-15 05:01:40', b'0', 1); INSERT INTO `system_dept` (`id`, `name`, `parent_id`, `sort`, `leader_user_id`, `phone`, `email`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, '研发部门', 101, 1, 104, '15888888888', 'ry@qq.com', 0, 'admin', '2021-01-05 17:03:47', '103', '2022-01-14 01:04:14', b'0', 1); @@ -1165,14 +1290,14 @@ CREATE TABLE `system_dict_data` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1435 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1455 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; -- ---------------------------- -- Records of system_dict_data -- ---------------------------- BEGIN; INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, 1, '男', '1', 'system_user_sex', 0, 'default', 'A', '性别男', 'admin', '2021-01-05 17:03:48', '1', '2022-03-29 00:14:39', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 2, '女', '2', 'system_user_sex', 1, 'success', '', '性别女', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 01:30:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2, 2, '女', '2', 'system_user_sex', 0, 'success', '', '性别女', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 23:30:37', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (8, 1, '正常', '1', 'infra_job_status', 0, 'success', '', '正常状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:33:38', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (9, 2, '暂停', '2', 'infra_job_status', 0, 'danger', '', '停用状态', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:33:45', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (12, 1, '系统内置', '1', 'infra_config_type', 0, 'danger', '', '参数类型 - 系统内置', 'admin', '2021-01-05 17:03:48', '1', '2022-02-16 19:06:02', b'0'); @@ -1474,6 +1599,20 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1438, 31, '微信公众平台', '31', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:18', '1', '2023-11-04 13:05:18', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1439, 32, '微信开放平台', '32', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:30', '1', '2023-11-04 13:05:30', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1440, 34, '微信小程序', '34', 'system_social_type', 0, '', '', '', '1', '2023-11-04 13:05:38', '1', '2023-11-04 13:07:16', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1441, 1, '上架', '1', 'crm_product_status', 0, 'success', '', '', '1', '2023-10-30 21:49:34', '1', '2023-10-30 21:49:34', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1442, 0, '下架', '0', 'crm_product_status', 0, 'success', '', '', '1', '2023-10-30 21:49:13', '1', '2023-10-30 21:49:13', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1443, 15, '子表', '15', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-13 23:06:16', '1', '2023-11-13 23:06:16', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1444, 10, '主表(标准模式)', '10', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-14 12:32:49', '1', '2023-11-14 12:32:49', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1445, 11, '主表(ERP 模式)', '11', 'infra_codegen_template_type', 0, 'default', '', '', '1', '2023-11-14 12:33:05', '1', '2023-11-14 12:33:05', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1446, 12, '主表(内嵌模式)', '12', 'infra_codegen_template_type', 0, '', '', '', '1', '2023-11-14 12:33:31', '1', '2023-11-14 12:33:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1447, 1, '负责人', '1', 'crm_permission_level', 0, 'default', '', '', '1', '2023-11-30 09:53:12', '1', '2023-11-30 09:53:12', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1448, 2, '只读', '2', 'crm_permission_level', 0, '', '', '', '1', '2023-11-30 09:53:29', '1', '2023-11-30 09:53:29', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1449, 3, '读写', '3', 'crm_permission_level', 0, '', '', '', '1', '2023-11-30 09:53:36', '1', '2023-11-30 09:53:36', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1450, 0, '未提交', '0', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:56:59', '1', '2023-11-30 18:56:59', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1451, 10, '审批中', '10', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:10', '1', '2023-11-30 18:57:10', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1452, 20, '审核通过', '20', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:24', '1', '2023-11-30 18:57:24', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1453, 30, '审核不通过', '30', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:32', '1', '2023-11-30 18:57:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1454, 40, '已取消', '40', 'crm_audit_status', 0, '', '', '', '1', '2023-11-30 18:57:42', '1', '2023-11-30 18:57:42', b'0'); COMMIT; -- ---------------------------- @@ -1494,7 +1633,7 @@ CREATE TABLE `system_dict_type` ( `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 600 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; +) ENGINE = InnoDB AUTO_INCREMENT = 607 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of system_dict_type @@ -1573,6 +1712,9 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (188, '客户来源', 'crm_customer_source', 0, 'CRM 客户来源', '1', '2023-10-28 23:00:34', '1', '2023-10-28 15:11:16', b'0', NULL); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (600, 'Banner 位置', 'promotion_banner_position', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-11-04 13:04:02', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (601, '社交类型', 'system_social_type', 0, '', '1', '2023-11-04 13:03:54', '1', '2023-11-04 13:03:54', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (604, '产品状态', 'crm_product_status', 0, '', '1', '2023-10-30 21:47:59', '1', '2023-10-30 21:48:45', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (605, 'CRM 数据权限的级别', 'crm_permission_level', 0, '', '1', '2023-11-30 09:51:59', '1', '2023-11-30 09:51:59', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (606, 'CRM 审批状态', 'crm_audit_status', 0, '', '1', '2023-11-30 18:56:23', '1', '2023-11-30 18:56:23', b'0', '1970-01-01 00:00:00'); COMMIT; -- ---------------------------- @@ -1592,7 +1734,7 @@ CREATE TABLE `system_error_code` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 5932 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表'; +) ENGINE = InnoDB AUTO_INCREMENT = 6039 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '错误码表'; -- ---------------------------- -- Records of system_error_code @@ -1621,7 +1763,7 @@ CREATE TABLE `system_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2631 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 2667 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1686,7 +1828,7 @@ CREATE TABLE `system_mail_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 355 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表'; +) ENGINE = InnoDB AUTO_INCREMENT = 356 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '邮件日志表'; -- ---------------------------- -- Records of system_mail_log @@ -1751,7 +1893,7 @@ CREATE TABLE `system_menu` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2449 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2526 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; -- ---------------------------- -- Records of system_menu @@ -1839,11 +1981,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1065, '设置用户角色', 'system:permission:assign-user-role', 3, 8, 101, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-07 10:23:28', '', '2022-04-20 17:03:10', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1066, '获得 Redis 监控信息', 'infra:redis:get-monitor-info', 3, 1, 113, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-26 01:02:31', '', '2022-04-20 17:03:10', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1067, '获得 Redis Key 列表', 'infra:redis:get-key-list', 3, 2, 113, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-01-26 01:02:52', '', '2022-04-20 17:03:10', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1070, '代码生成示例', 'infra:test-demo:query', 2, 1, 2, 'test-demo', 'validCode', 'infra/testDemo/index', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1071, '测试示例表创建', 'infra:test-demo:create', 3, 1, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1072, '测试示例表更新', 'infra:test-demo:update', 3, 2, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1073, '测试示例表删除', 'infra:test-demo:delete', 3, 3, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1074, '测试示例表导出', 'infra:test-demo:export', 3, 4, 1070, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2022-04-20 17:03:10', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1070, '代码生成案例', '', 1, 1, 2, 'demo', 'ep:aim', 'infra/testDemo/index', NULL, 0, b'1', b'1', b'1', '', '2021-02-06 12:42:49', '1', '2023-11-15 23:45:53', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1075, '任务触发', 'infra:job:trigger', 3, 8, 110, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2021-02-07 13:03:10', '', '2022-04-20 17:03:10', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1076, '数据库文档', '', 2, 4, 2, 'db-doc', 'table', 'infra/dbDoc/index', 'InfraDBDoc', 0, b'1', b'1', b'1', '', '2021-02-08 01:41:47', '1', '2023-04-08 09:13:38', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1077, '监控平台', '', 2, 13, 2, 'skywalking', 'eye-open', 'infra/skywalking/index', 'InfraSkyWalking', 0, b'1', b'1', b'1', '', '2021-02-08 20:41:31', '1', '2023-04-08 10:39:06', b'0'); @@ -2165,7 +2303,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2303, '拼团活动', '', 2, 3, 2030, 'combination', 'fa:group', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:19:54', '1', '2023-08-12 17:20:05', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2304, '拼团商品', '', 2, 1, 2303, 'acitivity', 'ep:apple', 'mall/promotion/combination/activity/index', 'PromotionCombinationActivity', 0, b'1', b'1', b'1', '1', '2023-08-12 17:22:03', '1', '2023-08-12 17:22:29', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2305, '拼团活动查询', 'promotion:combination-activity:query ', 3, 1, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:32', '1', '2023-08-12 17:54:32', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2305, '拼团活动查询', 'promotion:combination-activity:query', 3, 1, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:32', '1', '2023-11-24 11:57:40', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2306, '拼团活动创建', 'promotion:combination-activity:create', 3, 2, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:49', '1', '2023-08-12 17:54:49', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2307, '拼团活动更新', 'promotion:combination-activity:update', 3, 3, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:55:04', '1', '2023-08-12 17:55:04', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2308, '拼团活动删除', 'promotion:combination-activity:delete', 3, 4, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:55:23', '1', '2023-08-12 17:55:23', b'0'); @@ -2310,6 +2448,36 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2451, '三方应用更新', 'system:social-client:update', 3, 3, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:27', '1', '2023-11-04 12:44:27', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2452, '三方应用删除', 'system:social-client:delete', 3, 4, 2448, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-11-04 12:44:43', '1', '2023-11-04 12:44:43', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2453, '三方用户', 'system:social-user:query', 2, 2, 2447, 'user', 'ep:avatar', 'system/social/user/index.vue', 'SocialUser', 0, b'1', b'1', b'1', '1', '2023-11-04 14:01:05', '1', '2023-11-04 14:01:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2472, '主子表(内嵌)', '', 2, 12, 1070, 'demo03-inner', 'fa:power-off', 'infra/demo/demo03/inner/index', 'Demo03StudentInner', 0, b'1', b'1', b'1', '', '2023-11-13 04:39:51', '1', '2023-11-16 23:53:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2478, '单表(增删改查)', '', 2, 1, 1070, 'demo01-contact', 'ep:bicycle', 'infra/demo/demo01/index', 'Demo01Contact', 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '1', '2023-11-16 20:34:40', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2479, '示例联系人查询', 'infra:demo01-contact:query', 3, 1, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2480, '示例联系人创建', 'infra:demo01-contact:create', 3, 2, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2481, '示例联系人更新', 'infra:demo01-contact:update', 3, 3, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2482, '示例联系人删除', 'infra:demo01-contact:delete', 3, 4, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2483, '示例联系人导出', 'infra:demo01-contact:export', 3, 5, 2478, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-15 14:42:30', '', '2023-11-15 14:42:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2484, '树表(增删改查)', '', 2, 2, 1070, 'demo02-category', 'fa:tree', 'infra/demo/demo02/index', 'Demo02Category', 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '1', '2023-11-16 20:35:01', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2485, '示例分类查询', 'infra:demo02-category:query', 3, 1, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2486, '示例分类创建', 'infra:demo02-category:create', 3, 2, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2487, '示例分类更新', 'infra:demo02-category:update', 3, 3, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2488, '示例分类删除', 'infra:demo02-category:delete', 3, 4, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2489, '示例分类导出', 'infra:demo02-category:export', 3, 5, 2484, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:18:27', '', '2023-11-16 12:18:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2490, '主子表(标准)', '', 2, 10, 1070, 'demo03-normal', 'fa:battery-3', 'infra/demo/demo03/normal/index', 'Demo03StudentNormal', 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '1', '2023-11-16 23:10:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2491, '学生查询', 'infra:demo03-student:query', 3, 1, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2492, '学生创建', 'infra:demo03-student:create', 3, 2, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2493, '学生更新', 'infra:demo03-student:update', 3, 3, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2494, '学生删除', 'infra:demo03-student:delete', 3, 4, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2495, '学生导出', 'infra:demo03-student:export', 3, 5, 2490, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-16 12:53:37', '', '2023-11-16 12:53:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2497, '主子表(ERP)', '', 2, 11, 1070, 'demo03-erp', 'ep:calendar', 'infra/demo/demo03/erp/index', 'Demo03StudentERP', 0, b'1', b'1', b'1', '', '2023-11-16 15:50:59', '1', '2023-11-17 13:19:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2516, '客户公海配置', '', 2, 0, 2524, 'customer-pool-config', 'ep:data-analysis', 'crm/config/customerPoolConfig/index', 'CrmCustomerPoolConfig', 0, b'1', b'1', b'1', '', '2023-11-18 13:33:31', '1', '2023-11-26 20:08:14', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2517, '客户公海配置保存', 'crm:customer-pool-config:update', 3, 1, 2516, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:31', '', '2023-11-18 13:33:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2518, '客户限制配置', '', 2, 0, 2524, 'customer-limit-config', 'ep:avatar', 'crm/config/customerLimitConfig/index', 'CrmCustomerLimitConfig', 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '1', '2023-11-26 20:07:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2519, '客户限制配置查询', 'crm:customer-limit-config:query', 3, 1, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2520, '客户限制配置创建', 'crm:customer-limit-config:create', 3, 2, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2521, '客户限制配置更新', 'crm:customer-limit-config:update', 3, 3, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2522, '客户限制配置删除', 'crm:customer-limit-config:delete', 3, 4, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2523, '客户限制配置导出', 'crm:customer-limit-config:export', 3, 5, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2524, '系统配置', '', 1, 99, 2397, 'config', 'ep:connection', '', '', 0, b'1', b'1', b'1', '1', '2023-11-18 21:58:00', '1', '2023-11-18 21:58:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2525, 'WebSocket 测试', '', 2, 7, 2, 'websocket', 'ep:connection', 'infra/webSocket/index', 'InfraWebSocket', 0, b'1', b'1', b'1', '1', '2023-11-23 19:41:55', '1', '2023-11-24 19:22:30', b'0'); COMMIT; -- ---------------------------- @@ -2336,7 +2504,7 @@ CREATE TABLE `system_notice` ( -- ---------------------------- BEGIN; INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, '芋道的公众', '

新版本内容133

', 1, 0, 'admin', '2021-01-05 17:03:48', '1', '2022-05-04 21:00:20', b'0', 1); -INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '维护通知:2018-07-01 若依系统凌晨维护', '

维护内容

', 2, 1, 'admin', '2021-01-05 17:03:48', '1', '2022-05-11 12:34:24', b'0', 1); +INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, '维护通知:2018-07-01 系统凌晨维护', '

\"\"1111

', 2, 1, 'admin', '2021-01-05 17:03:48', '1', '2023-11-23 23:37:41', b'0', 1); INSERT INTO `system_notice` (`id`, `title`, `content`, `type`, `status`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, '我是测试标题', '

哈哈哈哈123

', 1, 0, '110', '2022-02-22 01:01:25', '110', '2022-02-22 01:01:46', b'0', 121); COMMIT; @@ -2400,7 +2568,7 @@ CREATE TABLE `system_notify_template` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '站内信模板表'; +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '站内信模板表'; -- ---------------------------- -- Records of system_notify_template @@ -2430,7 +2598,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 3152 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 3587 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2552,7 +2720,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1099 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1132 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -2592,7 +2760,7 @@ CREATE TABLE `system_operate_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 8845 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 9175 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; -- ---------------------------- -- Records of system_operate_log @@ -2625,8 +2793,8 @@ CREATE TABLE `system_post` ( -- ---------------------------- BEGIN; INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'ceo', '董事长', 1, 0, '', 'admin', '2021-01-06 17:03:48', '1', '2023-02-11 15:19:04', b'0', 1); -INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2021-12-12 10:47:47', b'0', 1); -INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 'user', '普通员工', 4, 0, '111', 'admin', '2021-01-05 17:03:48', '1', '2023-02-11 15:19:00', b'0', 1); +INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2, 'se', '项目经理', 2, 0, '', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 09:18:20', b'0', 1); +INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (4, 'user', '普通员工', 4, 0, '111', 'admin', '2021-01-05 17:03:48', '1', '2023-11-15 09:18:18', b'0', 1); COMMIT; -- ---------------------------- @@ -2819,10 +2987,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1657, 101, 1066, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1658, 101, 1067, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1659, 101, 1070, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1660, 101, 1071, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1661, 101, 1072, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1662, 101, 1073, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1663, 101, 1074, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1664, 101, 1075, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1665, 101, 1076, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1666, 101, 1077, '1', '2022-04-01 22:21:37', '1', '2022-04-01 22:21:37', b'0', 1); @@ -3140,10 +3304,6 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2027, 2, 1066, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2028, 2, 1067, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2029, 2, 1070, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2030, 2, 1071, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2031, 2, 1072, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2032, 2, 1073, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); -INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2033, 2, 1074, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2034, 2, 1075, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2035, 2, 1076, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (2036, 2, 1082, '1', '2023-01-25 08:42:52', '1', '2023-01-25 08:42:52', b'0', 1); @@ -3600,7 +3760,7 @@ CREATE TABLE `system_sms_code` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_mobile`(`mobile` ASC) USING BTREE COMMENT '手机号' -) ENGINE = InnoDB AUTO_INCREMENT = 535 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; +) ENGINE = InnoDB AUTO_INCREMENT = 536 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '手机验证码'; -- ---------------------------- -- Records of system_sms_code @@ -3627,8 +3787,6 @@ CREATE TABLE `system_sms_log` ( `user_type` tinyint NULL DEFAULT NULL COMMENT '用户类型', `send_status` tinyint NOT NULL DEFAULT 0 COMMENT '发送状态', `send_time` datetime NULL DEFAULT NULL COMMENT '发送时间', - `send_code` int NULL DEFAULT NULL COMMENT '发送结果的编码', - `send_msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '发送结果的提示', `api_send_code` varchar(63) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '短信 API 发送结果的编码', `api_send_msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '短信 API 发送失败的提示', `api_request_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '短信 API 发送返回的唯一请求 ID', @@ -3743,7 +3901,7 @@ CREATE TABLE `system_social_user` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 24 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; +) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; -- ---------------------------- -- Records of system_social_user @@ -3768,7 +3926,7 @@ CREATE TABLE `system_social_user_bind` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 80 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; +) ENGINE = InnoDB AUTO_INCREMENT = 81 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; -- ---------------------------- -- Records of system_social_user_bind @@ -3787,7 +3945,7 @@ CREATE TABLE `system_tenant` ( `contact_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '联系人', `contact_mobile` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '联系手机', `status` tinyint NOT NULL DEFAULT 0 COMMENT '租户状态(0正常 1停用)', - `domain` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '绑定域名', + `website` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '绑定域名', `package_id` bigint NOT NULL COMMENT '租户套餐编号', `expire_time` datetime NOT NULL COMMENT '过期时间', `account_count` int NOT NULL COMMENT '账号数量', @@ -3803,9 +3961,9 @@ CREATE TABLE `system_tenant` ( -- Records of system_tenant -- ---------------------------- BEGIN; -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'https://www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2022-02-23 12:15:11', b'0'); -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'http://www.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-09-16 16:59:42', b'0'); -INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `domain`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-09-16 16:59:27', b'0'); +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2023-11-06 11:41:41', b'0'); +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'zsxq.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2023-11-06 11:41:47', b'0'); +INSERT INTO `system_tenant` (`id`, `name`, `contact_user_id`, `contact_name`, `contact_mobile`, `status`, `website`, `package_id`, `expire_time`, `account_count`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'test.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', '2022-03-07 21:37:58', '1', '2023-11-06 11:41:53', b'0'); COMMIT; -- ---------------------------- @@ -3938,13 +4096,13 @@ CREATE TABLE `system_users` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `idx_username`(`username` ASC, `update_time` ASC, `tenant_id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 127 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表'; +) ENGINE = InnoDB AUTO_INCREMENT = 126 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表'; -- ---------------------------- -- Records of system_users -- ---------------------------- BEGIN; -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2023-11-04 10:33:16', 'admin', '2021-01-05 17:03:47', NULL, '2023-11-04 10:33:16', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '127.0.0.1', '2023-11-30 09:16:00', 'admin', '2021-01-05 17:03:47', NULL, '2023-11-30 09:16:00', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2023-09-24 18:21:19', '', '2021-01-21 02:13:53', NULL, '2023-09-24 18:21:19', b'0', 1); @@ -3959,7 +4117,7 @@ INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (115, 'aotemane', '$2a$10$/WCwGHu1eq0wOVDd/u8HweJ0gJCHyLS6T7ndCqI8UXZAQom1etk2e', '1', '11', 101, '[]', '', '', 1, '', 0, '', NULL, '1', '2022-04-30 02:55:43', '1', '2022-06-22 13:34:58', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (116, '15601691302', '$2a$10$L5C4S0U6adBWMvFv1Wwl4.DI/NwYS3WIfLj5Q.Naqr5II8CmqsDZ6', '小豆', NULL, NULL, NULL, '', '', 0, '', 0, '', NULL, '1', '2022-05-17 10:07:10', '1', '2022-05-17 10:07:10', b'0', 124); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (117, 'admin123', '$2a$10$WI8Gg/lpZQIrOEZMHqka7OdFaD4Nx.B/qY8ZGTTUKrOJwaHFqibaC', '测试号', '1111', 100, '[2]', '', '15601691234', 1, '', 0, '', NULL, '1', '2022-07-09 17:40:26', '1', '2022-07-09 17:40:26', b'0', 1); -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (118, 'goudan', '$2a$10$Lrb71muL.s5/AFjQ2IHkzOFlAFwUToH.zQL7bnghvTDt/QptjGgF6', '狗蛋', NULL, 103, '[1]', '', '', 2, '', 0, '', NULL, '1', '2022-07-09 17:44:43', '1', '2022-12-31 17:29:13', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (118, 'goudan', '$2a$10$Lrb71muL.s5/AFjQ2IHkzOFlAFwUToH.zQL7bnghvTDt/QptjGgF6', '狗蛋', NULL, 103, '[1]', '', '', 2, '', 0, '', NULL, '1', '2022-07-09 17:44:43', '1', '2023-11-18 19:02:13', b'0', 1); COMMIT; SET FOREIGN_KEY_CHECKS = 1; diff --git a/sql/oracle/ruoyi-vue-pro.sql b/sql/oracle/ruoyi-vue-pro.sql index 46481ae2f..0eb0f6440 100644 --- a/sql/oracle/ruoyi-vue-pro.sql +++ b/sql/oracle/ruoyi-vue-pro.sql @@ -4178,7 +4178,7 @@ CREATE TABLE "SYSTEM_TENANT" ( "CONTACT_NAME" NVARCHAR2(30), "CONTACT_MOBILE" NVARCHAR2(500), "STATUS" NUMBER(4,0) NOT NULL, - "DOMAIN" NVARCHAR2(256), + "WEBSITE" NVARCHAR2(256), "PACKAGE_ID" NUMBER(20,0) NOT NULL, "EXPIRE_TIME" DATE NOT NULL, "ACCOUNT_COUNT" NUMBER(11,0) NOT NULL, @@ -4211,7 +4211,7 @@ COMMENT ON COLUMN "SYSTEM_TENANT"."CONTACT_USER_ID" IS '联系人的用户编号 COMMENT ON COLUMN "SYSTEM_TENANT"."CONTACT_NAME" IS '联系人'; COMMENT ON COLUMN "SYSTEM_TENANT"."CONTACT_MOBILE" IS '联系手机'; COMMENT ON COLUMN "SYSTEM_TENANT"."STATUS" IS '租户状态(0正常 1停用)'; -COMMENT ON COLUMN "SYSTEM_TENANT"."DOMAIN" IS '绑定域名'; +COMMENT ON COLUMN "SYSTEM_TENANT"."WEBSITE" IS '绑定域名'; COMMENT ON COLUMN "SYSTEM_TENANT"."PACKAGE_ID" IS '租户套餐编号'; COMMENT ON COLUMN "SYSTEM_TENANT"."EXPIRE_TIME" IS '过期时间'; COMMENT ON COLUMN "SYSTEM_TENANT"."ACCOUNT_COUNT" IS '账号数量'; @@ -4225,9 +4225,9 @@ COMMENT ON TABLE "SYSTEM_TENANT" IS '租户表'; -- ---------------------------- -- Records of SYSTEM_TENANT -- ---------------------------- -INSERT INTO "SYSTEM_TENANT" ("ID", "NAME", "CONTACT_USER_ID", "CONTACT_NAME", "CONTACT_MOBILE", "STATUS", "DOMAIN", "PACKAGE_ID", "EXPIRE_TIME", "ACCOUNT_COUNT", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('1', '芋道源码', NULL, '芋艿', '17321315478', '0', 'https://www.iocoder.cn', '0', TO_DATE('2099-02-19 17:14:16', 'SYYYY-MM-DD HH24:MI:SS'), '9999', '1', TO_DATE('2021-01-05 17:03:47', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-23 12:15:11', 'SYYYY-MM-DD HH24:MI:SS'), '0'); -INSERT INTO "SYSTEM_TENANT" ("ID", "NAME", "CONTACT_USER_ID", "CONTACT_NAME", "CONTACT_MOBILE", "STATUS", "DOMAIN", "PACKAGE_ID", "EXPIRE_TIME", "ACCOUNT_COUNT", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('121', '小租户', '110', '小王2', '15601691300', '0', 'http://www.iocoder.cn', '111', TO_DATE('2024-03-11 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), '20', '1', TO_DATE('2022-02-22 00:56:14', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-03-19 18:37:20', 'SYYYY-MM-DD HH24:MI:SS'), '0'); -INSERT INTO "SYSTEM_TENANT" ("ID", "NAME", "CONTACT_USER_ID", "CONTACT_NAME", "CONTACT_MOBILE", "STATUS", "DOMAIN", "PACKAGE_ID", "EXPIRE_TIME", "ACCOUNT_COUNT", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('122', '测试租户', '113', '芋道', '15601691300', '0', 'https://www.iocoder.cn', '111', TO_DATE('2022-04-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), '50', '1', TO_DATE('2022-03-07 21:37:58', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-03-07 21:37:58', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_TENANT" ("ID", "NAME", "CONTACT_USER_ID", "CONTACT_NAME", "CONTACT_MOBILE", "STATUS", "WEBSITE", "PACKAGE_ID", "EXPIRE_TIME", "ACCOUNT_COUNT", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('1', '芋道源码', NULL, '芋艿', '17321315478', '0', 'https://www.iocoder.cn', '0', TO_DATE('2099-02-19 17:14:16', 'SYYYY-MM-DD HH24:MI:SS'), '9999', '1', TO_DATE('2021-01-05 17:03:47', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-02-23 12:15:11', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_TENANT" ("ID", "NAME", "CONTACT_USER_ID", "CONTACT_NAME", "CONTACT_MOBILE", "STATUS", "WEBSITE", "PACKAGE_ID", "EXPIRE_TIME", "ACCOUNT_COUNT", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('121', '小租户', '110', '小王2', '15601691300', '0', 'http://www.iocoder.cn', '111', TO_DATE('2024-03-11 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), '20', '1', TO_DATE('2022-02-22 00:56:14', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-03-19 18:37:20', 'SYYYY-MM-DD HH24:MI:SS'), '0'); +INSERT INTO "SYSTEM_TENANT" ("ID", "NAME", "CONTACT_USER_ID", "CONTACT_NAME", "CONTACT_MOBILE", "STATUS", "WEBSITE", "PACKAGE_ID", "EXPIRE_TIME", "ACCOUNT_COUNT", "CREATOR", "CREATE_TIME", "UPDATER", "UPDATE_TIME", "DELETED") VALUES ('122', '测试租户', '113', '芋道', '15601691300', '0', 'https://www.iocoder.cn', '111', TO_DATE('2022-04-30 00:00:00', 'SYYYY-MM-DD HH24:MI:SS'), '50', '1', TO_DATE('2022-03-07 21:37:58', 'SYYYY-MM-DD HH24:MI:SS'), '1', TO_DATE('2022-03-07 21:37:58', 'SYYYY-MM-DD HH24:MI:SS'), '0'); COMMIT; COMMIT; diff --git a/sql/postgresql/ruoyi-vue-pro.sql b/sql/postgresql/ruoyi-vue-pro.sql index cab2e38bc..206fdfce8 100644 --- a/sql/postgresql/ruoyi-vue-pro.sql +++ b/sql/postgresql/ruoyi-vue-pro.sql @@ -6779,7 +6779,7 @@ CREATE TABLE "system_tenant" "contact_name" varchar(30) COLLATE "pg_catalog"."default" NOT NULL, "contact_mobile" varchar(500) COLLATE "pg_catalog"."default", "status" int2 NOT NULL, - "domain" varchar(256) COLLATE "pg_catalog"."default", + "website" varchar(256) COLLATE "pg_catalog"."default", "package_id" int8 NOT NULL, "expire_time" timestamp(6) NOT NULL, "account_count" int4 NOT NULL, @@ -6803,7 +6803,7 @@ ON COLUMN "system_tenant"."contact_mobile" IS '联系手机'; COMMENT ON COLUMN "system_tenant"."status" IS '租户状态(0正常 1停用)'; COMMENT -ON COLUMN "system_tenant"."domain" IS '绑定域名'; +ON COLUMN "system_tenant"."website" IS '绑定域名'; COMMENT ON COLUMN "system_tenant"."package_id" IS '租户套餐编号'; COMMENT @@ -6827,17 +6827,17 @@ ON TABLE "system_tenant" IS '租户表'; -- Records of system_tenant -- ---------------------------- BEGIN; -INSERT INTO "system_tenant" ("id", "name", "contact_user_id", "contact_name", "contact_mobile", "status", "domain", +INSERT INTO "system_tenant" ("id", "name", "contact_user_id", "contact_name", "contact_mobile", "status", "website", "package_id", "expire_time", "account_count", "creator", "create_time", "updater", "update_time", "deleted") VALUES (1, '芋道源码', NULL, '芋艿', '17321315478', 0, 'https://www.iocoder.cn', 0, '2099-02-19 17:14:16', 9999, '1', '2021-01-05 17:03:47', '1', '2022-02-23 12:15:11', 0); -INSERT INTO "system_tenant" ("id", "name", "contact_user_id", "contact_name", "contact_mobile", "status", "domain", +INSERT INTO "system_tenant" ("id", "name", "contact_user_id", "contact_name", "contact_mobile", "status", "website", "package_id", "expire_time", "account_count", "creator", "create_time", "updater", "update_time", "deleted") VALUES (121, '小租户', 110, '小王2', '15601691300', 0, 'http://www.iocoder.cn', 111, '2024-03-11 00:00:00', 20, '1', '2022-02-22 00:56:14', '1', '2022-03-19 18:37:20', 0); -INSERT INTO "system_tenant" ("id", "name", "contact_user_id", "contact_name", "contact_mobile", "status", "domain", +INSERT INTO "system_tenant" ("id", "name", "contact_user_id", "contact_name", "contact_mobile", "status", "website", "package_id", "expire_time", "account_count", "creator", "create_time", "updater", "update_time", "deleted") VALUES (122, '测试租户', 113, '芋道', '15601691300', 0, 'https://www.iocoder.cn', 111, '2022-04-30 00:00:00', 50, '1', diff --git a/sql/sqlserver/ruoyi-vue-pro.sql b/sql/sqlserver/ruoyi-vue-pro.sql index 454d8d4bc..bfb10f6bd 100644 --- a/sql/sqlserver/ruoyi-vue-pro.sql +++ b/sql/sqlserver/ruoyi-vue-pro.sql @@ -10595,7 +10595,7 @@ CREATE TABLE [dbo].[system_tenant] ( [contact_name] nvarchar(30) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [contact_mobile] nvarchar(500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [status] tinyint NOT NULL, - [domain] nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [website] nvarchar(256) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [package_id] bigint NOT NULL, [expire_time] datetime2(7) NOT NULL, [account_count] int NOT NULL, @@ -10656,7 +10656,7 @@ EXEC sp_addextendedproperty 'MS_Description', N'绑定域名', 'SCHEMA', N'dbo', 'TABLE', N'system_tenant', -'COLUMN', N'domain' +'COLUMN', N'website' GO EXEC sp_addextendedproperty @@ -10731,13 +10731,13 @@ GO SET IDENTITY_INSERT [dbo].[system_tenant] ON GO -INSERT INTO [dbo].[system_tenant] ([id], [name], [contact_user_id], [contact_name], [contact_mobile], [status], [domain], [package_id], [expire_time], [account_count], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'1', N'芋道源码', NULL, N'芋艿', N'17321315478', N'0', N'https://www.iocoder.cn', N'0', N'2099-02-19 17:14:16.0000000', N'9999', N'1', N'2021-01-05 17:03:47.0000000', N'1', N'2022-02-23 12:15:11.0000000', N'0') +INSERT INTO [dbo].[system_tenant] ([id], [name], [contact_user_id], [contact_name], [contact_mobile], [status], [website], [package_id], [expire_time], [account_count], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'1', N'芋道源码', NULL, N'芋艿', N'17321315478', N'0', N'https://www.iocoder.cn', N'0', N'2099-02-19 17:14:16.0000000', N'9999', N'1', N'2021-01-05 17:03:47.0000000', N'1', N'2022-02-23 12:15:11.0000000', N'0') GO -INSERT INTO [dbo].[system_tenant] ([id], [name], [contact_user_id], [contact_name], [contact_mobile], [status], [domain], [package_id], [expire_time], [account_count], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'121', N'小租户', N'110', N'小王2', N'15601691300', N'0', N'http://www.iocoder.cn', N'111', N'2024-03-11 00:00:00.0000000', N'20', N'1', N'2022-02-22 00:56:14.0000000', N'1', N'2022-03-19 18:37:20.0000000', N'0') +INSERT INTO [dbo].[system_tenant] ([id], [name], [contact_user_id], [contact_name], [contact_mobile], [status], [website], [package_id], [expire_time], [account_count], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'121', N'小租户', N'110', N'小王2', N'15601691300', N'0', N'http://www.iocoder.cn', N'111', N'2024-03-11 00:00:00.0000000', N'20', N'1', N'2022-02-22 00:56:14.0000000', N'1', N'2022-03-19 18:37:20.0000000', N'0') GO -INSERT INTO [dbo].[system_tenant] ([id], [name], [contact_user_id], [contact_name], [contact_mobile], [status], [domain], [package_id], [expire_time], [account_count], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'122', N'测试租户', N'113', N'芋道', N'15601691300', N'0', N'https://www.iocoder.cn', N'111', N'2022-04-30 00:00:00.0000000', N'50', N'1', N'2022-03-07 21:37:58.0000000', N'1', N'2022-03-07 21:37:58.0000000', N'0') +INSERT INTO [dbo].[system_tenant] ([id], [name], [contact_user_id], [contact_name], [contact_mobile], [status], [website], [package_id], [expire_time], [account_count], [creator], [create_time], [updater], [update_time], [deleted]) VALUES (N'122', N'测试租户', N'113', N'芋道', N'15601691300', N'0', N'https://www.iocoder.cn', N'111', N'2022-04-30 00:00:00.0000000', N'50', N'1', N'2022-03-07 21:37:58.0000000', N'1', N'2022-03-07 21:37:58.0000000', N'0') GO SET IDENTITY_INSERT [dbo].[system_tenant] OFF diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 1b7ba6515..a82f9b08c 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.8.3-snapshot + 1.9.0-snapshot 1.5.0 2.7.17 @@ -78,10 +78,10 @@ 4.6.4 2.2.1 3.1.853 - 1.0.5 + 1.0.8 1.6.1 2.12.2 - 4.5.0 + 4.5.7.B @@ -135,11 +135,6 @@ yudao-spring-boot-starter-biz-pay ${revision} - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-weixin - ${revision} - cn.iocoder.cloud yudao-spring-boot-starter-biz-tenant @@ -150,11 +145,6 @@ yudao-spring-boot-starter-biz-data-permission ${revision} - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-social - ${revision} - cn.iocoder.cloud yudao-spring-boot-starter-biz-error-code @@ -203,6 +193,12 @@ ${revision} + + cn.iocoder.cloud + yudao-spring-boot-starter-websocket + ${revision} + + org.springdoc springdoc-openapi-ui @@ -627,11 +623,6 @@ weixin-java-pay ${weixin-java.version} - - com.github.binarywang - weixin-java-mp - ${weixin-java.version} - com.github.binarywang wx-java-mp-spring-boot-starter diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index c2e7d6123..546f42723 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -34,8 +34,6 @@ yudao-spring-boot-starter-biz-sms yudao-spring-boot-starter-biz-pay - yudao-spring-boot-starter-biz-weixin - yudao-spring-boot-starter-biz-social yudao-spring-boot-starter-biz-tenant yudao-spring-boot-starter-biz-data-permission yudao-spring-boot-starter-biz-error-code @@ -43,6 +41,7 @@ yudao-spring-boot-starter-flowable yudao-spring-boot-starter-captcha + yudao-spring-boot-starter-websocket yudao-spring-boot-starter-desensitize diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java index 5738ded67..97819f993 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/PageParam.java @@ -15,6 +15,13 @@ public class PageParam implements Serializable { private static final Integer PAGE_NO = 1; private static final Integer PAGE_SIZE = 10; + /** + * 每页条数 - 不分页 + * + * 例如说,导出接口,可以设置 {@link #pageSize} 为 -1 不分页,查询所有数据。 + */ + public static final Integer PAGE_SIZE_NONE = -1; + @Schema(description = "页码,从 1 开始", requiredMode = Schema.RequiredMode.REQUIRED,example = "1") @NotNull(message = "页码不能为空") @Min(value = 1, message = "页码最小值为 1") diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 366e78e23..2d3232978 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -238,7 +238,7 @@ public class CollectionUtils { if (CollUtil.isEmpty(from)) { return null; } - assert from.size() > 0; // 断言,避免告警 + assert !from.isEmpty(); // 断言,避免告警 T t = from.stream().max(Comparator.comparing(valueFunc)).get(); return valueFunc.apply(t); } @@ -280,6 +280,15 @@ public class CollectionUtils { return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toList()); } + public static List convertListByFlatMap(Collection from, + Function mapper, + Function> func) { + if (CollUtil.isEmpty(from)) { + return new ArrayList<>(); + } + return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toList()); + } + public static Set convertSetByFlatMap(Collection from, Function> func) { if (CollUtil.isEmpty(from)) { @@ -288,4 +297,13 @@ public class CollectionUtils { return from.stream().flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet()); } + public static Set convertSetByFlatMap(Collection from, + Function mapper, + Function> func) { + if (CollUtil.isEmpty(from)) { + return new HashSet<>(); + } + return from.stream().map(mapper).flatMap(func).filter(Objects::nonNull).collect(Collectors.toSet()); + } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java index 624a0d9a7..2c7288efa 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/JsonUtils.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.common.util.json; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; @@ -30,6 +31,7 @@ public class JsonUtils { static { objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略 null 值 objectMapper.registerModules(new JavaTimeModule()); // 解决 LocalDateTime 的序列化 } @@ -71,6 +73,20 @@ public class JsonUtils { } } + public static T parseObject(String text, String path, Class clazz) { + if (StrUtil.isEmpty(text)) { + return null; + } + try { + JsonNode treeNode = objectMapper.readTree(text); + JsonNode pathNode = treeNode.path(path); + return objectMapper.readValue(pathNode.toString(), clazz); + } catch (IOException e) { + log.error("json parse err,json:{}", text, e); + throw new RuntimeException(e); + } + } + public static T parseObject(String text, Type type) { if (StrUtil.isEmpty(text)) { return null; @@ -132,6 +148,20 @@ public class JsonUtils { } } + public static List parseArray(String text, String path, Class clazz) { + if (StrUtil.isEmpty(text)) { + return null; + } + try { + JsonNode treeNode = objectMapper.readTree(text); + JsonNode pathNode = treeNode.path(path); + return objectMapper.readValue(pathNode.toString(), objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (IOException e) { + log.error("json parse err,json:{}", text, e); + throw new RuntimeException(e); + } + } + public static JsonNode parseTree(String text) { try { return objectMapper.readTree(text); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java new file mode 100644 index 000000000..e14572a7f --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.common.util.object; + +import cn.hutool.core.bean.BeanUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; + +import java.util.List; + +/** + * Bean 工具类 + * + * 1. 默认使用 {@link cn.hutool.core.bean.BeanUtil} 作为实现类,虽然不同 bean 工具的性能有差别,但是对绝大多数同学的项目,不用在意这点性能 + * 2. 针对复杂的对象转换,可以搜参考 AuthConvert 实现,通过 mapstruct + default 配合实现 + * + * @author 芋道源码 + */ +public class BeanUtils { + + public static T toBean(Object source, Class targetClass) { + return BeanUtil.toBean(source, targetClass); + } + + public static List toBean(List source, Class targetType) { + if (source == null) { + return null; + } + return CollectionUtils.convertList(source, s -> toBean(s, targetType)); + } + + public static PageResult toBean(PageResult source, Class targetType) { + if (source == null) { + return null; + } + return new PageResult<>(toBean(source.getList(), targetType), source.getTotal()); + } + +} \ No newline at end of file diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java index cd5db713c..08cea833f 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/string/StrUtils.java @@ -50,4 +50,20 @@ public class StrUtils { return Arrays.stream(integers).boxed().collect(Collectors.toList()); } + /** + * 移除字符串中,包含指定字符串的行 + * + * @param content 字符串 + * @param sequence 包含的字符串 + * @return 移除后的字符串 + */ + public static String removeLineContains(String content, String sequence) { + if (StrUtil.isEmpty(content) || StrUtil.isEmpty(sequence)) { + return content; + } + return Arrays.stream(content.split("\n")) + .filter(line -> !line.contains(sequence)) + .collect(Collectors.joining("\n")); + } + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Telephone.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Telephone.java new file mode 100644 index 000000000..910601fd0 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Telephone.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.common.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.PARAMETER, + ElementType.TYPE_USE +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = TelephoneValidator.class +) +public @interface Telephone { + + String message() default "电话格式不正确"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/TelephoneValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/TelephoneValidator.java new file mode 100644 index 000000000..d214cfeef --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/TelephoneValidator.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.framework.common.validation; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.PhoneUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class TelephoneValidator implements ConstraintValidator { + + @Override + public void initialize(Telephone annotation) { + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 如果手机号为空,默认不校验,即校验通过 + if (CharSequenceUtil.isEmpty(value)) { + return true; + } + // 校验手机 + return PhoneUtil.isTel(value) || PhoneUtil.isPhone(value); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java index fd175367c..f2131e5b7 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java @@ -49,8 +49,12 @@ public class ErrorCodeAutoGeneratorImpl implements ErrorCodeAutoGenerator { log.info("[execute][解析到错误码数量为 ({}) 个]", autoGenerateDTOs.size()); // 第二步,写入到 system 服务 - errorCodeApi.autoGenerateErrorCodeList(autoGenerateDTOs).checkError(); - log.info("[execute][写入到 system 组件完成]"); + try { + errorCodeApi.autoGenerateErrorCodeList(autoGenerateDTOs).checkError(); + log.info("[execute][写入到 system 组件完成]"); + } catch (Exception ex) { + log.error("[execute][写入到 system 组件失败({})]", ExceptionUtil.getRootCauseMessage(ex)); + } } /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java index 26fb060d2..0bf70211f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java @@ -21,4 +21,14 @@ public interface ErrorCodeLoader { ServiceExceptionUtil.put(code, msg); } + /** + * 刷新错误码 + */ + void refreshErrorCodes(); + + /** + * 加载错误码 + */ + void loadErrorCodes(); + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java index 870c74f11..64d08630d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.errorcode.core.loader; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.exceptions.ExceptionUtil; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.module.system.api.errorcode.ErrorCodeApi; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO; @@ -8,6 +9,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import java.time.LocalDateTime; @@ -43,31 +45,38 @@ public class ErrorCodeLoaderImpl implements ErrorCodeLoader { */ private LocalDateTime maxUpdateTime; + @Override @EventListener(ApplicationReadyEvent.class) + @Async // 异步,保证项目的启动过程,毕竟非关键流程 public void loadErrorCodes() { - this.loadErrorCodes0(); + loadErrorCodes0(); } + @Override @Scheduled(fixedDelay = REFRESH_ERROR_CODE_PERIOD, initialDelay = REFRESH_ERROR_CODE_PERIOD) public void refreshErrorCodes() { - this.loadErrorCodes0(); + loadErrorCodes0(); } private void loadErrorCodes0() { - // 加载错误码 - List errorCodeRespDTOs = errorCodeApi.getErrorCodeList(applicationName, maxUpdateTime).getCheckedData(); - if (CollUtil.isEmpty(errorCodeRespDTOs)) { - return; - } - log.info("[loadErrorCodes0][加载到 ({}) 个错误码]", errorCodeRespDTOs.size()); + try { + // 加载错误码 + List errorCodeRespDTOs = errorCodeApi.getErrorCodeList(applicationName, maxUpdateTime).getCheckedData(); + if (CollUtil.isEmpty(errorCodeRespDTOs)) { + return; + } + log.info("[loadErrorCodes0][加载到 ({}) 个错误码]", errorCodeRespDTOs.size()); - // 刷新错误码的缓存 - errorCodeRespDTOs.forEach(errorCodeRespDTO -> { - // 写入到错误码的缓存 - putErrorCode(errorCodeRespDTO.getCode(), errorCodeRespDTO.getMessage()); - // 记录下更新时间,方便增量更新 - maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeRespDTO.getUpdateTime()); - }); + // 刷新错误码的缓存 + errorCodeRespDTOs.forEach(errorCodeRespDTO -> { + // 写入到错误码的缓存 + putErrorCode(errorCodeRespDTO.getCode(), errorCodeRespDTO.getMessage()); + // 记录下更新时间,方便增量更新 + maxUpdateTime = DateUtils.max(maxUpdateTime, errorCodeRespDTO.getUpdateTime()); + }); + } catch (Exception ex) { + log.error("[loadErrorCodes0][加载错误码失败({})]", ExceptionUtil.getRootCauseMessage(ex)); + } } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java index 05353474c..e31ff2e33 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/OperateLogFrameworkServiceImpl.java @@ -21,7 +21,7 @@ public class OperateLogFrameworkServiceImpl implements OperateLogFrameworkServic @Override @Async public void createOperateLog(OperateLog operateLog) { - OperateLogCreateReqDTO reqDTO = BeanUtil.copyProperties(operateLog, OperateLogCreateReqDTO.class); + OperateLogCreateReqDTO reqDTO = BeanUtil.toBean(operateLog, OperateLogCreateReqDTO.class); operateLogApi.createOperateLog(reqDTO); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index f4f326a65..bd361e9c0 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -16,8 +16,8 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDT import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum; +import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result; import com.github.binarywang.wxpay.bean.request.*; @@ -175,8 +175,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient sendSms(Long logId, String mobile, String apiTemplateId, - List> templateParams); + SmsSendRespDTO sendSms(Long logId, String mobile, String apiTemplateId, + List> templateParams) throws Throwable; /** * 解析接收短信的接收结果 @@ -49,6 +49,6 @@ public interface SmsClient { * @param apiTemplateId 短信 API 的模板编号 * @return 短信模板 */ - SmsCommonResult getSmsTemplate(String apiTemplateId); + SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable; } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCodeMapping.java deleted file mode 100644 index 826306fde..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCodeMapping.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; - -import java.util.function.Function; - -/** - * 将 API 的错误码,转换为通用的错误码 - * - * @see SmsCommonResult - * @see SmsFrameworkErrorCodeConstants - * - * @author 芋道源码 - */ -public interface SmsCodeMapping extends Function { -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCommonResult.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCommonResult.java deleted file mode 100644 index d314de2cd..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsCommonResult.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client; - -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -/** - * 短信的 CommonResult 拓展类 - * - * 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段 - * - * 另外,一些短信平台(例如说阿里云、腾讯云)会返回一个请求编号,用于排查请求失败的问题,我们设置到 {@link #apiRequestId} 字段 - * - * @author 芋道源码 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsCommonResult extends CommonResult { - - /** - * API 返回错误码 - * - * 由于第三方的错误码可能是字符串,所以使用 String 类型 - */ - private String apiCode; - /** - * API 返回提示 - */ - private String apiMsg; - - /** - * API 请求编号 - */ - private String apiRequestId; - - private SmsCommonResult() { - } - - public static SmsCommonResult build(String apiCode, String apiMsg, String apiRequestId, - T data, SmsCodeMapping codeMapping) { - Assert.notNull(codeMapping, "参数 codeMapping 不能为空"); - SmsCommonResult result = new SmsCommonResult().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId); - result.setData(data); - // 翻译错误码 - if (codeMapping != null) { - ErrorCode errorCode = codeMapping.apply(apiCode); - if (errorCode == null) { - errorCode = SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - } - result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg()); - } - return result; - } - - public static SmsCommonResult error(Throwable ex) { - SmsCommonResult result = new SmsCommonResult<>(); - result.setCode(SmsFrameworkErrorCodeConstants.EXCEPTION.getCode()); - result.setMsg(ExceptionUtil.getRootCauseMessage(ex)); - return result; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java index 9d320d57b..ec517508a 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java @@ -10,9 +10,34 @@ import lombok.Data; @Data public class SmsSendRespDTO { + /** + * 是否成功 + */ + private Boolean success; + + /** + * API 请求编号 + */ + private String apiRequestId; + + // ==================== 成功时字段 ==================== + /** * 短信 API 发送返回的序号 */ private String serialNo; + // ==================== 失败时字段 ==================== + + /** + * API 返回错误码 + * + * 由于第三方的错误码可能是字符串,所以使用 String 类型 + */ + private String apiCode; + /** + * API 返回提示 + */ + private String apiMsg; + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java index f91083ddd..42f00f968 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java @@ -1,17 +1,9 @@ package cn.iocoder.yudao.framework.sms.core.client.impl; -import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; -import java.util.List; - /** * 短信客户端的抽象类,提供模板方法,减少子类的冗余代码 * @@ -25,14 +17,9 @@ public abstract class AbstractSmsClient implements SmsClient { * 短信渠道配置 */ protected volatile SmsChannelProperties properties; - /** - * 错误码枚举类 - */ - protected final SmsCodeMapping codeMapping; - public AbstractSmsClient(SmsChannelProperties properties, SmsCodeMapping codeMapping) { - this.properties = prepareProperties(properties); - this.codeMapping = codeMapping; + public AbstractSmsClient(SmsChannelProperties properties) { + this.properties = properties; } /** @@ -54,74 +41,13 @@ public abstract class AbstractSmsClient implements SmsClient { return; } log.info("[refresh][配置({})发生变化,重新初始化]", properties); - this.properties = prepareProperties(properties); // 初始化 this.init(); } - /** - * 在赋值给{@link this#properties}前,子类可根据需要预处理短信渠道配置 - * - * @param properties 数据库中存储的短信渠道配置 - * @return 满足子类实现的短信渠道配置 - */ - protected SmsChannelProperties prepareProperties(SmsChannelProperties properties) { - return properties; - } - @Override public Long getId() { return properties.getId(); } - @Override - public final SmsCommonResult sendSms(Long logId, String mobile, - String apiTemplateId, List> templateParams) { - // 执行短信发送 - SmsCommonResult result; - try { - result = doSendSms(logId, mobile, apiTemplateId, templateParams); - } catch (Throwable ex) { - // 打印异常日志 - log.error("[sendSms][发送短信异常,sendLogId({}) mobile({}) apiTemplateId({}) templateParams({})]", - logId, mobile, apiTemplateId, templateParams, ex); - // 封装返回 - return SmsCommonResult.error(ex); - } - return result; - } - - protected abstract SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) - throws Throwable; - - @Override - public List parseSmsReceiveStatus(String text) throws Throwable { - try { - return doParseSmsReceiveStatus(text); - } catch (Throwable ex) { - log.error("[parseSmsReceiveStatus][text({}) 解析发生异常]", text, ex); - throw ex; - } - } - - protected abstract List doParseSmsReceiveStatus(String text) throws Throwable; - - @Override - public SmsCommonResult getSmsTemplate(String apiTemplateId) { - // 执行短信发送 - SmsCommonResult result; - try { - result = doGetSmsTemplate(apiTemplateId); - } catch (Throwable ex) { - // 打印异常日志 - log.error("[getSmsTemplate][获得短信模板({}) 发生异常]", apiTemplateId, ex); - // 封装返回 - return SmsCommonResult.error(ex); - } - return result; - } - - protected abstract SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable; - } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java index 59723c4c9..d32a5bb11 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java @@ -1,25 +1,21 @@ package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ReflectUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import com.aliyuncs.AcsRequest; -import com.aliyuncs.AcsResponse; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; +import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; -import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.IClientProfile; import com.fasterxml.jackson.annotation.JsonFormat; @@ -31,9 +27,8 @@ import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; import java.util.List; import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; @@ -46,6 +41,11 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE @Slf4j public class AliyunSmsClient extends AbstractSmsClient { + /** + * 调用成功 code + */ + public static final String API_CODE_SUCCESS = "OK"; + /** * REGION, 使用杭州 */ @@ -57,7 +57,7 @@ public class AliyunSmsClient extends AbstractSmsClient { private volatile IAcsClient client; public AliyunSmsClient(SmsChannelProperties properties) { - super(properties, new AliyunSmsCodeMapping()); + super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); } @@ -69,9 +69,9 @@ public class AliyunSmsClient extends AbstractSmsClient { } @Override - protected SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) { - // 构建参数 + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, + List> templateParams) throws Throwable { + // 构建请求 SendSmsRequest request = new SendSmsRequest(); request.setPhoneNumbers(mobile); request.setSignName(properties.getSignature()); @@ -79,34 +79,32 @@ public class AliyunSmsClient extends AbstractSmsClient { request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); request.setOutId(String.valueOf(sendLogId)); // 执行请求 - return invoke(request, response -> new SmsSendRespDTO().setSerialNo(response.getBizId())); + SendSmsResponse response = client.getAcsResponse(request); + return new SmsSendRespDTO().setSuccess(Objects.equals(response.getCode(), API_CODE_SUCCESS)).setSerialNo(response.getBizId()) + .setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage()); } @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { + public List parseSmsReceiveStatus(String text) { List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); - return statuses.stream().map(status -> { - SmsReceiveRespDTO resp = new SmsReceiveRespDTO(); - resp.setSuccess(status.getSuccess()); - resp.setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()); - resp.setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()); - resp.setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId())); - return resp; - }).collect(Collectors.toList()); + return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess()) + .setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()) + .setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()) + .setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()))); } @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) { - // 构建参数 + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { + // 构建请求 QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); request.setTemplateCode(apiTemplateId); // 执行请求 - return invoke(request, response -> { - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); - data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); - data.setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); - return data; - }); + QuerySmsTemplateResponse response = client.getAcsResponse(request); + if (response.getTemplateStatus() == null) { + return null; + } + return new SmsTemplateRespDTO().setId(response.getTemplateCode()).setContent(response.getTemplateContent()) + .setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); } @VisibleForTesting @@ -119,37 +117,10 @@ public class AliyunSmsClient extends AbstractSmsClient { } } - @VisibleForTesting - SmsCommonResult invoke(AcsRequest request, Function responseConsumer) { - try { - // 执行发送. 由于阿里云 sms 短信没有统一的 Response,但是有统一的 code、message、requestId 属性,所以只好反射 - T sendResult = client.getAcsResponse(request); - String code = (String) ReflectUtil.getFieldValue(sendResult, "code"); - String message = (String) ReflectUtil.getFieldValue(sendResult, "message"); - String requestId = (String) ReflectUtil.getFieldValue(sendResult, "requestId"); - // 解析结果 - R data = null; - if (Objects.equals(code, "OK")) { // 请求成功的情况下 - data = responseConsumer.apply(sendResult); - } - // 拼接结果 - return SmsCommonResult.build(code, message, requestId, data, codeMapping); - } catch (ClientException ex) { - return SmsCommonResult.build(ex.getErrCode(), formatResultMsg(ex), ex.getRequestId(), null, codeMapping); - } - } - - private static String formatResultMsg(ClientException ex) { - if (StrUtil.isEmpty(ex.getErrorDescription())) { - return ex.getErrMsg(); - } - return ex.getErrMsg() + " => " + ex.getErrorDescription(); - } - /** * 短信接收状态 * - * 参见 https://help.aliyun.com/document_detail/101867.html 文档 + * 参见 文档 * * @author 芋道源码 */ diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java deleted file mode 100644 index fd188d9b2..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMapping.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; - -/** - * 阿里云的 SmsCodeMapping 实现类 - * - * 参见 https://help.aliyun.com/document_detail/101346.htm 文档 - * - * @author 芋道源码 - */ -public class AliyunSmsCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - switch (apiCode) { - case "OK": return GlobalErrorCodeConstants.SUCCESS; - case "isv.ACCOUNT_NOT_EXISTS": - case "isv.ACCOUNT_ABNORMAL": - case "MissingAccessKeyId": return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID; - case "isp.RAM_PERMISSION_DENY": return SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY; - case "isv.INVALID_JSON_PARAM": - case "isv.INVALID_PARAMETERS": return SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR; - case "isv.BUSINESS_LIMIT_CONTROL": return SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL; - case "isv.DAY_LIMIT_CONTROL": return SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL; - case "isv.SMS_CONTENT_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID; - case "isv.SMS_TEMPLATE_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID; - case "isv.SMS_SIGNATURE_ILLEGAL": - case "isv.SIGN_NAME_ILLEGAL": - case "isv.SMS_SIGN_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID; - case "isv.AMOUNT_NOT_ENOUGH": - case "isv.OUT_OF_SERVICE": return SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH; - case "isv.MOBILE_NUMBER_ILLEGAL": return SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID; - case "isv.TEMPLATE_MISSING_PARAMETERS": return SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR; - default: return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java deleted file mode 100644 index 0a7e48bfc..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkCodeMapping.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.debug; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; - -import java.util.Objects; - -/** - * 钉钉的 SmsCodeMapping 实现类 - * - * @author 芋道源码 - */ -public class DebugDingTalkCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - return Objects.equals(apiCode, "0") ? GlobalErrorCodeConstants.SUCCESS : SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java index cedcfb6dc..315edf942 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java @@ -8,19 +8,19 @@ import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.digest.HmacAlgorithm; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * 基于钉钉 WebHook 实现的调试的短信客户端实现类 @@ -32,7 +32,7 @@ import java.util.Map; public class DebugDingTalkSmsClient extends AbstractSmsClient { public DebugDingTalkSmsClient(SmsChannelProperties properties) { - super(properties, new DebugDingTalkCodeMapping()); + super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); } @@ -42,8 +42,8 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { } @Override - protected SmsCommonResult doSendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) throws Throwable { + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, + String apiTemplateId, List> templateParams) throws Throwable { // 构建请求 String url = buildUrl("robot/send"); Map params = new HashMap<>(); @@ -55,14 +55,15 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params)); // 解析结果 Map responseObj = JsonUtils.parseObject(responseText, Map.class); - return SmsCommonResult.build(MapUtil.getStr(responseObj, "errcode"), MapUtil.getStr(responseObj, "errorMsg"), - null, new SmsSendRespDTO().setSerialNo(StrUtil.uuid()), codeMapping); + String errorCode = MapUtil.getStr(responseObj, "errcode"); + return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid()) + .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg")); } /** * 构建请求地址 * - * 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档 + * 参见 文档 * * @param path 请求路径 * @return 请求地址 @@ -82,15 +83,14 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { } @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { + public List parseSmsReceiveStatus(String text) { throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调"); } @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) { - SmsTemplateRespDTO data = new SmsTemplateRespDTO().setId(apiTemplateId).setContent("") + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) { + return new SmsTemplateRespDTO().setId(apiTemplateId).setContent("") .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(""); - return SmsCommonResult.build("0", "success", null, data, codeMapping); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsChannelProperties.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsChannelProperties.java deleted file mode 100644 index 6b539c602..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsChannelProperties.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import lombok.Data; - -/** - * 腾讯云短信配置实现类 - * 腾讯云发送短信时,需要额外的参数 sdkAppId, - * - * @author shiwp - */ -@Data -public class TencentSmsChannelProperties extends SmsChannelProperties { - - /** - * 应用 id - */ - private String sdkAppId; - - /** - * 考虑到不破坏原有的 apiKey + apiSecret 的结构, - * 所以腾讯云短信存储时,将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。 - * 因此在使用时,需要将 secretId 和 sdkAppId 解析出来,分别存储到对应字段中。 - */ - public static TencentSmsChannelProperties build(SmsChannelProperties properties) { - if (properties instanceof TencentSmsChannelProperties) { - return (TencentSmsChannelProperties) properties; - } - TencentSmsChannelProperties result = BeanUtil.toBean(properties, TencentSmsChannelProperties.class); - String combineKey = properties.getApiKey(); - Assert.notEmpty(combineKey, "apiKey 不能为空"); - String[] keys = combineKey.trim().split(" "); - Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]"); - Assert.notBlank(keys[0], "腾讯云短信 secretId 不能为空"); - Assert.notBlank(keys[1], "腾讯云短信 sdkAppId 不能为空"); - result.setSdkAppId(keys[1]).setApiKey(keys[0]); - return result; - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java index 743c1aed8..eeb287ffe 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java @@ -4,9 +4,7 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; @@ -17,23 +15,22 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; import com.tencentcloudapi.common.Credential; -import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.sms.v20210111.SmsClient; import com.tencentcloudapi.sms.v20210111.models.*; import lombok.Data; import java.time.LocalDateTime; import java.util.List; -import java.util.function.Function; -import java.util.function.Supplier; +import java.util.Objects; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; /** * 腾讯云短信功能实现 - *

- * 参见 https://cloud.tencent.com/document/product/382/52077 + * + * 参见 文档 * * @author shiwp */ @@ -42,7 +39,7 @@ public class TencentSmsClient extends AbstractSmsClient { /** * 调用成功 code */ - public static final String API_SUCCESS_CODE = "Ok"; + public static final String API_CODE_SUCCESS = "Ok"; /** * REGION,使用南京 @@ -51,180 +48,103 @@ public class TencentSmsClient extends AbstractSmsClient { /** * 是否国际/港澳台短信: + * * 0:表示国内短信。 * 1:表示国际/港澳台短信。 */ - private static final long INTERNATIONAL = 0L; + private static final long INTERNATIONAL_CHINA = 0L; private SmsClient client; public TencentSmsClient(SmsChannelProperties properties) { - super(properties, new TencentSmsCodeMapping()); + super(properties); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); + validateSdkAppId(properties); } @Override protected void doInit() { // 实例化一个认证对象,入参需要传入腾讯云账户密钥对 secretId,secretKey - Credential credential = new Credential(properties.getApiKey(), properties.getApiSecret()); + Credential credential = new Credential(getApiKey(), properties.getApiSecret()); client = new SmsClient(credential, ENDPOINT); } + /** + * 参数校验腾讯云的 SDK AppId + * + * 原因是:腾讯云发放短信的时候,需要额外的参数 sdkAppId + * + * 解决方案:考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。 + * + * @param properties 配置 + */ + private static void validateSdkAppId(SmsChannelProperties properties) { + String combineKey = properties.getApiKey(); + Assert.notEmpty(combineKey, "apiKey 不能为空"); + String[] keys = combineKey.trim().split(" "); + Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]"); + } + + private String getSdkAppId() { + return StrUtil.subAfter(properties.getApiKey(), " ", true); + } + + private String getApiKey() { + return StrUtil.subBefore(properties.getApiKey(), " ", true); + } + @Override - protected SmsCommonResult doSendSms(Long sendLogId, - String mobile, - String apiTemplateId, - List> templateParams) throws Throwable { - return invoke(() -> buildSendSmsRequest(sendLogId, mobile, apiTemplateId, templateParams), - this::doSendSms0, - response -> { - SendStatus sendStatus = response.getSendStatusSet()[0]; - return SmsCommonResult.build(sendStatus.getCode(), sendStatus.getMessage(), response.getRequestId(), - new SmsSendRespDTO().setSerialNo(sendStatus.getSerialNo()), codeMapping); - }); - } - - - /** - * 腾讯云发放短信的时候,需要额外的参数 sdkAppId。 - * 考虑到不破坏原有的 apiKey + apiSecret 的结构,所以将 secretId 拼接到 apiKey 字段中,格式为 "secretId sdkAppId"。 - * 因此,这边需要使用 TencentSmsChannelProperties 做拆分,重新封装到 properties 内。 - * - * @param properties 数据库中存储的短信渠道配置 - * @return TencentSmsChannelProperties - */ - @Override - protected SmsChannelProperties prepareProperties(SmsChannelProperties properties) { - return TencentSmsChannelProperties.build(properties); - } - - /** - * 调用腾讯云 SDK 发送短信 - * - * @param request 发送短信请求 - * @return 发送短信响应 - * @throws TencentCloudSDKException SDK 用来封装发送短信失败 - */ - private SendSmsResponse doSendSms0(SendSmsRequest request) throws TencentCloudSDKException { - return client.SendSms(request); - } - - /** - * 封装腾讯云发送短信请求 - * - * @param sendLogId 日志编号 - * @param mobile 手机号 - * @param apiTemplateId 短信 API 的模板编号 - * @param templateParams 短信模板参数。通过 List 数组,保证参数的顺序 - * @return 腾讯云发送短信请求 - */ - private SendSmsRequest buildSendSmsRequest(Long sendLogId, - String mobile, - String apiTemplateId, - List> templateParams) { + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, + String apiTemplateId, List> templateParams) throws Throwable { + // 构建请求 SendSmsRequest request = new SendSmsRequest(); - request.setSmsSdkAppId(((TencentSmsChannelProperties) properties).getSdkAppId()); + request.setSmsSdkAppId(getSdkAppId()); request.setPhoneNumberSet(new String[]{mobile}); request.setSignName(properties.getSignature()); request.setTemplateId(apiTemplateId); request.setTemplateParamSet(ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue()))); request.setSessionContext(JsonUtils.toJsonString(new SessionContext().setLogId(sendLogId))); - return request; + // 执行请求 + SendSmsResponse response = client.SendSms(request); + SendStatus status = response.getSendStatusSet()[0]; + return new SmsSendRespDTO().setSuccess(Objects.equals(status.getCode(), API_CODE_SUCCESS)).setSerialNo(status.getSerialNo()) + .setApiRequestId(response.getRequestId()).setApiCode(status.getCode()).setApiMsg(status.getMessage()); } @Override - protected List doParseSmsReceiveStatus(String text) throws Throwable { + public List parseSmsReceiveStatus(String text) { List callback = JsonUtils.parseArray(text, SmsReceiveStatus.class); - return CollectionUtils.convertList(callback, status -> { - SmsReceiveRespDTO data = new SmsReceiveRespDTO(); - data.setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription()); - data.setReceiveTime(status.getReceiveTime()).setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus())); - data.setMobile(status.getMobile()).setSerialNo(status.getSerialNo()); - SessionContext context; - Long logId; - Assert.notNull(context = status.getSessionContext(), "回执信息中未解析出 context,请联系腾讯云小助手"); - Assert.notNull(logId = context.getLogId(), "回执信息中未解析出 logId,请联系腾讯云小助手"); - data.setLogId(logId); - return data; - }); + return convertList(callback, status -> new SmsReceiveRespDTO() + .setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus())) + .setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription()) + .setMobile(status.getMobile()).setReceiveTime(status.getReceiveTime()) + .setSerialNo(status.getSerialNo()).setLogId(status.getSessionContext().getLogId())); } @Override - protected SmsCommonResult doGetSmsTemplate(String apiTemplateId) throws Throwable { - return invoke(() -> this.buildSmsTemplateStatusRequest(apiTemplateId), - this::doGetSmsTemplate0, - response -> { - SmsTemplateRespDTO data = convertTemplateStatusDTO(response.getDescribeTemplateStatusSet()[0]); - return SmsCommonResult.build(API_SUCCESS_CODE, null, response.getRequestId(), data, codeMapping); - }); + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { + // 构建请求 + DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest(); + request.setTemplateIdSet(new Long[]{Long.parseLong(apiTemplateId)}); + request.setInternational(INTERNATIONAL_CHINA); + // 执行请求 + DescribeSmsTemplateListResponse response = client.DescribeSmsTemplateList(request); + DescribeTemplateListStatus status = response.getDescribeTemplateStatusSet()[0]; + if (status == null || status.getStatusCode() == null) { + return null; + } + return new SmsTemplateRespDTO().setId(status.getTemplateId().toString()).setContent(status.getTemplateContent()) + .setAuditStatus(convertSmsTemplateAuditStatus(status.getStatusCode().intValue())).setAuditReason(status.getReviewReply()); } @VisibleForTesting - SmsTemplateRespDTO convertTemplateStatusDTO(DescribeTemplateListStatus templateStatus) { - if (templateStatus == null) { - return null; + Integer convertSmsTemplateAuditStatus(int templateStatus) { + switch (templateStatus) { + case 1: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); + case 0: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); + case -1: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); + default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); } - SmsTemplateAuditStatusEnum auditStatus; - Assert.notNull(templateStatus.getStatusCode(), - StrUtil.format("短信模版审核状态为 null,模版 id{}", templateStatus.getTemplateId())); - switch (templateStatus.getStatusCode().intValue()) { - case -1: - auditStatus = SmsTemplateAuditStatusEnum.FAIL; - break; - case 0: - auditStatus = SmsTemplateAuditStatusEnum.SUCCESS; - break; - case 1: - auditStatus = SmsTemplateAuditStatusEnum.CHECKING; - break; - default: - throw new IllegalStateException(StrUtil.format("不能解析短信模版审核状态{},模版 id{}", - templateStatus.getStatusCode(), templateStatus.getTemplateId())); - } - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); - data.setId(String.valueOf(templateStatus.getTemplateId())).setContent(templateStatus.getTemplateContent()); - data.setAuditStatus(auditStatus.getStatus()).setAuditReason(templateStatus.getReviewReply()); - return data; - } - - /** - * 封装查询模版审核状态请求 - * @param apiTemplateId api 的模版 id - * @return 查询模版审核状态请求 - */ - private DescribeSmsTemplateListRequest buildSmsTemplateStatusRequest(String apiTemplateId) { - DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest(); - request.setTemplateIdSet(new Long[]{Long.parseLong(apiTemplateId)}); - // 地区 0:表示国内短信。1:表示国际/港澳台短信。 - request.setInternational(INTERNATIONAL); - return request; - } - - /** - * 调用腾讯云 SDK 查询短信模版状态 - * - * @param request 查询短信模版状态请求 - * @return 查询短信模版状态响应 - * @throws TencentCloudSDKException SDK 用来封装查询短信模版状态失败 - */ - private DescribeSmsTemplateListResponse doGetSmsTemplate0(DescribeSmsTemplateListRequest request) throws TencentCloudSDKException { - return client.DescribeSmsTemplateList(request); - } - - SmsCommonResult invoke(Supplier requestSupplier, - SdkFunction responseSupplier, - Function> resultGen) { - // 构建请求body - Q request = requestSupplier.get(); - P response; - // 调用腾讯云发送短信 - try { - response = responseSupplier.apply(request); - } catch (TencentCloudSDKException e) { - // 调用异常,封装结果 - return SmsCommonResult.build(e.getErrorCode(), e.getMessage(), e.getRequestId(), null, codeMapping); - } - return resultGen.apply(response); } @Data @@ -278,7 +198,7 @@ public class TencentSmsClient extends AbstractSmsClient { private String serialNo; /** - * 用户的 session 内容(与发送接口的请求参数SessionContext一致) + * 用户的 session 内容(与发送接口的请求参数 SessionContext 一致) */ @JsonProperty("ext") private SessionContext sessionContext; @@ -293,10 +213,7 @@ public class TencentSmsClient extends AbstractSmsClient { * 发送短信记录id */ private Long logId; - } - private interface SdkFunction { - R apply(T t) throws TencentCloudSDKException; } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMapping.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMapping.java deleted file mode 100644 index 05ad355ef..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMapping.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.client.SmsCodeMapping; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; - -import static cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.*; - -/** - * 腾讯云的 SmsCodeMapping 实现类 - * - * 参见 https://cloud.tencent.com/document/api/382/52075#.E5.85.AC.E5.85.B1.E9.94.99.E8.AF.AF.E7.A0.81 - * - * @author : shiwp - */ -public class TencentSmsCodeMapping implements SmsCodeMapping { - - @Override - public ErrorCode apply(String apiCode) { - switch (apiCode) { - case TencentSmsClient.API_SUCCESS_CODE: return GlobalErrorCodeConstants.SUCCESS; - case "FailedOperation.ContainSensitiveWord": return SMS_SEND_CONTENT_INVALID; - case "FailedOperation.JsonParseFail": - case "MissingParameter.EmptyPhoneNumberSet": - case "LimitExceeded.PhoneNumberCountLimit": - case "FailedOperation.FailResolvePacket": return GlobalErrorCodeConstants.BAD_REQUEST; - case "FailedOperation.InsufficientBalanceInSmsPackage": return SMS_ACCOUNT_MONEY_NOT_ENOUGH; - case "FailedOperation.MarketingSendTimeConstraint": return SMS_SEND_MARKET_LIMIT_CONTROL; - case "FailedOperation.PhoneNumberInBlacklist": return SMS_MOBILE_BLACK; - case "FailedOperation.SignatureIncorrectOrUnapproved": return SMS_SIGN_INVALID; - case "FailedOperation.MissingTemplateToModify": - case "FailedOperation.TemplateIncorrectOrUnapproved": return SMS_TEMPLATE_INVALID; - case "InvalidParameterValue.IncorrectPhoneNumber": return SMS_MOBILE_INVALID; - case "InvalidParameterValue.SdkAppIdNotExist": return SMS_APP_ID_INVALID; - case "InvalidParameterValue.TemplateParameterLengthLimit": - case "InvalidParameterValue.TemplateParameterFormatError": return SMS_TEMPLATE_PARAM_ERROR; - case "LimitExceeded.PhoneNumberDailyLimit": return SMS_SEND_DAY_LIMIT_CONTROL; - case "LimitExceeded.PhoneNumberThirtySecondLimit": - case "LimitExceeded.PhoneNumberOneHourLimit": return SMS_SEND_BUSINESS_LIMIT_CONTROL; - case "UnauthorizedOperation.RequestPermissionDeny": - case "FailedOperation.ForbidAddMarketingTemplates": - case "FailedOperation.NotEnterpriseCertification": - case "UnauthorizedOperation.IndividualUserMarketingSmsPermissionDeny": return SMS_PERMISSION_DENY; - case "UnauthorizedOperation.RequestIpNotInWhitelist": return SMS_IP_DENY; - case "AuthFailure.SecretIdNotFound": return SMS_ACCOUNT_INVALID; - } - return SmsFrameworkErrorCodeConstants.SMS_UNKNOWN; - } -} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java deleted file mode 100644 index 36f9dec82..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientIntegrationTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; - -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.aliyun.AliyunSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link AliyunSmsClient} 的集成测试 - */ -public class AliyunSmsClientIntegrationTest { - - private static AliyunSmsClient smsClient; - - @BeforeAll - public static void before() { - // 创建配置类 - SmsChannelProperties properties = new SmsChannelProperties(); - properties.setId(1L); - properties.setSignature("Ballcat"); - properties.setCode(SmsChannelEnum.ALIYUN.getCode()); - properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY")); - properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY")); - // 创建客户端 - smsClient = new AliyunSmsClient(properties); - smsClient.init(); - } - - @Test - public void testSendSms() { - List> templateParams = new ArrayList<>(); - templateParams.add(new KeyValue<>("code", "1024")); -// templateParams.put("operation", "嘿嘿"); -// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); - SmsCommonResult result = smsClient.sendSms(1L, "15601691399", - "SMS_207945135", templateParams); - System.out.println(result); - } - - @Test - public void testGetSmsTemplate() { - String apiTemplateId = "SMS_2079451351"; - SmsCommonResult result = smsClient.getSmsTemplate(apiTemplateId); - System.out.println(result); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClientIntegrationTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClientIntegrationTest.java deleted file mode 100644 index 47de977cb..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test-integration/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClientIntegrationTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.debug; - -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -/** - * {@link DebugDingTalkSmsClient} 的集成测试 - */ -public class DebugDingTalkSmsClientIntegrationTest { - - private static DebugDingTalkSmsClient smsClient; - - @BeforeAll - public static void init() { - // 创建配置类 - SmsChannelProperties properties = new SmsChannelProperties(); - properties.setId(1L); - properties.setSignature("芋道"); - properties.setCode(SmsChannelEnum.DEBUG_DING_TALK.getCode()); - properties.setApiKey("696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859"); - properties.setApiSecret("SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67"); - // 创建客户端 - smsClient = new DebugDingTalkSmsClient(properties); - smsClient.init(); - } - - @Test - public void testSendSms() { - List> templateParams = new ArrayList<>(); - templateParams.add(new KeyValue<>("code", "1024")); - templateParams.add(new KeyValue<>("operation", "嘿嘿")); -// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams); - SmsCommonResult result = smsClient.sendSms(1L, "15601691399", "4383920", templateParams); - System.out.println(result); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java index 4b02c5121..c60cd26a1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java @@ -1,26 +1,20 @@ package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import com.aliyuncs.AcsRequest; +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; -import com.aliyuncs.exceptions.ClientException; import com.google.common.collect.Lists; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatcher; import org.mockito.InjectMocks; @@ -28,12 +22,10 @@ import org.mockito.Mock; import java.time.LocalDateTime; import java.util.List; -import java.util.function.Function; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.when; @@ -67,8 +59,7 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { } @Test - @SuppressWarnings("unchecked") - public void testDoSendSms() throws ClientException { + public void tesSendSms_success() throws Throwable { // 准备参数 Long sendLogId = randomLongId(); String mobile = randomString(); @@ -87,20 +78,47 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { }))).thenReturn(response); // 调用 - SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); // 断言 + assertTrue(result.getSuccess()); + assertEquals(response.getRequestId(), result.getApiRequestId()); assertEquals(response.getCode(), result.getApiCode()); assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getBizId(), result.getData().getSerialNo()); + assertEquals(response.getBizId(), result.getSerialNo()); } @Test - public void testDoTParseSmsReceiveStatus() throws Throwable { + public void tesSendSms_fail() throws Throwable { + // 准备参数 + Long sendLogId = randomLongId(); + String mobile = randomString(); + String apiTemplateId = randomString(); + List> templateParams = Lists.newArrayList( + new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); + // mock 方法 + SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("ERROR")); + when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { + assertEquals(mobile, acsRequest.getPhoneNumbers()); + assertEquals(properties.getSignature(), acsRequest.getSignName()); + assertEquals(apiTemplateId, acsRequest.getTemplateCode()); + assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); + assertEquals(sendLogId.toString(), acsRequest.getOutId()); + return true; + }))).thenReturn(response); + + // 调用 + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); + // 断言 + assertFalse(result.getSuccess()); + assertEquals(response.getRequestId(), result.getApiRequestId()); + assertEquals(response.getCode(), result.getApiCode()); + assertEquals(response.getMessage(), result.getApiMsg()); + assertEquals(response.getBizId(), result.getSerialNo()); + } + + @Test + public void testParseSmsReceiveStatus() { // 准备参数 String text = "[\n" + " {\n" + @@ -118,20 +136,21 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { // mock 方法 // 调用 - List statuses = smsClient.doParseSmsReceiveStatus(text); + List statuses = smsClient.parseSmsReceiveStatus(text); // 断言 assertEquals(1, statuses.size()); assertTrue(statuses.get(0).getSuccess()); assertEquals("DELIVERED", statuses.get(0).getErrorCode()); assertEquals("用户接收成功", statuses.get(0).getErrorMsg()); assertEquals("13900000001", statuses.get(0).getMobile()); - assertEquals(LocalDateTime.of(2017, 2, 2, 22, 23, 24), statuses.get(0).getReceiveTime()); + assertEquals(LocalDateTime.of(2017, 2, 2, 22, 23, 24), + statuses.get(0).getReceiveTime()); assertEquals("12345", statuses.get(0).getSerialNo()); assertEquals(67890L, statuses.get(0).getLogId()); } @Test - public void testDoGetSmsTemplate() throws ClientException { + public void testGetSmsTemplate() throws Throwable { // 准备参数 String apiTemplateId = randomString(); // mock 方法 @@ -145,18 +164,12 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { }))).thenReturn(response); // 调用 - SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId); + SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId); // 断言 - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getTemplateCode(), result.getData().getId()); - assertEquals(response.getTemplateContent(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(response.getReason(), result.getData().getAuditReason()); + assertEquals(response.getTemplateCode(), result.getId()); + assertEquals(response.getTemplateContent(), result.getContent()); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus()); + assertEquals(response.getReason(), result.getAuditReason()); } @Test @@ -171,55 +184,4 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { "未知审核状态(3)"); } - @Test - @SuppressWarnings("unchecked") - public void testInvoke_throwable() throws ClientException { - // 准备参数 - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); - // mock 方法 - ClientException ex = new ClientException("isv.INVALID_PARAMETERS", "参数不正确", randomString()); - when(client.getAcsResponse(any(AcsRequest.class))).thenThrow(ex); - - // 调用,并断言异常 - SmsCommonResult result = smsClient.invoke(request, null); - // 断言 - assertEquals(ex.getErrCode(), result.getApiCode()); - assertEquals(ex.getErrMsg(), result.getApiMsg()); - Assertions.assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR.getCode(), result.getCode()); - Assertions.assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR.getMsg(), result.getMsg()); - assertEquals(ex.getRequestId(), result.getApiRequestId()); - } - - @Test - public void testInvoke_success() throws ClientException { - // 准备参数 - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); - Function responseConsumer = response -> { - SmsTemplateRespDTO data = new SmsTemplateRespDTO(); - data.setId(response.getTemplateCode()).setContent(response.getTemplateContent()); - data.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(response.getReason()); - return data; - }; - // mock 方法 - QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { - o.setCode("OK"); - o.setTemplateStatus(1); // 设置模板通过 - }); - when(client.getAcsResponse(any(AcsRequest.class))).thenReturn(response); - - // 调用 - SmsCommonResult result = smsClient.invoke(request, responseConsumer); - // 断言 - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getTemplateCode(), result.getData().getId()); - assertEquals(response.getTemplateContent(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(response.getReason(), result.getData().getAuditReason()); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java deleted file mode 100644 index ef8901daf..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsCodeMappingTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; - -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link AliyunSmsCodeMapping} 的单元测试 - * - * @author 芋道源码 - */ -public class AliyunSmsCodeMappingTest extends BaseMockitoUnitTest { - - @InjectMocks - private AliyunSmsCodeMapping codeMapping; - - @Test - public void testApply() { - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply("OK")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("MissingAccessKeyId")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_NOT_EXISTS")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("isv.ACCOUNT_ABNORMAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("isv.DAY_LIMIT_CONTROL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("isv.SMS_CONTENT_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGN_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SIGN_NAME_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("isp.RAM_PERMISSION_DENY")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.OUT_OF_SERVICE")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("isv.AMOUNT_NOT_ENOUGH")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("isv.SMS_TEMPLATE_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("isv.SMS_SIGNATURE_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_PARAMETERS")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_API_PARAM_ERROR, codeMapping.apply("isv.INVALID_JSON_PARAM")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("isv.MOBILE_NUMBER_ILLEGAL")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("isv.TEMPLATE_MISSING_PARAMETERS")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("isv.BUSINESS_LIMIT_CONTROL")); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java index 9269de724..d62eed1e1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java @@ -1,13 +1,10 @@ package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; import cn.hutool.core.util.ReflectUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; @@ -31,7 +28,6 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.when; @@ -78,7 +74,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { } @Test - public void testDoSendSms() throws Throwable { + public void testDoSendSms_success() throws Throwable { // 准备参数 Long sendLogId = randomLongId(); String mobile = randomString(); @@ -94,7 +90,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { o.setSendStatusSet(sendStatuses); SendStatus sendStatus = new SendStatus(); sendStatuses[0] = sendStatus; - sendStatus.setCode(TencentSmsClient.API_SUCCESS_CODE); + sendStatus.setCode(TencentSmsClient.API_CODE_SUCCESS); sendStatus.setMessage("send success"); sendStatus.setSerialNo(serialNo); }); @@ -109,20 +105,58 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { }))).thenReturn(response); // 调用 - SmsCommonResult result = smsClient.doSendSms(sendLogId, mobile, - apiTemplateId, templateParams); + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); // 断言 + assertTrue(result.getSuccess()); + assertEquals(response.getRequestId(), result.getApiRequestId()); assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode()); assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getData().getSerialNo()); + assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo()); } @Test - public void testDoTParseSmsReceiveStatus() throws Throwable { + public void testDoSendSms_fail() throws Throwable { + // 准备参数 + Long sendLogId = randomLongId(); + String mobile = randomString(); + String apiTemplateId = randomString(); + List> templateParams = Lists.newArrayList( + new KeyValue<>("1", 1234), new KeyValue<>("2", "login")); + String requestId = randomString(); + String serialNo = randomString(); + // mock 方法 + SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> { + o.setRequestId(requestId); + SendStatus[] sendStatuses = new SendStatus[1]; + o.setSendStatusSet(sendStatuses); + SendStatus sendStatus = new SendStatus(); + sendStatuses[0] = sendStatus; + sendStatus.setCode("ERROR"); + sendStatus.setMessage("send success"); + sendStatus.setSerialNo(serialNo); + }); + when(client.SendSms(argThat(request -> { + assertEquals(mobile, request.getPhoneNumberSet()[0]); + assertEquals(properties.getSignature(), request.getSignName()); + assertEquals(apiTemplateId, request.getTemplateId()); + assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)), + toJsonString(request.getTemplateParamSet())); + assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId")); + return true; + }))).thenReturn(response); + + // 调用 + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); + // 断言 + assertFalse(result.getSuccess()); + assertEquals(response.getRequestId(), result.getApiRequestId()); + assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode()); + assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg()); + assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo()); + } + + @Test + public void testParseSmsReceiveStatus() { // 准备参数 String text = "[\n" + " {\n" + @@ -139,7 +173,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { // mock 方法 // 调用 - List statuses = smsClient.doParseSmsReceiveStatus(text); + List statuses = smsClient.parseSmsReceiveStatus(text); // 断言 assertEquals(1, statuses.size()); assertTrue(statuses.get(0).getSuccess()); @@ -152,7 +186,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { } @Test - public void testDoGetSmsTemplate() throws Throwable { + public void testGetSmsTemplate() throws Throwable { // 准备参数 Long apiTemplateId = randomLongId(); String requestId = randomString(); @@ -173,50 +207,24 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { }))).thenReturn(response); // 调用 - SmsCommonResult result = smsClient.doGetSmsTemplate(apiTemplateId.toString()); + SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId.toString()); // 断言 - assertEquals(TencentSmsClient.API_SUCCESS_CODE, result.getApiCode()); - assertNull(result.getApiMsg()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getCode(), result.getCode()); - assertEquals(GlobalErrorCodeConstants.SUCCESS.getMsg(), result.getMsg()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - // 断言结果 - assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getData().getId()); - assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getData().getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getData().getAuditStatus()); - assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getData().getAuditReason()); + assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getId()); + assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getContent()); + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus()); + assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getAuditReason()); } @Test - public void testConvertSuccessTemplateStatus() { - testTemplateStatus(SmsTemplateAuditStatusEnum.SUCCESS, 0L); - } - - @Test - public void testConvertCheckingTemplateStatus() { - testTemplateStatus(SmsTemplateAuditStatusEnum.CHECKING, 1L); - } - - @Test - public void testConvertFailTemplateStatus() { - testTemplateStatus(SmsTemplateAuditStatusEnum.FAIL, -1L); - } - - @Test - public void testConvertUnknownTemplateStatus() { - DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus(); - templateStatus.setStatusCode(3L); - Long templateId = randomLongId(); - // 调用,并断言结果 - assertThrows(IllegalStateException.class, () -> smsClient.convertTemplateStatusDTO(templateStatus), - StrUtil.format("不能解析短信模版审核状态[3],模版id[{}]", templateId)); - } - - private void testTemplateStatus(SmsTemplateAuditStatusEnum expected, Long value) { - DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus(); - templateStatus.setStatusCode(value); - SmsTemplateRespDTO result = smsClient.convertTemplateStatusDTO(templateStatus); - assertEquals(expected.getStatus(), result.getAuditStatus()); + public void testConvertSmsTemplateAuditStatus() { + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), + smsClient.convertSmsTemplateAuditStatus(0)); + assertEquals(SmsTemplateAuditStatusEnum.CHECKING.getStatus(), + smsClient.convertSmsTemplateAuditStatus(1)); + assertEquals(SmsTemplateAuditStatusEnum.FAIL.getStatus(), + smsClient.convertSmsTemplateAuditStatus(-1)); + assertThrows(IllegalArgumentException.class, () -> smsClient.convertSmsTemplateAuditStatus(3), + "未知审核状态(3)"); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMappingTest.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMappingTest.java deleted file mode 100644 index ebcdaf18a..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsCodeMappingTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; - -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link TencentSmsCodeMapping} 的单元测试 - * - * @author : shiwp - */ -public class TencentSmsCodeMappingTest extends BaseMockitoUnitTest { - - @InjectMocks - private TencentSmsCodeMapping codeMapping; - - @Test - public void testApply() { - assertEquals(GlobalErrorCodeConstants.SUCCESS, codeMapping.apply(TencentSmsClient.API_SUCCESS_CODE)); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_CONTENT_INVALID, codeMapping.apply("FailedOperation.ContainSensitiveWord")); - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("FailedOperation.JsonParseFail")); - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("MissingParameter.EmptyPhoneNumberSet")); - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("LimitExceeded.PhoneNumberCountLimit")); - assertEquals(GlobalErrorCodeConstants.BAD_REQUEST, codeMapping.apply("FailedOperation.FailResolvePacket")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_MONEY_NOT_ENOUGH, codeMapping.apply("FailedOperation.InsufficientBalanceInSmsPackage")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_MARKET_LIMIT_CONTROL, codeMapping.apply("FailedOperation.MarketingSendTimeConstraint")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_BLACK, codeMapping.apply("FailedOperation.PhoneNumberInBlacklist")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SIGN_INVALID, codeMapping.apply("FailedOperation.SignatureIncorrectOrUnapproved")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("FailedOperation.MissingTemplateToModify")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_INVALID, codeMapping.apply("FailedOperation.TemplateIncorrectOrUnapproved")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_MOBILE_INVALID, codeMapping.apply("InvalidParameterValue.IncorrectPhoneNumber")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_APP_ID_INVALID, codeMapping.apply("InvalidParameterValue.SdkAppIdNotExist")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("InvalidParameterValue.TemplateParameterLengthLimit")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_TEMPLATE_PARAM_ERROR, codeMapping.apply("InvalidParameterValue.TemplateParameterFormatError")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_DAY_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberDailyLimit")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberThirtySecondLimit")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_SEND_BUSINESS_LIMIT_CONTROL, codeMapping.apply("LimitExceeded.PhoneNumberOneHourLimit")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("UnauthorizedOperation.RequestPermissionDeny")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("FailedOperation.ForbidAddMarketingTemplates")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("FailedOperation.NotEnterpriseCertification")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_PERMISSION_DENY, codeMapping.apply("UnauthorizedOperation.IndividualUserMarketingSmsPermissionDeny")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_IP_DENY, codeMapping.apply("UnauthorizedOperation.RequestIpNotInWhitelist")); - assertEquals(SmsFrameworkErrorCodeConstants.SMS_ACCOUNT_INVALID, codeMapping.apply("AuthFailure.SecretIdNotFound")); - } - -} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-social/pom.xml deleted file mode 100644 index eb7d12f34..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - cn.iocoder.cloud - yudao-framework - ${revision} - - jar - 4.0.0 - - yudao-spring-boot-starter-biz-social - ${project.artifactId} - - - - cn.iocoder.cloud - yudao-common - - - - org.springframework.boot - spring-boot-starter-aop - - - - cn.iocoder.cloud - yudao-spring-boot-starter-web - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - com.xingyuv - spring-boot-starter-justauth - - - cn.iocoder.cloud - yudao-spring-boot-starter-redis - - - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java deleted file mode 100644 index 57accd20d..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/config/YudaoSocialAutoConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.framework.social.config; - -import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; -import com.xingyuv.http.HttpUtil; -import com.xingyuv.http.support.hutool.HutoolImpl; -import com.xingyuv.jushauth.cache.AuthStateCache; -import com.xingyuv.justauth.autoconfigure.JustAuthProperties; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; - -/** - * 社交自动装配类 - * - * @author timfruit - * @date 2021-10-30 - */ -@Slf4j -@AutoConfiguration -@EnableConfigurationProperties(JustAuthProperties.class) -public class YudaoSocialAutoConfiguration { - - @Bean - @Primary - @ConditionalOnProperty(prefix = "justauth", value = "enabled", havingValue = "true", matchIfMissing = true) - public YudaoAuthRequestFactory yudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) { - // 需要修改 HttpUtil 使用的实现,避免类报错 - HttpUtil.setHttp(new HutoolImpl()); - // 创建 YudaoAuthRequestFactory - return new YudaoAuthRequestFactory(properties, authStateCache); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java deleted file mode 100644 index 97f29ad63..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/YudaoAuthRequestFactory.java +++ /dev/null @@ -1,94 +0,0 @@ -package cn.iocoder.yudao.framework.social.core; - -import cn.hutool.core.util.EnumUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource; -import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMiniAppRequest; -import cn.iocoder.yudao.framework.social.core.request.AuthWeChatMpRequest; -import com.xingyuv.jushauth.cache.AuthStateCache; -import com.xingyuv.jushauth.config.AuthConfig; -import com.xingyuv.jushauth.config.AuthSource; -import com.xingyuv.jushauth.request.AuthRequest; -import com.xingyuv.justauth.AuthRequestFactory; -import com.xingyuv.justauth.autoconfigure.JustAuthProperties; - -import java.lang.reflect.Method; - -import static com.xingyuv.jushauth.config.AuthDefaultSource.WECHAT_MP; - -/** - * 第三方授权拓展 request 工厂类 - * 为使得拓展配置 {@link AuthConfig} 和默认配置齐平,所以自定义本工厂类 - * - * @author timfruit - * @date 2021-10-31 - */ -public class YudaoAuthRequestFactory extends AuthRequestFactory { - - protected JustAuthProperties properties; - protected AuthStateCache authStateCache; - - /** - * 由于父类 configureHttpConfig 方法是 private 修饰,所以获取后,进行反射调用 - */ - private final Method configureHttpConfigMethod = ReflectUtil.getMethod(AuthRequestFactory.class, - "configureHttpConfig", String.class, AuthConfig.class, JustAuthProperties.JustAuthHttpConfig.class); - - public YudaoAuthRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) { - super(properties, authStateCache); - this.properties = properties; - this.authStateCache = authStateCache; - } - - /** - * 返回 AuthRequest 对象 - * - * @param source {@link AuthSource} - * @return {@link AuthRequest} - */ - @Override - public AuthRequest get(String source) { - // 先尝试获取自定义扩展的 - AuthRequest authRequest = getExtendRequest(source); - // 找不到,使用默认拓展 - if (authRequest == null) { - authRequest = super.get(source); - } - return authRequest; - } - - protected AuthRequest getExtendRequest(String source) { - // TODO 芋艿:临时兼容 justauth 迁移的类型不对问题; - if (WECHAT_MP.name().equalsIgnoreCase(source)) { - AuthConfig config = properties.getType().get(WECHAT_MP.name()); - return new AuthWeChatMpRequest(config, authStateCache); - } - - AuthExtendSource authExtendSource; - try { - authExtendSource = EnumUtil.fromString(AuthExtendSource.class, source.toUpperCase()); - } catch (IllegalArgumentException e) { - // 无自定义匹配 - return null; - } - - // 拓展配置和默认配置齐平,properties 放在一起 - AuthConfig config = properties.getType().get(authExtendSource.name()); - // 找不到对应关系,直接返回空 - if (config == null) { - return null; - } - // 反射调用,配置 http config - ReflectUtil.invoke(this, configureHttpConfigMethod, authExtendSource.name(), config, properties.getHttpConfig()); - - // 获得拓展的 Request - // noinspection SwitchStatementWithTooFewBranches - switch (authExtendSource) { - case WECHAT_MINI_APP: - return new AuthWeChatMiniAppRequest(config, authStateCache); - default: - return null; - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/enums/AuthExtendSource.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/enums/AuthExtendSource.java deleted file mode 100644 index fe4e53c4d..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/enums/AuthExtendSource.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.framework.social.core.enums; - -import com.xingyuv.jushauth.config.AuthSource; -import com.xingyuv.jushauth.request.AuthDefaultRequest; - -/** - * 拓展 JustAuth 各 api 需要的 url, 用枚举类分平台类型管理 - * - * 默认配置 {@link com.xingyuv.jushauth.config.AuthDefaultSource} - * - * @author timfruit - */ -public enum AuthExtendSource implements AuthSource { - - /** - * 微信小程序授权登录 - */ - WECHAT_MINI_APP { - - @Override - public String authorize() { - // 参见 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 文档 - throw new UnsupportedOperationException("不支持获取授权 url,请使用小程序内置函数 wx.login() 登录获取 code"); - } - - @Override - public String accessToken() { - // 参见 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html 文档 - // 获取 openid, unionId , session_key 等字段 - return "https://api.weixin.qq.com/sns/jscode2session"; - } - - @Override - public String userInfo() { - // 参见 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html 文档 - throw new UnsupportedOperationException("不支持获取用户信息 url,请使用小程序内置函数 wx.getUserProfile() 获取用户信息"); - } - - @Override - public Class getTargetClass() { - return null; - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMiniAppRequest.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMiniAppRequest.java deleted file mode 100644 index 964eb31cd..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMiniAppRequest.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.iocoder.yudao.framework.social.core.request; - -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.social.core.enums.AuthExtendSource; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.xingyuv.jushauth.cache.AuthStateCache; -import com.xingyuv.jushauth.config.AuthConfig; -import com.xingyuv.jushauth.exception.AuthException; -import com.xingyuv.jushauth.model.AuthCallback; -import com.xingyuv.jushauth.model.AuthToken; -import com.xingyuv.jushauth.model.AuthUser; -import com.xingyuv.jushauth.request.AuthDefaultRequest; -import com.xingyuv.jushauth.utils.HttpUtils; -import com.xingyuv.jushauth.utils.UrlBuilder; -import lombok.Data; - -/** - * 微信小程序登陆 Request 请求 - * - * 由于 JustAuth 定位是面向 Web 为主的三方登录,所以微信小程序只能自己封装 - * - * @author timfruit - * @date 2021-10-29 - */ -public class AuthWeChatMiniAppRequest extends AuthDefaultRequest { - - public AuthWeChatMiniAppRequest(AuthConfig config, AuthStateCache authStateCache) { - super(config, AuthExtendSource.WECHAT_MINI_APP, authStateCache); - } - - @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { - // 参见 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html 文档 - // 使用 code 获取对应的 openId、unionId 等字段 - String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode())).getBody(); - JSCode2SessionResponse accessTokenObject = JsonUtils.parseObject(response, JSCode2SessionResponse.class); - assert accessTokenObject != null; - checkResponse(accessTokenObject); - // 拼装结果 - return AuthToken.builder() - .openId(accessTokenObject.getOpenid()) - .unionId(accessTokenObject.getUnionId()) - .build(); - } - - @Override - protected AuthUser getUserInfo(AuthToken authToken) { - // 参见 https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html 文档 - // 如果需要用户信息,需要在小程序调用函数后传给后端 - return AuthUser.builder() - .username("") - .nickname("") - .avatar("") - .uuid(authToken.getOpenId()) - .token(authToken) - .source(source.toString()) - .build(); - } - - /** - * 检查响应内容是否正确 - * - * @param response 请求响应内容 - */ - private void checkResponse(JSCode2SessionResponse response) { - if (response.getErrorCode() != 0) { - throw new AuthException(response.getErrorCode(), response.getErrorMsg()); - } - } - - @Override - protected String accessTokenUrl(String code) { - return UrlBuilder.fromBaseUrl(source.accessToken()) - .queryParam("appid", config.getClientId()) - .queryParam("secret", config.getClientSecret()) - .queryParam("js_code", code) - .queryParam("grant_type", "authorization_code") - .build(); - } - - @Data - @SuppressWarnings("SpellCheckingInspection") - private static class JSCode2SessionResponse { - - @JsonProperty("errcode") - private int errorCode; - @JsonProperty("errmsg") - private String errorMsg; - @JsonProperty("session_key") - private String sessionKey; - private String openid; - @JsonProperty("unionid") - private String unionId; - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java deleted file mode 100644 index 13b77cd35..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/java/cn/iocoder/yudao/framework/social/core/request/AuthWeChatMpRequest.java +++ /dev/null @@ -1,178 +0,0 @@ -package cn.iocoder.yudao.framework.social.core.request; - -import com.alibaba.fastjson.JSONObject; -import com.xingyuv.jushauth.cache.AuthStateCache; -import com.xingyuv.jushauth.config.AuthConfig; -import com.xingyuv.jushauth.config.AuthDefaultSource; -import com.xingyuv.jushauth.enums.AuthResponseStatus; -import com.xingyuv.jushauth.enums.AuthUserGender; -import com.xingyuv.jushauth.enums.scope.AuthWechatMpScope; -import com.xingyuv.jushauth.exception.AuthException; -import com.xingyuv.jushauth.model.AuthCallback; -import com.xingyuv.jushauth.model.AuthResponse; -import com.xingyuv.jushauth.model.AuthToken; -import com.xingyuv.jushauth.model.AuthUser; -import com.xingyuv.jushauth.request.AuthDefaultRequest; -import com.xingyuv.jushauth.utils.AuthScopeUtils; -import com.xingyuv.jushauth.utils.GlobalAuthUtils; -import com.xingyuv.jushauth.utils.HttpUtils; -import com.xingyuv.jushauth.utils.UrlBuilder; - -/** - * 微信公众平台登录 - * - * @author yangkai.shen (https://xkcoding.com) - * @since 1.1.0 - */ -public class AuthWeChatMpRequest extends AuthDefaultRequest { - public AuthWeChatMpRequest(AuthConfig config) { - super(config, AuthDefaultSource.WECHAT_MP); - } - - public AuthWeChatMpRequest(AuthConfig config, AuthStateCache authStateCache) { - super(config, AuthDefaultSource.WECHAT_MP, authStateCache); - } - - /** - * 微信的特殊性,此时返回的信息同时包含 openid 和 access_token - * - * @param authCallback 回调返回的参数 - * @return 所有信息 - */ - @Override - protected AuthToken getAccessToken(AuthCallback authCallback) { - return this.getToken(accessTokenUrl(authCallback.getCode())); - } - - @Override - protected AuthUser getUserInfo(AuthToken authToken) { - String openId = authToken.getOpenId(); - - String response = doGetUserInfo(authToken); - JSONObject object = JSONObject.parseObject(response); - - this.checkResponse(object); - - String location = String.format("%s-%s-%s", object.getString("country"), object.getString("province"), object.getString("city")); - - if (object.containsKey("unionid")) { - authToken.setUnionId(object.getString("unionid")); - } - - return AuthUser.builder() - .rawUserInfo(object) - .username(object.getString("nickname")) - .nickname(object.getString("nickname")) - .avatar(object.getString("headimgurl")) - .location(location) - .uuid(openId) - .gender(AuthUserGender.getWechatRealGender(object.getString("sex"))) - .token(authToken) - .source(source.toString()) - .build(); - } - - @Override - public AuthResponse refresh(AuthToken oldToken) { - return AuthResponse.builder() - .code(AuthResponseStatus.SUCCESS.getCode()) - .data(this.getToken(refreshTokenUrl(oldToken.getRefreshToken()))) - .build(); - } - - /** - * 检查响应内容是否正确 - * - * @param object 请求响应内容 - */ - private void checkResponse(JSONObject object) { - if (object.containsKey("errcode")) { - throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg")); - } - } - - /** - * 获取token,适用于获取access_token和刷新token - * - * @param accessTokenUrl 实际请求token的地址 - * @return token对象 - */ - private AuthToken getToken(String accessTokenUrl) { - String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl).getBody(); - JSONObject accessTokenObject = JSONObject.parseObject(response); - - this.checkResponse(accessTokenObject); - - return AuthToken.builder() - .accessToken(accessTokenObject.getString("access_token")) - .refreshToken(accessTokenObject.getString("refresh_token")) - .expireIn(accessTokenObject.getIntValue("expires_in")) - .openId(accessTokenObject.getString("openid")) - .scope(accessTokenObject.getString("scope")) - .build(); - } - - /** - * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} - * - * @param state state 验证授权流程的参数,可以防止csrf - * @return 返回授权地址 - * @since 1.9.3 - */ - @Override - public String authorize(String state) { - return UrlBuilder.fromBaseUrl(source.authorize()) - .queryParam("appid", config.getClientId()) - .queryParam("redirect_uri", GlobalAuthUtils.urlEncode(config.getRedirectUri())) - .queryParam("response_type", "code") - .queryParam("scope", this.getScopes(",", false, AuthScopeUtils.getDefaultScopes(AuthWechatMpScope.values()))) - .queryParam("state", getRealState(state).concat("#wechat_redirect")) - .build(); - } - - /** - * 返回获取accessToken的url - * - * @param code 授权码 - * @return 返回获取accessToken的url - */ - @Override - protected String accessTokenUrl(String code) { - return UrlBuilder.fromBaseUrl(source.accessToken()) - .queryParam("appid", config.getClientId()) - .queryParam("secret", config.getClientSecret()) - .queryParam("code", code) - .queryParam("grant_type", "authorization_code") - .build(); - } - - /** - * 返回获取userInfo的url - * - * @param authToken 用户授权后的token - * @return 返回获取userInfo的url - */ - @Override - protected String userInfoUrl(AuthToken authToken) { - return UrlBuilder.fromBaseUrl(source.userInfo()) - .queryParam("access_token", authToken.getAccessToken()) - .queryParam("openid", authToken.getOpenId()) - .queryParam("lang", "zh_CN") - .build(); - } - - /** - * 返回获取userInfo的url - * - * @param refreshToken getAccessToken方法返回的refreshToken - * @return 返回获取userInfo的url - */ - @Override - protected String refreshTokenUrl(String refreshToken) { - return UrlBuilder.fromBaseUrl(source.refresh()) - .queryParam("appid", config.getClientId()) - .queryParam("grant_type", "refresh_token") - .queryParam("refresh_token", refreshToken) - .build(); - } -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index c7ca9cf4e..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.social.config.YudaoSocialAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java index 1d0dd98f3..e2cbbeb95 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java @@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.BatchStrategies; import org.springframework.data.redis.cache.RedisCacheConfiguration; @@ -98,9 +99,20 @@ public class YudaoTenantAutoConfiguration { // ========== MQ ========== - @Bean - public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() { - return new TenantRedisMessageInterceptor(); + /** + * 多租户 Redis 消息队列的配置类 + * + * 为什么要单独一个配置类呢?如果直接把 TenantRedisMessageInterceptor Bean 的初始化放外面,会报 RedisMessageInterceptor 类不存在的错误 + */ + @Configuration + @ConditionalOnClass(name = "cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate") + public static class TenantRedisMQAutoConfiguration { + + @Bean + public TenantRedisMessageInterceptor tenantRedisMessageInterceptor() { + return new TenantRedisMessageInterceptor(); + } + } @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml deleted file mode 100644 index b21403dc6..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - cn.iocoder.cloud - yudao-framework - ${revision} - - 4.0.0 - yudao-spring-boot-starter-biz-weixin - jar - - ${project.artifactId} - 微信拓展 - 1. 基于 weixin-java-mp 库,对接微信公众号平台。目前主要解决微信公众号的支付场景。 - - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.cloud - yudao-common - - - - - cn.iocoder.cloud - yudao-spring-boot-starter-test - test - - - - - com.github.binarywang - wx-java-mp-spring-boot-starter - - - com.github.binarywang - wx-java-miniapp-spring-boot-starter - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/framework/weixin/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/framework/weixin/package-info.java deleted file mode 100644 index 260476dfb..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/main/java/cn/iocoder/yudao/framework/weixin/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 微信拓展 - * 1. 基于 weixin-java-mp 库,对接微信公众号平台。目前主要解决微信公众号的支付场景。 - * 2. 基于 weixin-java-miniapp 库,对接微信小程序。目前主要解决微信小程序的一键登录场景。 - */ -package cn.iocoder.yudao.framework.weixin; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java b/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java deleted file mode 100644 index 392e651c5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/java/cn/iocoder/yudao/framework/weixin/WxMpServiceTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.framework.weixin; - -import me.chanjar.weixin.common.error.WxErrorException; -import me.chanjar.weixin.mp.api.WxMpService; -import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; - -import javax.annotation.Resource; - -@SpringBootTest(classes = WxMpServiceTest.Application.class) -public class WxMpServiceTest { - - @Resource - private WxMpService wxMpService; - - @Test - public void testGetAccessToken() throws WxErrorException { - String accessToken = wxMpService.getAccessToken(); - System.out.println(accessToken); - } - - @Test - public void testGet() throws WxErrorException { - String jsapiTicket = wxMpService.getJsapiTicket(); - System.out.println(jsapiTicket); - } - - @SpringBootApplication - public static class Application { - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/resources/application.yml b/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/resources/application.yml deleted file mode 100644 index 9b30060a8..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-weixin/src/test-integration/resources/application.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- #################### 微信公众号相关配置 #################### -wx: # 参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 - mp: - # 公众号配置(必填) - app-id: wx041349c6f39b268b - secret: 5abee519483bc9f8cb37ce280e814bd0 - # 存储配置,解决 AccessToken 的跨节点的共享 -# config-storage: -# type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 -# key-prefix: wx # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置 -# http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQConsumerAutoConfiguration.java similarity index 92% rename from yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQAutoConfiguration.java rename to yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQConsumerAutoConfiguration.java index bbc63b719..d02e84b14 100644 --- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQConsumerAutoConfiguration.java @@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.system.SystemUtil; import cn.iocoder.yudao.framework.common.enums.DocumentEnum; import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate; -import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor; import cn.iocoder.yudao.framework.mq.redis.core.job.RedisPendingMessageResendJob; import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener; import cn.iocoder.yudao.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener; @@ -23,7 +22,6 @@ import org.springframework.data.redis.connection.stream.ReadOffset; import org.springframework.data.redis.connection.stream.StreamOffset; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.stream.StreamMessageListenerContainer; @@ -33,30 +31,19 @@ import java.util.List; import java.util.Properties; /** - * 消息队列配置类 + * Redis 消息队列 Consumer 配置类 * * @author 芋道源码 */ @Slf4j @EnableScheduling // 启用定时任务,用于 RedisPendingMessageResendJob 重发消息 @AutoConfiguration(after = YudaoRedisAutoConfiguration.class) -public class YudaoRedisMQAutoConfiguration { - - @Bean - public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate, - List interceptors) { - RedisMQTemplate redisMQTemplate = new RedisMQTemplate(redisTemplate); - // 添加拦截器 - interceptors.forEach(redisMQTemplate::addInterceptor); - return redisMQTemplate; - } - - // ========== 消费者相关 ========== +public class YudaoRedisMQConsumerAutoConfiguration { /** * 创建 Redis Pub/Sub 广播消费的容器 */ - @Bean(initMethod = "start", destroyMethod = "stop") + @Bean @ConditionalOnBean(AbstractRedisChannelMessageListener.class) // 只有 AbstractChannelMessageListener 存在的时候,才需要注册 Redis pubsub 监听 public RedisMessageListenerContainer redisMessageListenerContainer( RedisMQTemplate redisMQTemplate, List> listeners) { diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQProducerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQProducerAutoConfiguration.java new file mode 100644 index 000000000..c1950c489 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/redis/config/YudaoRedisMQProducerAutoConfiguration.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.mq.redis.config; + +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate; +import cn.iocoder.yudao.framework.mq.redis.core.interceptor.RedisMessageInterceptor; +import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.data.redis.core.StringRedisTemplate; + +import java.util.List; + +/** + * Redis 消息队列 Producer 配置类 + * + * @author 芋道源码 + */ +@Slf4j +@AutoConfiguration(after = YudaoRedisAutoConfiguration.class) +public class YudaoRedisMQProducerAutoConfiguration { + + @Bean + public RedisMQTemplate redisMQTemplate(StringRedisTemplate redisTemplate, + List interceptors) { + RedisMQTemplate redisMQTemplate = new RedisMQTemplate(redisTemplate); + // 添加拦截器 + interceptors.forEach(redisMQTemplate::addInterceptor); + return redisMQTemplate; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index f0f201707..4b98f6110 100644 --- a/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-mq/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ -cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQAutoConfiguration +cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQProducerAutoConfiguration +cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration cn.iocoder.yudao.framework.mq.rabbitmq.config.YudaoRabbitMQAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index e40171584..33ccd0437 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -36,18 +36,22 @@ com.oracle.database.jdbc ojdbc8 + true org.postgresql postgresql + true com.microsoft.sqlserver mssql-jdbc + true com.dameng DmJdbcDriver18 + true diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index d70c21626..023611bbc 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.toolkit.Db; import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.interfaces.MPJBaseJoin; import org.apache.ibatis.annotations.Param; import java.util.Collection; @@ -26,6 +27,12 @@ import java.util.List; public interface BaseMapperX extends MPJBaseMapper { default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) { + // 特殊:不分页,直接查询全部 + if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { + List list = selectList(queryWrapper); + return new PageResult<>(list, (long) list.size()); + } + // MyBatis Plus 查询 IPage mpPage = MyBatisUtils.buildPage(pageParam); selectPage(mpPage, queryWrapper); @@ -33,6 +40,13 @@ public interface BaseMapperX extends MPJBaseMapper { return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } + default PageResult selectJoinPage(PageParam pageParam, Class resultTypeClass, MPJBaseJoin joinQueryWrapper) { + IPage mpPage = MyBatisUtils.buildPage(pageParam); + selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper); + // 转换返回 + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); + } + default T selectOne(String field, Object value) { return selectOne(new QueryWrapper().eq(field, value)); } @@ -93,10 +107,15 @@ public interface BaseMapperX extends MPJBaseMapper { return selectList(new LambdaQueryWrapper().in(field, values)); } + @Deprecated default List selectList(SFunction leField, SFunction geField, Object value) { return selectList(new LambdaQueryWrapper().le(leField, value).ge(geField, value)); } + default List selectList(SFunction field1, Object value1, SFunction field2, Object value2) { + return selectList(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); + } + /** * 批量插入,适合大量数据插入 * @@ -128,8 +147,20 @@ public interface BaseMapperX extends MPJBaseMapper { Db.updateBatchById(entities, size); } - default void saveOrUpdateBatch(Collection collection) { + default void insertOrUpdate(T entity) { + Db.saveOrUpdate(entity); + } + + default void insertOrUpdateBatch(Collection collection) { Db.saveOrUpdateBatch(collection); } + default int delete(String field, String value) { + return delete(new QueryWrapper().eq(field, value)); + } + + default int delete(SFunction field, Object value) { + return delete(new LambdaQueryWrapper().eq(field, value)); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-rpc/pom.xml b/yudao-framework/yudao-spring-boot-starter-rpc/pom.xml index 946092b46..767156231 100644 --- a/yudao-framework/yudao-spring-boot-starter-rpc/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-rpc/pom.xml @@ -32,6 +32,10 @@ org.springframework.cloud spring-cloud-starter-openfeign + + io.github.openfeign + feign-okhttp + diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java index 2560dcc0b..3d19f32a6 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/SecurityProperties.java @@ -19,6 +19,13 @@ public class SecurityProperties { */ @NotEmpty(message = "Token Header 不能为空") private String tokenHeader = "Authorization"; + /** + * HTTP 请求时,访问令牌的请求参数 + * + * 初始目的:解决 WebSocket 无法通过 header 传参,只能通过 token 参数拼接 + */ + @NotEmpty(message = "Token Parameter 不能为空") + private String tokenParameter = "token"; /** * mock 模式的开关 @@ -41,5 +48,4 @@ public class SecurityProperties { * PasswordEncoder 加密复杂度,越高开销越大 */ private Integer passwordEncoderLength = 4; - } diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index 24ba15ac0..d03ba3677 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.security.config; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; import cn.iocoder.yudao.framework.web.config.WebProperties; import com.google.common.collect.HashMultimap; @@ -17,6 +18,7 @@ import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; @@ -160,8 +162,17 @@ public class YudaoWebSecurityConfigurerAdapter { continue; } Set urls = entry.getKey().getPatternsCondition().getPatterns(); + // 特殊:使用 @RequestMapping 注解,并且未写 method 属性,此时认为都需要免登录 + Set methods = entry.getKey().getMethodsCondition().getMethods(); + if (CollUtil.isEmpty(methods)) { // + result.putAll(HttpMethod.GET, urls); + result.putAll(HttpMethod.POST, urls); + result.putAll(HttpMethod.PUT, urls); + result.putAll(HttpMethod.DELETE, urls); + continue; + } // 根据请求方法,添加到 result 结果 - entry.getKey().getMethodsCondition().getMethods().forEach(requestMethod -> { + methods.forEach(requestMethod -> { switch (requestMethod) { case GET: result.putAll(HttpMethod.GET, urls); diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java index 6efd48340..1bc13cd3e 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java @@ -48,7 +48,8 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { // 情况二,基于 Token 获得用户 // 注意,这里主要满足直接使用 Nginx 直接转发到 Spring Cloud 服务的场景。 if (loginUser == null) { - String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); + String token = SecurityFrameworkUtils.obtainAuthorization(request, + securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); if (StrUtil.isNotEmpty(token)) { Integer userType = WebFrameworkUtils.getLoginUserType(request); try { @@ -82,7 +83,10 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { return null; } // 用户类型不匹配,无权限 - if (ObjectUtil.notEqual(accessToken.getUserType(), userType)) { + // 注意:只有 /admin-api/* 和 /app-api/* 有 userType,才需要比对用户类型 + // 类似 WebSocket 的 /ws/* 连接地址,是不需要比对用户类型的 + if (userType != null + && ObjectUtil.notEqual(accessToken.getUserType(), userType)) { throw new AccessDeniedException("错误的用户类型"); } // 构建登录用户 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java index 3fa9c0004..8607c31aa 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.security.core.util; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import org.springframework.lang.Nullable; @@ -20,6 +21,9 @@ import java.util.Collections; */ public class SecurityFrameworkUtils { + /** + * HEADER 认证头 value 的前缀 + */ public static final String AUTHORIZATION_BEARER = "Bearer"; public static final String LOGIN_USER_HEADER = "login-user"; @@ -30,19 +34,23 @@ public class SecurityFrameworkUtils { * 从请求中,获得认证 Token * * @param request 请求 - * @param header 认证 Token 对应的 Header 名字 + * @param headerName 认证 Token 对应的 Header 名字 + * @param parameterName 认证 Token 对应的 Parameter 名字 * @return 认证 Token */ - public static String obtainAuthorization(HttpServletRequest request, String header) { - String authorization = request.getHeader(header); - if (!StringUtils.hasText(authorization)) { + public static String obtainAuthorization(HttpServletRequest request, + String headerName, String parameterName) { + // 1. 获得 Token。优先级:Header > Parameter + String token = request.getHeader(headerName); + if (StrUtil.isEmpty(token)) { + token = request.getParameter(parameterName); + } + if (!StringUtils.hasText(token)) { return null; } - int index = authorization.indexOf(AUTHORIZATION_BEARER + " "); - if (index == -1) { // 未找到 - return null; - } - return authorization.substring(index + 7).trim(); + // 2. 去除 Token 中带的 Bearer + int index = token.indexOf(AUTHORIZATION_BEARER + " "); + return index >= 0 ? token.substring(index + 7).trim() : token; } /** diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml new file mode 100644 index 000000000..8fb9cc875 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml @@ -0,0 +1,84 @@ + + + + cn.iocoder.cloud + yudao-framework + ${revision} + + 4.0.0 + yudao-spring-boot-starter-websocket + jar + + ${project.artifactId} + WebSocket 框架,支持多节点的广播 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + cn.iocoder.cloud + yudao-common + + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-security + provided + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-security + provided + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-mq + + + org.springframework.kafka + spring-kafka + true + + + org.springframework.amqp + spring-rabbit + true + + + org.apache.rocketmq + rocketmq-spring-boot-starter + true + + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-biz-tenant + provided + + + + \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketProperties.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketProperties.java new file mode 100644 index 000000000..aa618fb04 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/WebSocketProperties.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.websocket.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * WebSocket 配置项 + * + * @author xingyu4j + */ +@ConfigurationProperties("yudao.websocket") +@Data +@Validated +public class WebSocketProperties { + + /** + * WebSocket 的连接路径 + */ + @NotEmpty(message = "WebSocket 的连接路径不能为空") + private String path = "/ws"; + + /** + * 消息发送器的类型 + * + * 可选值:local、redis、rocketmq、kafka、rabbitmq + */ + @NotNull(message = "WebSocket 的消息发送者不能为空") + private String senderType = "local"; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java new file mode 100644 index 000000000..0f08b7cf5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java @@ -0,0 +1,177 @@ +package cn.iocoder.yudao.framework.websocket.config; + +import cn.iocoder.yudao.framework.mq.redis.config.YudaoRedisMQConsumerAutoConfiguration; +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate; +import cn.iocoder.yudao.framework.websocket.core.handler.JsonWebSocketMessageHandler; +import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; +import cn.iocoder.yudao.framework.websocket.core.security.LoginUserHandshakeInterceptor; +import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer; +import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.local.LocalWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.rabbitmq.RabbitMQWebSocketMessageConsumer; +import cn.iocoder.yudao.framework.websocket.core.sender.rabbitmq.RabbitMQWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.redis.RedisWebSocketMessageConsumer; +import cn.iocoder.yudao.framework.websocket.core.sender.redis.RedisWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.rocketmq.RocketMQWebSocketMessageConsumer; +import cn.iocoder.yudao.framework.websocket.core.sender.rocketmq.RocketMQWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionHandlerDecorator; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManagerImpl; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.server.HandshakeInterceptor; + +import java.util.List; + +/** + * WebSocket 自动配置 + * + * @author xingyu4j + */ +@AutoConfiguration(before = YudaoRedisMQConsumerAutoConfiguration.class) // before YudaoRedisMQConsumerAutoConfiguration 的原因是,需要保证 RedisWebSocketMessageConsumer 先创建,才能创建 RedisMessageListenerContainer +@EnableWebSocket // 开启 websocket +@ConditionalOnProperty(prefix = "yudao.websocket", value = "enable", matchIfMissing = true) // 允许使用 yudao.websocket.enable=false 禁用 websocket +@EnableConfigurationProperties(WebSocketProperties.class) +public class YudaoWebSocketAutoConfiguration { + + @Bean + public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor[] handshakeInterceptors, + WebSocketHandler webSocketHandler, + WebSocketProperties webSocketProperties) { + return registry -> registry + // 添加 WebSocketHandler + .addHandler(webSocketHandler, webSocketProperties.getPath()) + .addInterceptors(handshakeInterceptors) + // 允许跨域,否则前端连接会直接断开 + .setAllowedOriginPatterns("*"); + } + + @Bean + public HandshakeInterceptor handshakeInterceptor() { + return new LoginUserHandshakeInterceptor(); + } + + @Bean + public WebSocketHandler webSocketHandler(WebSocketSessionManager sessionManager, + List> messageListeners) { + // 1. 创建 JsonWebSocketMessageHandler 对象,处理消息 + JsonWebSocketMessageHandler messageHandler = new JsonWebSocketMessageHandler(messageListeners); + // 2. 创建 WebSocketSessionHandlerDecorator 对象,处理连接 + return new WebSocketSessionHandlerDecorator(messageHandler, sessionManager); + } + + @Bean + public WebSocketSessionManager webSocketSessionManager() { + return new WebSocketSessionManagerImpl(); + } + + // ==================== Sender 相关 ==================== + + @Configuration + @ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "local", matchIfMissing = true) + public class LocalWebSocketMessageSenderConfiguration { + + @Bean + public LocalWebSocketMessageSender localWebSocketMessageSender(WebSocketSessionManager sessionManager) { + return new LocalWebSocketMessageSender(sessionManager); + } + + } + + @Configuration + @ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "redis", matchIfMissing = true) + public class RedisWebSocketMessageSenderConfiguration { + + @Bean + public RedisWebSocketMessageSender redisWebSocketMessageSender(WebSocketSessionManager sessionManager, + RedisMQTemplate redisMQTemplate) { + return new RedisWebSocketMessageSender(sessionManager, redisMQTemplate); + } + + @Bean + public RedisWebSocketMessageConsumer redisWebSocketMessageConsumer( + RedisWebSocketMessageSender redisWebSocketMessageSender) { + return new RedisWebSocketMessageConsumer(redisWebSocketMessageSender); + } + + } + + @Configuration + @ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rocketmq", matchIfMissing = true) + public class RocketMQWebSocketMessageSenderConfiguration { + + @Bean + public RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender( + WebSocketSessionManager sessionManager, RocketMQTemplate rocketMQTemplate, + @Value("${yudao.websocket.sender-rocketmq.topic}") String topic) { + return new RocketMQWebSocketMessageSender(sessionManager, rocketMQTemplate, topic); + } + + @Bean + public RocketMQWebSocketMessageConsumer rocketMQWebSocketMessageConsumer( + RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender) { + return new RocketMQWebSocketMessageConsumer(rocketMQWebSocketMessageSender); + } + + } + + @Configuration + @ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "rabbitmq", matchIfMissing = true) + public class RabbitMQWebSocketMessageSenderConfiguration { + + @Bean + public RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender( + WebSocketSessionManager sessionManager, RabbitTemplate rabbitTemplate, + TopicExchange websocketTopicExchange) { + return new RabbitMQWebSocketMessageSender(sessionManager, rabbitTemplate, websocketTopicExchange); + } + + @Bean + public RabbitMQWebSocketMessageConsumer rabbitMQWebSocketMessageConsumer( + RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender) { + return new RabbitMQWebSocketMessageConsumer(rabbitMQWebSocketMessageSender); + } + + /** + * 创建 Topic Exchange + */ + @Bean + public TopicExchange websocketTopicExchange(@Value("${yudao.websocket.sender-rabbitmq.exchange}") String exchange) { + return new TopicExchange(exchange, + true, // durable: 是否持久化 + false); // exclusive: 是否排它 + } + + } + + @Configuration + @ConditionalOnProperty(prefix = "yudao.websocket", name = "sender-type", havingValue = "kafka", matchIfMissing = true) + public class KafkaWebSocketMessageSenderConfiguration { + + @Bean + public KafkaWebSocketMessageSender kafkaWebSocketMessageSender( + WebSocketSessionManager sessionManager, KafkaTemplate kafkaTemplate, + @Value("${yudao.websocket.sender-kafka.topic}") String topic) { + return new KafkaWebSocketMessageSender(sessionManager, kafkaTemplate, topic); + } + + @Bean + public KafkaWebSocketMessageConsumer kafkaWebSocketMessageConsumer( + KafkaWebSocketMessageSender kafkaWebSocketMessageSender) { + return new KafkaWebSocketMessageConsumer(kafkaWebSocketMessageSender); + } + + } + +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java new file mode 100644 index 000000000..120f529c2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/handler/JsonWebSocketMessageHandler.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.framework.websocket.core.handler; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.TypeUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; +import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; +import cn.iocoder.yudao.framework.websocket.core.message.JsonWebSocketMessage; +import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; + +/** + * JSON 格式 {@link WebSocketHandler} 实现类 + * + * 基于 {@link JsonWebSocketMessage#getType()} 消息类型,调度到对应的 {@link WebSocketMessageListener} 监听器。 + * + * @author 芋道源码 + */ +@Slf4j +public class JsonWebSocketMessageHandler extends TextWebSocketHandler { + + /** + * type 与 WebSocketMessageListener 的映射 + */ + private final Map> listeners = new HashMap<>(); + + @SuppressWarnings({"rawtypes", "unchecked"}) + public JsonWebSocketMessageHandler(List listenersList) { + listenersList.forEach((Consumer) + listener -> listeners.put(listener.getType(), listener)); + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 1.1 空消息,跳过 + if (message.getPayloadLength() == 0) { + return; + } + // 1.2 ping 心跳消息,直接返回 pong 消息。 + if (message.getPayloadLength() == 4 && Objects.equals(message.getPayload(), "ping")) { + session.sendMessage(new TextMessage("pong")); + return; + } + + // 2.1 解析消息 + try { + JsonWebSocketMessage jsonMessage = JsonUtils.parseObject(message.getPayload(), JsonWebSocketMessage.class); + if (jsonMessage == null) { + log.error("[handleTextMessage][session({}) message({}) 解析为空]", session.getId(), message.getPayload()); + return; + } + if (StrUtil.isEmpty(jsonMessage.getType())) { + log.error("[handleTextMessage][session({}) message({}) 类型为空]", session.getId(), message.getPayload()); + return; + } + // 2.2 获得对应的 WebSocketMessageListener + WebSocketMessageListener messageListener = listeners.get(jsonMessage.getType()); + if (messageListener == null) { + log.error("[handleTextMessage][session({}) message({}) 监听器为空]", session.getId(), message.getPayload()); + return; + } + // 2.3 处理消息 + Type type = TypeUtil.getTypeArgument(messageListener.getClass(), 0); + Object messageObj = JsonUtils.parseObject(jsonMessage.getContent(), type); + Long tenantId = WebSocketFrameworkUtils.getTenantId(session); + TenantUtils.execute(tenantId, () -> messageListener.onMessage(session, messageObj)); + } catch (Throwable ex) { + log.error("[handleTextMessage][session({}) message({}) 处理异常]", session.getId(), message.getPayload()); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/listener/WebSocketMessageListener.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/listener/WebSocketMessageListener.java new file mode 100644 index 000000000..f3a62cc39 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/listener/WebSocketMessageListener.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.framework.websocket.core.listener; + +import cn.iocoder.yudao.framework.websocket.core.message.JsonWebSocketMessage; +import org.springframework.web.socket.WebSocketSession; + +/** + * WebSocket 消息监听器接口 + * + * 目的:前端发送消息给后端后,处理对应 {@link #getType()} 类型的消息 + * + * @param 泛型,消息类型 + */ +public interface WebSocketMessageListener { + + /** + * 处理消息 + * + * @param session Session + * @param message 消息 + */ + void onMessage(WebSocketSession session, T message); + + /** + * 获得消息类型 + * + * @see JsonWebSocketMessage#getType() + * @return 消息类型 + */ + String getType(); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/message/JsonWebSocketMessage.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/message/JsonWebSocketMessage.java new file mode 100644 index 000000000..0a55cd691 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/message/JsonWebSocketMessage.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.framework.websocket.core.message; + +import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; +import lombok.Data; + +import java.io.Serializable; + +/** + * JSON 格式的 WebSocket 消息帧 + * + * @author 芋道源码 + */ +@Data +public class JsonWebSocketMessage implements Serializable { + + /** + * 消息类型 + * + * 目的:用于分发到对应的 {@link WebSocketMessageListener} 实现类 + */ + private String type; + /** + * 消息内容 + * + * 要求 JSON 对象 + */ + private String content; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/security/LoginUserHandshakeInterceptor.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/security/LoginUserHandshakeInterceptor.java new file mode 100644 index 000000000..3a31825f5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/security/LoginUserHandshakeInterceptor.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.framework.websocket.core.security; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.server.HandshakeInterceptor; + +import java.util.Map; + +/** + * 登录用户的 {@link HandshakeInterceptor} 实现类 + * + * 流程如下: + * 1. 前端连接 websocket 时,会通过拼接 ?token={token} 到 ws:// 连接后,这样它可以被 {@link TokenAuthenticationFilter} 所认证通过 + * 2. {@link LoginUserHandshakeInterceptor} 负责把 {@link LoginUser} 添加到 {@link WebSocketSession} 中 + * + * @author 芋道源码 + */ +public class LoginUserHandshakeInterceptor implements HandshakeInterceptor { + + @Override + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, + WebSocketHandler wsHandler, Map attributes) { + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + if (loginUser != null) { + WebSocketFrameworkUtils.setLoginUser(loginUser, attributes); + } + return true; + } + + @Override + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, + WebSocketHandler wsHandler, Exception exception) { + // do nothing + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/security/WebSocketAuthorizeRequestsCustomizer.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/security/WebSocketAuthorizeRequestsCustomizer.java new file mode 100644 index 000000000..5614f05ce --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/security/WebSocketAuthorizeRequestsCustomizer.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.websocket.core.security; + +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; +import cn.iocoder.yudao.framework.websocket.config.WebSocketProperties; +import lombok.RequiredArgsConstructor; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; + +/** + * WebSocket 的权限自定义 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +public class WebSocketAuthorizeRequestsCustomizer extends AuthorizeRequestsCustomizer { + + private final WebSocketProperties webSocketProperties; + + @Override + public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) { + registry.antMatchers(webSocketProperties.getPath()).permitAll(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java new file mode 100644 index 000000000..4e0db44c9 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/AbstractWebSocketMessageSender.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.framework.websocket.core.sender; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.websocket.core.message.JsonWebSocketMessage; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * WebSocketMessageSender 实现类 + * + * @author 芋道源码 + */ +@Slf4j +@RequiredArgsConstructor +public abstract class AbstractWebSocketMessageSender implements WebSocketMessageSender { + + private final WebSocketSessionManager sessionManager; + + @Override + public void send(Integer userType, Long userId, String messageType, String messageContent) { + send(null, userType, userId, messageType, messageContent); + } + + @Override + public void send(Integer userType, String messageType, String messageContent) { + send(null, userType, null, messageType, messageContent); + } + + @Override + public void send(String sessionId, String messageType, String messageContent) { + send(sessionId, null, null, messageType, messageContent); + } + + /** + * 发送消息 + * + * @param sessionId Session 编号 + * @param userType 用户类型 + * @param userId 用户编号 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + public void send(String sessionId, Integer userType, Long userId, String messageType, String messageContent) { + // 1. 获得 Session 列表 + List sessions = Collections.emptyList(); + if (StrUtil.isNotEmpty(sessionId)) { + WebSocketSession session = sessionManager.getSession(sessionId); + if (session != null) { + sessions = Collections.singletonList(session); + } + } else if (userType != null && userId != null) { + sessions = (List) sessionManager.getSessionList(userType, userId); + } else if (userType != null) { + sessions = (List) sessionManager.getSessionList(userType); + } + if (CollUtil.isEmpty(sessions)) { + log.info("[send][sessionId({}) userType({}) userId({}) messageType({}) messageContent({}) 未匹配到会话]", + sessionId, userType, userId, messageType, messageContent); + } + // 2. 执行发送 + doSend(sessions, messageType, messageContent); + } + + /** + * 发送消息的具体实现 + * + * @param sessions Session 列表 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + public void doSend(Collection sessions, String messageType, String messageContent) { + JsonWebSocketMessage message = new JsonWebSocketMessage().setType(messageType).setContent(messageContent); + String payload = JsonUtils.toJsonString(message); // 关键,使用 JSON 序列化 + sessions.forEach(session -> { + // 1. 各种校验,保证 Session 可以被发送 + if (session == null) { + log.error("[doSend][session 为空, message({})]", message); + return; + } + if (!session.isOpen()) { + log.error("[doSend][session({}) 已关闭, message({})]", session.getId(), message); + return; + } + // 2. 执行发送 + try { + session.sendMessage(new TextMessage(payload)); + log.info("[doSend][session({}) 发送消息成功,message({})]", session.getId(), message); + } catch (IOException ex) { + log.error("[doSend][session({}) 发送消息失败,message({})]", session.getId(), message, ex); + } + }); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java new file mode 100644 index 000000000..9f75ad52d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/WebSocketMessageSender.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.framework.websocket.core.sender; + +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; + +/** + * WebSocket 消息的发送器接口 + * + * @author 芋道源码 + */ +public interface WebSocketMessageSender { + + /** + * 发送消息给指定用户 + * + * @param userType 用户类型 + * @param userId 用户编号 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + void send(Integer userType, Long userId, String messageType, String messageContent); + + /** + * 发送消息给指定用户类型 + * + * @param userType 用户类型 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + void send(Integer userType, String messageType, String messageContent); + + /** + * 发送消息给指定 Session + * + * @param sessionId Session 编号 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + void send(String sessionId, String messageType, String messageContent); + + default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) { + send(userType, userId, messageType, JsonUtils.toJsonString(messageContent)); + } + + default void sendObject(Integer userType, String messageType, Object messageContent) { + send(userType, messageType, JsonUtils.toJsonString(messageContent)); + } + + default void sendObject(String sessionId, String messageType, Object messageContent) { + send(sessionId, messageType, JsonUtils.toJsonString(messageContent)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessage.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessage.java new file mode 100644 index 000000000..5a4cf5311 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessage.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.kafka; + +import lombok.Data; + +/** + * Kafka 广播 WebSocket 的消息 + * + * @author 芋道源码 + */ +@Data +public class KafkaWebSocketMessage { + + /** + * Session 编号 + */ + private String sessionId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 用户编号 + */ + private Long userId; + + /** + * 消息类型 + */ + private String messageType; + /** + * 消息内容 + */ + private String messageContent; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessageConsumer.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessageConsumer.java new file mode 100644 index 000000000..201e65d81 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessageConsumer.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.kafka; + +import lombok.RequiredArgsConstructor; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.kafka.annotation.KafkaListener; + +/** + * {@link KafkaWebSocketMessage} 广播消息的消费者,真正把消息发送出去 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +public class KafkaWebSocketMessageConsumer { + + private final KafkaWebSocketMessageSender rabbitMQWebSocketMessageSender; + + @RabbitHandler + @KafkaListener( + topics = "${yudao.websocket.sender-kafka.topic}", + // 在 Group 上,使用 UUID 生成其后缀。这样,启动的 Consumer 的 Group 不同,以达到广播消费的目的 + groupId = "${yudao.websocket.sender-kafka.consumer-group}" + "-" + "#{T(java.util.UUID).randomUUID()}") + public void onMessage(KafkaWebSocketMessage message) { + rabbitMQWebSocketMessageSender.send(message.getSessionId(), + message.getUserType(), message.getUserId(), + message.getMessageType(), message.getMessageContent()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessageSender.java new file mode 100644 index 000000000..47bb598ad --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/kafka/KafkaWebSocketMessageSender.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.kafka; + +import cn.iocoder.yudao.framework.websocket.core.sender.AbstractWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import lombok.extern.slf4j.Slf4j; +import org.springframework.kafka.core.KafkaTemplate; + +import java.util.concurrent.ExecutionException; + +/** + * 基于 Kafka 的 {@link WebSocketMessageSender} 实现类 + * + * @author 芋道源码 + */ +@Slf4j +public class KafkaWebSocketMessageSender extends AbstractWebSocketMessageSender { + + private final KafkaTemplate kafkaTemplate; + + private final String topic; + + public KafkaWebSocketMessageSender(WebSocketSessionManager sessionManager, + KafkaTemplate kafkaTemplate, + String topic) { + super(sessionManager); + this.kafkaTemplate = kafkaTemplate; + this.topic = topic; + } + + @Override + public void send(Integer userType, Long userId, String messageType, String messageContent) { + sendKafkaMessage(null, userId, userType, messageType, messageContent); + } + + @Override + public void send(Integer userType, String messageType, String messageContent) { + sendKafkaMessage(null, null, userType, messageType, messageContent); + } + + @Override + public void send(String sessionId, String messageType, String messageContent) { + sendKafkaMessage(sessionId, null, null, messageType, messageContent); + } + + /** + * 通过 Kafka 广播消息 + * + * @param sessionId Session 编号 + * @param userId 用户编号 + * @param userType 用户类型 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + private void sendKafkaMessage(String sessionId, Long userId, Integer userType, + String messageType, String messageContent) { + KafkaWebSocketMessage mqMessage = new KafkaWebSocketMessage() + .setSessionId(sessionId).setUserId(userId).setUserType(userType) + .setMessageType(messageType).setMessageContent(messageContent); + try { + kafkaTemplate.send(topic, mqMessage).get(); + } catch (InterruptedException | ExecutionException e) { + log.error("[sendKafkaMessage][发送消息({}) 到 Kafka 失败]", mqMessage, e); + } + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/local/LocalWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/local/LocalWebSocketMessageSender.java new file mode 100644 index 000000000..66640ef34 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/local/LocalWebSocketMessageSender.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.local; + +import cn.iocoder.yudao.framework.websocket.core.sender.AbstractWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; + +/** + * 本地的 {@link WebSocketMessageSender} 实现类 + * + * 注意:仅仅适合单机场景!!! + * + * @author 芋道源码 + */ +public class LocalWebSocketMessageSender extends AbstractWebSocketMessageSender { + + public LocalWebSocketMessageSender(WebSocketSessionManager sessionManager) { + super(sessionManager); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessage.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessage.java new file mode 100644 index 000000000..80a4bc176 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessage.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.rabbitmq; + +import lombok.Data; + +import java.io.Serializable; + +/** + * RabbitMQ 广播 WebSocket 的消息 + * + * @author 芋道源码 + */ +@Data +public class RabbitMQWebSocketMessage implements Serializable { + + /** + * Session 编号 + */ + private String sessionId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 用户编号 + */ + private Long userId; + + /** + * 消息类型 + */ + private String messageType; + /** + * 消息内容 + */ + private String messageContent; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageConsumer.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageConsumer.java new file mode 100644 index 000000000..59e382421 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageConsumer.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.rabbitmq; + +import lombok.RequiredArgsConstructor; +import org.springframework.amqp.core.ExchangeTypes; +import org.springframework.amqp.rabbit.annotation.*; + +/** + * {@link RabbitMQWebSocketMessage} 广播消息的消费者,真正把消息发送出去 + * + * @author 芋道源码 + */ +@RabbitListener( + bindings = @QueueBinding( + value = @Queue( + // 在 Queue 的名字上,使用 UUID 生成其后缀。这样,启动的 Consumer 的 Queue 不同,以达到广播消费的目的 + name = "${yudao.websocket.sender-rabbitmq.queue}" + "-" + "#{T(java.util.UUID).randomUUID()}", + // Consumer 关闭时,该队列就可以被自动删除了 + autoDelete = "true" + ), + exchange = @Exchange( + name = "${yudao.websocket.sender-rabbitmq.exchange}", + type = ExchangeTypes.TOPIC, + declare = "false" + ) + ) +) +@RequiredArgsConstructor +public class RabbitMQWebSocketMessageConsumer { + + private final RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender; + + @RabbitHandler + public void onMessage(RabbitMQWebSocketMessage message) { + rabbitMQWebSocketMessageSender.send(message.getSessionId(), + message.getUserType(), message.getUserId(), + message.getMessageType(), message.getMessageContent()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageSender.java new file mode 100644 index 000000000..065a5d6bf --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rabbitmq/RabbitMQWebSocketMessageSender.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.rabbitmq; + +import cn.iocoder.yudao.framework.websocket.core.sender.AbstractWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.rabbit.core.RabbitTemplate; + +/** + * 基于 RabbitMQ 的 {@link WebSocketMessageSender} 实现类 + * + * @author 芋道源码 + */ +@Slf4j +public class RabbitMQWebSocketMessageSender extends AbstractWebSocketMessageSender { + + private final RabbitTemplate rabbitTemplate; + + private final TopicExchange topicExchange; + + public RabbitMQWebSocketMessageSender(WebSocketSessionManager sessionManager, + RabbitTemplate rabbitTemplate, + TopicExchange topicExchange) { + super(sessionManager); + this.rabbitTemplate = rabbitTemplate; + this.topicExchange = topicExchange; + } + + @Override + public void send(Integer userType, Long userId, String messageType, String messageContent) { + sendRabbitMQMessage(null, userId, userType, messageType, messageContent); + } + + @Override + public void send(Integer userType, String messageType, String messageContent) { + sendRabbitMQMessage(null, null, userType, messageType, messageContent); + } + + @Override + public void send(String sessionId, String messageType, String messageContent) { + sendRabbitMQMessage(sessionId, null, null, messageType, messageContent); + } + + /** + * 通过 RabbitMQ 广播消息 + * + * @param sessionId Session 编号 + * @param userId 用户编号 + * @param userType 用户类型 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + private void sendRabbitMQMessage(String sessionId, Long userId, Integer userType, + String messageType, String messageContent) { + RabbitMQWebSocketMessage mqMessage = new RabbitMQWebSocketMessage() + .setSessionId(sessionId).setUserId(userId).setUserType(userType) + .setMessageType(messageType).setMessageContent(messageContent); + rabbitTemplate.convertAndSend(topicExchange.getName(), null, mqMessage); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessage.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessage.java new file mode 100644 index 000000000..fb9ea0ca0 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessage.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.redis; + +import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessage; +import lombok.Data; + +/** + * Redis 广播 WebSocket 的消息 + */ +@Data +public class RedisWebSocketMessage extends AbstractRedisChannelMessage { + + /** + * Session 编号 + */ + private String sessionId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 用户编号 + */ + private Long userId; + + /** + * 消息类型 + */ + private String messageType; + /** + * 消息内容 + */ + private String messageContent; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessageConsumer.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessageConsumer.java new file mode 100644 index 000000000..abce00695 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessageConsumer.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.redis; + +import cn.iocoder.yudao.framework.mq.redis.core.pubsub.AbstractRedisChannelMessageListener; +import lombok.RequiredArgsConstructor; + +/** + * {@link RedisWebSocketMessage} 广播消息的消费者,真正把消息发送出去 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +public class RedisWebSocketMessageConsumer extends AbstractRedisChannelMessageListener { + + private final RedisWebSocketMessageSender redisWebSocketMessageSender; + + @Override + public void onMessage(RedisWebSocketMessage message) { + redisWebSocketMessageSender.send(message.getSessionId(), + message.getUserType(), message.getUserId(), + message.getMessageType(), message.getMessageContent()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessageSender.java new file mode 100644 index 000000000..d6004ac6d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/redis/RedisWebSocketMessageSender.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.redis; + +import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate; +import cn.iocoder.yudao.framework.websocket.core.sender.AbstractWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import lombok.extern.slf4j.Slf4j; + +/** + * 基于 Redis 的 {@link WebSocketMessageSender} 实现类 + * + * @author 芋道源码 + */ +@Slf4j +public class RedisWebSocketMessageSender extends AbstractWebSocketMessageSender { + + private final RedisMQTemplate redisMQTemplate; + + public RedisWebSocketMessageSender(WebSocketSessionManager sessionManager, + RedisMQTemplate redisMQTemplate) { + super(sessionManager); + this.redisMQTemplate = redisMQTemplate; + } + + @Override + public void send(Integer userType, Long userId, String messageType, String messageContent) { + sendRedisMessage(null, userId, userType, messageType, messageContent); + } + + @Override + public void send(Integer userType, String messageType, String messageContent) { + sendRedisMessage(null, null, userType, messageType, messageContent); + } + + @Override + public void send(String sessionId, String messageType, String messageContent) { + sendRedisMessage(sessionId, null, null, messageType, messageContent); + } + + /** + * 通过 Redis 广播消息 + * + * @param sessionId Session 编号 + * @param userId 用户编号 + * @param userType 用户类型 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + private void sendRedisMessage(String sessionId, Long userId, Integer userType, + String messageType, String messageContent) { + RedisWebSocketMessage mqMessage = new RedisWebSocketMessage() + .setSessionId(sessionId).setUserId(userId).setUserType(userType) + .setMessageType(messageType).setMessageContent(messageContent); + redisMQTemplate.send(mqMessage); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessage.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessage.java new file mode 100644 index 000000000..91570e3e3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessage.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.rocketmq; + +import lombok.Data; + +/** + * RocketMQ 广播 WebSocket 的消息 + * + * @author 芋道源码 + */ +@Data +public class RocketMQWebSocketMessage { + + /** + * Session 编号 + */ + private String sessionId; + /** + * 用户类型 + */ + private Integer userType; + /** + * 用户编号 + */ + private Long userId; + + /** + * 消息类型 + */ + private String messageType; + /** + * 消息内容 + */ + private String messageContent; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageConsumer.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageConsumer.java new file mode 100644 index 000000000..ab2e2c4dc --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageConsumer.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.rocketmq; + +import lombok.RequiredArgsConstructor; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; + +/** + * {@link RocketMQWebSocketMessage} 广播消息的消费者,真正把消息发送出去 + * + * @author 芋道源码 + */ +@RocketMQMessageListener( // 重点:添加 @RocketMQMessageListener 注解,声明消费的 topic + topic = "${yudao.websocket.sender-rocketmq.topic}", + consumerGroup = "${yudao.websocket.sender-rocketmq.consumer-group}", + messageModel = MessageModel.BROADCASTING // 设置为广播模式,保证每个实例都能收到消息 +) +@RequiredArgsConstructor +public class RocketMQWebSocketMessageConsumer implements RocketMQListener { + + private final RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender; + + @Override + public void onMessage(RocketMQWebSocketMessage message) { + rocketMQWebSocketMessageSender.send(message.getSessionId(), + message.getUserType(), message.getUserId(), + message.getMessageType(), message.getMessageContent()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageSender.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageSender.java new file mode 100644 index 000000000..ed059bac4 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/sender/rocketmq/RocketMQWebSocketMessageSender.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.framework.websocket.core.sender.rocketmq; + +import cn.iocoder.yudao.framework.websocket.core.sender.AbstractWebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.session.WebSocketSessionManager; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.core.RocketMQTemplate; + +/** + * 基于 RocketMQ 的 {@link WebSocketMessageSender} 实现类 + * + * @author 芋道源码 + */ +@Slf4j +public class RocketMQWebSocketMessageSender extends AbstractWebSocketMessageSender { + + private final RocketMQTemplate rocketMQTemplate; + + private final String topic; + + public RocketMQWebSocketMessageSender(WebSocketSessionManager sessionManager, + RocketMQTemplate rocketMQTemplate, + String topic) { + super(sessionManager); + this.rocketMQTemplate = rocketMQTemplate; + this.topic = topic; + } + + @Override + public void send(Integer userType, Long userId, String messageType, String messageContent) { + sendRocketMQMessage(null, userId, userType, messageType, messageContent); + } + + @Override + public void send(Integer userType, String messageType, String messageContent) { + sendRocketMQMessage(null, null, userType, messageType, messageContent); + } + + @Override + public void send(String sessionId, String messageType, String messageContent) { + sendRocketMQMessage(sessionId, null, null, messageType, messageContent); + } + + /** + * 通过 RocketMQ 广播消息 + * + * @param sessionId Session 编号 + * @param userId 用户编号 + * @param userType 用户类型 + * @param messageType 消息类型 + * @param messageContent 消息内容 + */ + private void sendRocketMQMessage(String sessionId, Long userId, Integer userType, + String messageType, String messageContent) { + RocketMQWebSocketMessage mqMessage = new RocketMQWebSocketMessage() + .setSessionId(sessionId).setUserId(userId).setUserType(userType) + .setMessageType(messageType).setMessageContent(messageContent); + rocketMQTemplate.syncSend(topic, mqMessage); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionHandlerDecorator.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionHandlerDecorator.java new file mode 100644 index 000000000..600a4dd96 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionHandlerDecorator.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.framework.websocket.core.session; + +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator; +import org.springframework.web.socket.handler.WebSocketHandlerDecorator; + +/** + * {@link WebSocketHandler} 的装饰类,实现了以下功能: + * + * 1. {@link WebSocketSession} 连接或关闭时,使用 {@link #sessionManager} 进行管理 + * 2. 封装 {@link WebSocketSession} 支持并发操作 + * + * @author 芋道源码 + */ +public class WebSocketSessionHandlerDecorator extends WebSocketHandlerDecorator { + + /** + * 发送时间的限制,单位:毫秒 + */ + private static final Integer SEND_TIME_LIMIT = 1000 * 5; + /** + * 发送消息缓冲上线,单位:bytes + */ + private static final Integer BUFFER_SIZE_LIMIT = 1024 * 100; + + private final WebSocketSessionManager sessionManager; + + public WebSocketSessionHandlerDecorator(WebSocketHandler delegate, + WebSocketSessionManager sessionManager) { + super(delegate); + this.sessionManager = sessionManager; + } + + @Override + public void afterConnectionEstablished(WebSocketSession session) { + // 实现 session 支持并发,可参考 https://blog.csdn.net/abu935009066/article/details/131218149 + session = new ConcurrentWebSocketSessionDecorator(session, SEND_TIME_LIMIT, BUFFER_SIZE_LIMIT); + // 添加到 WebSocketSessionManager 中 + sessionManager.addSession(session); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) { + sessionManager.removeSession(session); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java new file mode 100644 index 000000000..ad1de23c2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManager.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.framework.websocket.core.session; + +import org.springframework.web.socket.WebSocketSession; + +import java.util.Collection; + +/** + * {@link WebSocketSession} 管理器的接口 + * + * @author 芋道源码 + */ +public interface WebSocketSessionManager { + + /** + * 添加 Session + * + * @param session Session + */ + void addSession(WebSocketSession session); + + /** + * 移除 Session + * + * @param session Session + */ + void removeSession(WebSocketSession session); + + /** + * 获得指定编号的 Session + * + * @param id Session 编号 + * @return Session + */ + WebSocketSession getSession(String id); + + /** + * 获得指定用户类型的 Session 列表 + * + * @param userType 用户类型 + * @return Session 列表 + */ + Collection getSessionList(Integer userType); + + /** + * 获得指定用户编号的 Session 列表 + * + * @param userType 用户类型 + * @param userId 用户编号 + * @return Session 列表 + */ + Collection getSessionList(Integer userType, Long userId); + +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java new file mode 100644 index 000000000..aca572f90 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java @@ -0,0 +1,125 @@ +package cn.iocoder.yudao.framework.websocket.core.session; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; +import org.springframework.web.socket.WebSocketSession; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * 默认的 {@link WebSocketSessionManager} 实现类 + * + * @author 芋道源码 + */ +public class WebSocketSessionManagerImpl implements WebSocketSessionManager { + + /** + * id 与 WebSocketSession 映射 + * + * key:Session 编号 + */ + private final ConcurrentMap idSessions = new ConcurrentHashMap<>(); + + /** + * user 与 WebSocketSession 映射 + * + * key1:用户类型 + * key2:用户编号 + */ + private final ConcurrentMap>> userSessions + = new ConcurrentHashMap<>(); + + @Override + public void addSession(WebSocketSession session) { + // 添加到 idSessions 中 + idSessions.put(session.getId(), session); + // 添加到 userSessions 中 + LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); + if (user == null) { + return; + } + ConcurrentMap> userSessionsMap = userSessions.get(user.getUserType()); + if (userSessionsMap == null) { + userSessionsMap = new ConcurrentHashMap<>(); + if (userSessions.putIfAbsent(user.getUserType(), userSessionsMap) != null) { + userSessionsMap = userSessions.get(user.getUserType()); + } + } + CopyOnWriteArrayList sessions = userSessionsMap.get(user.getId()); + if (sessions == null) { + sessions = new CopyOnWriteArrayList<>(); + if (userSessionsMap.putIfAbsent(user.getId(), sessions) != null) { + sessions = userSessionsMap.get(user.getId()); + } + } + sessions.add(session); + } + + @Override + public void removeSession(WebSocketSession session) { + // 移除从 idSessions 中 + idSessions.remove(session.getId(), session); + // 移除从 idSessions 中 + LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); + if (user == null) { + return; + } + ConcurrentMap> userSessionsMap = userSessions.get(user.getUserType()); + if (userSessionsMap == null) { + return; + } + CopyOnWriteArrayList sessions = userSessionsMap.get(user.getId()); + sessions.removeIf(session0 -> session0.getId().equals(session.getId())); + if (CollUtil.isEmpty(sessions)) { + userSessionsMap.remove(user.getId(), sessions); + } + } + + @Override + public WebSocketSession getSession(String id) { + return idSessions.get(id); + } + + @Override + public Collection getSessionList(Integer userType) { + ConcurrentMap> userSessionsMap = userSessions.get(userType); + if (CollUtil.isEmpty(userSessionsMap)) { + return new ArrayList<>(); + } + LinkedList result = new LinkedList<>(); // 避免扩容 + Long contextTenantId = TenantContextHolder.getTenantId(); + for (List sessions : userSessionsMap.values()) { + if (CollUtil.isEmpty(sessions)) { + continue; + } + // 特殊:如果租户不匹配,则直接排除 + if (contextTenantId != null) { + Long userTenantId = WebSocketFrameworkUtils.getTenantId(sessions.get(0)); + if (!contextTenantId.equals(userTenantId)) { + continue; + } + } + result.addAll(sessions); + } + return result; + } + + @Override + public Collection getSessionList(Integer userType, Long userId) { + ConcurrentMap> userSessionsMap = userSessions.get(userType); + if (CollUtil.isEmpty(userSessionsMap)) { + return new ArrayList<>(); + } + CopyOnWriteArrayList sessions = userSessionsMap.get(userId); + return CollUtil.isNotEmpty(sessions) ? new ArrayList<>(sessions) : new ArrayList<>(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/util/WebSocketFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/util/WebSocketFrameworkUtils.java new file mode 100644 index 000000000..58cdedc29 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/util/WebSocketFrameworkUtils.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.framework.websocket.core.util; + +import cn.iocoder.yudao.framework.security.core.LoginUser; +import org.springframework.web.socket.WebSocketSession; + +import java.util.Map; + +/** + * 专属于 web 包的工具类 + * + * @author 芋道源码 + */ +public class WebSocketFrameworkUtils { + + public static final String ATTRIBUTE_LOGIN_USER = "LOGIN_USER"; + + /** + * 设置当前用户 + * + * @param loginUser 登录用户 + * @param attributes Session + */ + public static void setLoginUser(LoginUser loginUser, Map attributes) { + attributes.put(ATTRIBUTE_LOGIN_USER, loginUser); + } + + /** + * 获取当前用户 + * + * @return 当前用户 + */ + public static LoginUser getLoginUser(WebSocketSession session) { + return (LoginUser) session.getAttributes().get(ATTRIBUTE_LOGIN_USER); + } + + /** + * 获得当前用户的编号 + * + * @return 用户编号 + */ + public static Long getLoginUserId(WebSocketSession session) { + LoginUser loginUser = getLoginUser(session); + return loginUser != null ? loginUser.getId() : null; + } + + /** + * 获得当前用户的类型 + * + * @return 用户编号 + */ + public static Integer getLoginUserType(WebSocketSession session) { + LoginUser loginUser = getLoginUser(session); + return loginUser != null ? loginUser.getUserType() : null; + } + + /** + * 获得当前用户的租户编号 + * + * @param session Session + * @return 租户编号 + */ + public static Long getTenantId(WebSocketSession session) { + LoginUser loginUser = getLoginUser(session); + return loginUser != null ? loginUser.getTenantId() : null; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/package-info.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/package-info.java new file mode 100644 index 000000000..97bc5f951 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/package-info.java @@ -0,0 +1,4 @@ +/** + * WebSocket 框架,支持多节点的广播 + */ +package cn.iocoder.yudao.framework.websocket; diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..6260e407e --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +cn.iocoder.yudao.framework.websocket.config.YudaoWebSocketAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/《芋道 Spring Boot WebSocket 入门》.md b/yudao-framework/yudao-spring-boot-starter-websocket/《芋道 Spring Boot WebSocket 入门》.md new file mode 100644 index 000000000..8df5a7758 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-websocket/《芋道 Spring Boot WebSocket 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-gateway/src/main/resources/application.yaml b/yudao-gateway/src/main/resources/application.yaml index 0f5e204a7..e629df383 100644 --- a/yudao-gateway/src/main/resources/application.yaml +++ b/yudao-gateway/src/main/resources/application.yaml @@ -37,6 +37,10 @@ spring: uri: grayLb://infra-server predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 - Path=/admin/** + - id: infra-websocket # 路由的编号(WebSocket) + uri: grayLb://infra-server + predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组 + - Path=/infra/ws/** ## member-server 服务 - id: member-admin-api # 路由的编号 uri: grayLb://member-server diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java index 92c7c154c..4e4e68d6f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/BpmOALeaveDO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.bpm.dal.dataobject.oa; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; -import java.util.*; -import com.baomidou.mybatisplus.annotation.*; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; /** * OA 请假申请 DO @@ -39,7 +39,6 @@ public class BpmOALeaveDO extends BaseDO { /** * 请假类型 */ - @TableField("`type`") private String type; /** * 原因 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml index 2908b5ce3..f0f5bd881 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/application.yaml @@ -67,7 +67,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml b/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml index 256fd1f9e..7c044484a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/resources/application-unit-test.yaml @@ -22,7 +22,7 @@ spring: mybatis-plus: lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject global-config: db-config: id-type: AUTO # H2 主键递增 @@ -44,4 +44,4 @@ mybatis-plus: # 芋道配置项,设置当前项目所有自定义的配置 yudao: info: - base-package: cn.iocoder.yudao.module + base-package: cn.iocoder.yudao.module.bpm diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java new file mode 100644 index 000000000..5ed3c9f4c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApi.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.infra.api.websocket; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.infra.api.websocket.dto.WebSocketSendReqDTO; +import cn.iocoder.yudao.module.infra.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.validation.Valid; + +@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory = +@Tag(name = "RPC 服务 - WebSocket 发送器的") // 对 WebSocketMessageSender 进行封装,提供给其它模块使用 +public interface WebSocketSenderApi { + + String PREFIX = ApiConstants.PREFIX + "/websocket"; + + @PostMapping(PREFIX + "/send") + @Operation(summary = "发送 WebSocket 消息") + CommonResult send(@Valid @RequestBody WebSocketSendReqDTO message); + + /** + * 发送消息给指定用户 + * + * @param userType 用户类型 + * @param userId 用户编号 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + default void send(Integer userType, Long userId, String messageType, String messageContent) { + send(new WebSocketSendReqDTO().setUserType(userType).setUserId(userId) + .setMessageType(messageType).setMessageContent(messageContent)).checkError(); + } + + /** + * 发送消息给指定用户类型 + * + * @param userType 用户类型 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + default void send(Integer userType, String messageType, String messageContent) { + send(new WebSocketSendReqDTO().setUserType(userType) + .setMessageType(messageType).setMessageContent(messageContent)).checkError(); + } + + /** + * 发送消息给指定 Session + * + * @param sessionId Session 编号 + * @param messageType 消息类型 + * @param messageContent 消息内容,JSON 格式 + */ + default void send(String sessionId, String messageType, String messageContent) { + send(new WebSocketSendReqDTO().setSessionId(sessionId) + .setMessageType(messageType).setMessageContent(messageContent)).checkError(); + } + + default void sendObject(Integer userType, Long userId, String messageType, Object messageContent) { + send(userType, userId, messageType, JsonUtils.toJsonString(messageContent)); + } + + default void sendObject(Integer userType, String messageType, Object messageContent) { + send(userType, messageType, JsonUtils.toJsonString(messageContent)); + } + + default void sendObject(String sessionId, String messageType, Object messageContent) { + send(sessionId, messageType, JsonUtils.toJsonString(messageContent)); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java new file mode 100644 index 000000000..0f321a8c3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/dto/WebSocketSendReqDTO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.infra.api.websocket.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +@Schema(description = "RPC 服务 - WebSocket 消息发送 Request DTO") +@Data +public class WebSocketSendReqDTO { + + @Schema(description = "Session 编号", example = "abc") + private String sessionId; + @Schema(description = "用户编号", example = "1024") + private Long userId; + @Schema(description = "用户类型", example = "1") + private Integer userType; + + @Schema(description = "消息类型", example = "demo-message") + @NotEmpty(message = "消息类型不能为空") + private String messageType; + @Schema(description = "消息内容", example = "{\"name\":\"李四\"}}") + @NotEmpty(message = "消息内容不能为空") + private String messageContent; + +} diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index d956e763d..471950017 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -42,9 +42,10 @@ public interface ErrorCodeConstants { ErrorCode CODEGEN_SYNC_NONE_CHANGE = new ErrorCode(1_003_001_007, "同步失败,不存在改变"); ErrorCode CODEGEN_TABLE_INFO_TABLE_COMMENT_IS_NULL = new ErrorCode(1_003_001_008, "数据库的表注释未填写"); ErrorCode CODEGEN_TABLE_INFO_COLUMN_COMMENT_IS_NULL = new ErrorCode(1_003_001_009, "数据库的表字段({})注释未填写"); - - // ========== 字典类型(测试)1-001-005-000 ========== - ErrorCode TEST_DEMO_NOT_EXISTS = new ErrorCode(1_001_005_000, "测试示例不存在"); + ErrorCode CODEGEN_MASTER_TABLE_NOT_EXISTS = new ErrorCode(1_003_001_010, "主表(id={})定义不存在,请检查"); + ErrorCode CODEGEN_SUB_COLUMN_NOT_EXISTS = new ErrorCode(1_003_001_011, "子表的字段(id={})不存在,请检查"); + ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE = new ErrorCode(1_003_001_012, "主表生成代码失败,原因:它没有子表"); + ErrorCode CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_COLUMN = new ErrorCode(1_003_001_013, "主表生成代码失败,原因:它的子表({})没有字段"); // ========== 文件配置 1-001-006-000 ========== ErrorCode FILE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_006_000, "文件配置不存在"); @@ -54,4 +55,19 @@ public interface ErrorCodeConstants { ErrorCode DATA_SOURCE_CONFIG_NOT_EXISTS = new ErrorCode(1_001_007_000, "数据源配置不存在"); ErrorCode DATA_SOURCE_CONFIG_NOT_OK = new ErrorCode(1_001_007_001, "数据源配置不正确,无法进行连接"); + // ========== 数据源配置 1-001-107-000 ========== + ErrorCode DEMO_STUDENT_NOT_EXISTS = new ErrorCode(1_001_107_000, "学生不存在"); + + // ========== 学生 1-001-201-000 ========== + ErrorCode DEMO01_CONTACT_NOT_EXISTS = new ErrorCode(1_001_201_000, "示例联系人不存在"); + ErrorCode DEMO02_CATEGORY_NOT_EXISTS = new ErrorCode(1_001_201_001, "示例分类不存在"); + ErrorCode DEMO02_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_001_201_002, "存在存在子示例分类,无法删除"); + ErrorCode DEMO02_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_001_201_003,"父级示例分类不存在"); + ErrorCode DEMO02_CATEGORY_PARENT_ERROR = new ErrorCode(1_001_201_004, "不能设置自己为父示例分类"); + ErrorCode DEMO02_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_001_201_005, "已经存在该名字的示例分类"); + ErrorCode DEMO02_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_001_201_006, "不能设置自己的子示例分类为父示例分类"); + ErrorCode DEMO03_STUDENT_NOT_EXISTS = new ErrorCode(1_001_201_007, "学生不存在"); + ErrorCode DEMO03_GRADE_NOT_EXISTS = new ErrorCode(1_001_201_008, "学生班级不存在"); + ErrorCode DEMO03_GRADE_EXISTS = new ErrorCode(1_001_201_009, "学生班级已存在"); + } diff --git a/yudao-module-infra/yudao-module-infra-biz/pom.xml b/yudao-module-infra/yudao-module-infra-biz/pom.xml index 5df268b29..e952dd326 100644 --- a/yudao-module-infra/yudao-module-infra-biz/pom.xml +++ b/yudao-module-infra/yudao-module-infra-biz/pom.xml @@ -61,6 +61,11 @@ yudao-spring-boot-starter-security + + cn.iocoder.cloud + yudao-spring-boot-starter-websocket + + cn.iocoder.cloud @@ -101,6 +106,10 @@ + + cn.iocoder.cloud + yudao-spring-boot-starter-mq + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java new file mode 100644 index 000000000..53c98dd09 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.infra.api.websocket; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.module.infra.api.websocket.dto.WebSocketSendReqDTO; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@RestController // 提供 RESTful API 接口,给 Feign 调用 +@Validated +public class WebSocketSenderApiImpl implements WebSocketSenderApi { + + @Resource + private WebSocketMessageSender webSocketMessageSender; + + @Override + public CommonResult send(WebSocketSendReqDTO message) { + if (StrUtil.isNotEmpty(message.getSessionId())) { + webSocketMessageSender.send(message.getSessionId(), + message.getMessageType(), message.getMessageContent()); + } else if (message.getUserType() != null && message.getUserId() != null) { + webSocketMessageSender.send(message.getUserType(), message.getUserId(), + message.getMessageType(), message.getMessageContent()); + } else if (message.getUserType() != null) { + webSocketMessageSender.send(message.getUserType(), + message.getMessageType(), message.getMessageContent()); + } + return success(true); + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java index 76e5b6a83..dc4d32c43 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/CodegenController.java @@ -16,10 +16,10 @@ import cn.iocoder.yudao.module.infra.convert.codegen.CodegenConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.module.infra.service.codegen.CodegenService; -import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -60,10 +60,19 @@ public class CodegenController { return success(codegenService.getDatabaseTableList(dataSourceConfigId, name, comment)); } + @GetMapping("/table/list") + @Operation(summary = "获得表定义列表") + @Parameter(name = "dataSourceConfigId", description = "数据源配置的编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('infra:codegen:query')") + public CommonResult> getCodegenTableList(@RequestParam(value = "dataSourceConfigId") Long dataSourceConfigId) { + List list = codegenService.getCodegenTableList(dataSourceConfigId); + return success(CodegenConvert.INSTANCE.convertList05(list)); + } + @GetMapping("/table/page") @Operation(summary = "获得表定义分页") @PreAuthorize("@ss.hasPermission('infra:codegen:query')") - public CommonResult> getCodeGenTablePage(@Valid CodegenTablePageReqVO pageReqVO) { + public CommonResult> getCodegenTablePage(@Valid CodegenTablePageReqVO pageReqVO) { PageResult pageResult = codegenService.getCodegenTablePage(pageReqVO); return success(CodegenConvert.INSTANCE.convertPage(pageResult)); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenDetailRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenDetailRespVO.java index 264934178..f7d8a62a4 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenDetailRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenDetailRespVO.java @@ -17,4 +17,4 @@ public class CodegenDetailRespVO { @Schema(description = "字段定义") private List columns; -} \ No newline at end of file +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenUpdateReqVO.java index 2531fd768..a43aa987a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenUpdateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/CodegenUpdateReqVO.java @@ -4,6 +4,8 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.column.CodegenColumnBaseVO; import cn.iocoder.yudao.module.infra.controller.admin.codegen.vo.table.CodegenTableBaseVO; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -37,12 +39,27 @@ public class CodegenUpdateReqVO { private Long id; @AssertTrue(message = "上级菜单不能为空,请前往 [修改生成配置 -> 生成信息] 界面,设置“上级菜单”字段") + @JsonIgnore public boolean isParentMenuIdValid() { // 生成场景为管理后台时,必须设置上级菜单,不然生成的菜单 SQL 是无父级菜单的 return ObjectUtil.notEqual(getScene(), CodegenSceneEnum.ADMIN.getScene()) || getParentMenuId() != null; } + @AssertTrue(message = "关联的父表信息不全") + @JsonIgnore + public boolean isSubValid() { + return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.SUB) + || (ObjectUtil.isAllNotEmpty(getMasterTableId(), getSubJoinColumnId(), getSubJoinMany())); + } + + @AssertTrue(message = "关联的树表信息不全") + @JsonIgnore + public boolean isTreeValid() { + return ObjectUtil.notEqual(getTemplateType(), CodegenTemplateTypeEnum.TREE) + || (ObjectUtil.isAllNotEmpty(getTreeParentColumnId(), getTreeNameColumnId())); + } + } @Schema(description = "更新表定义") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java index ede10fccd..dff1115f3 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/codegen/vo/table/CodegenTableBaseVO.java @@ -58,4 +58,16 @@ public class CodegenTableBaseVO { @Schema(description = "父菜单编号", example = "1024") private Long parentMenuId; + @Schema(description = "主表的编号", example = "2048") + private Long masterTableId; + @Schema(description = "子表关联主表的字段编号", example = "4096") + private Long subJoinColumnId; + @Schema(description = "主表与子表是否一对多", example = "4096") + private Boolean subJoinMany; + + @Schema(description = "树表的父字段编号", example = "8192") + private Long treeParentColumnId; + @Schema(description = "树表的名字字段编号", example = "16384") + private Long treeNameColumnId; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java index 6bdadb0ff..00f6ecce7 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java @@ -1,17 +1,20 @@ package cn.iocoder.yudao.module.infra.controller.admin.config; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.*; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigSaveReqVO; import cn.iocoder.yudao.module.infra.convert.config.ConfigConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.infra.service.config.ConfigService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -38,15 +41,15 @@ public class ConfigController { @PostMapping("/create") @Operation(summary = "创建参数配置") @PreAuthorize("@ss.hasPermission('infra:config:create')") - public CommonResult createConfig(@Valid @RequestBody ConfigCreateReqVO reqVO) { - return success(configService.createConfig(reqVO)); + public CommonResult createConfig(@Valid @RequestBody ConfigSaveReqVO createReqVO) { + return success(configService.createConfig(createReqVO)); } @PutMapping("/update") @Operation(summary = "修改参数配置") @PreAuthorize("@ss.hasPermission('infra:config:update')") - public CommonResult updateConfig(@Valid @RequestBody ConfigUpdateReqVO reqVO) { - configService.updateConfig(reqVO); + public CommonResult updateConfig(@Valid @RequestBody ConfigSaveReqVO updateReqVO) { + configService.updateConfig(updateReqVO); return success(true); } @@ -84,8 +87,8 @@ public class ConfigController { @GetMapping("/page") @Operation(summary = "获取参数配置分页") @PreAuthorize("@ss.hasPermission('infra:config:query')") - public CommonResult> getConfigPage(@Valid ConfigPageReqVO reqVO) { - PageResult page = configService.getConfigPage(reqVO); + public CommonResult> getConfigPage(@Valid ConfigPageReqVO pageReqVO) { + PageResult page = configService.getConfigPage(pageReqVO); return success(ConfigConvert.INSTANCE.convertPage(page)); } @@ -93,13 +96,13 @@ public class ConfigController { @Operation(summary = "导出参数配置") @PreAuthorize("@ss.hasPermission('infra:config:export')") @OperateLog(type = EXPORT) - public void exportConfig(@Valid ConfigExportReqVO reqVO, + public void exportConfig(@Valid ConfigPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = configService.getConfigList(reqVO); - // 拼接数据 - List datas = ConfigConvert.INSTANCE.convertList(list); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = configService.getConfigPage(exportReqVO).getList(); // 输出 - ExcelUtils.write(response, "参数配置.xls", "数据", ConfigExcelVO.class, datas); + ExcelUtils.write(response, "参数配置.xls", "数据", ConfigRespVO.class, + ConfigConvert.INSTANCE.convertList(list)); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java deleted file mode 100644 index ebbdf67fc..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigCreateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.config.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; - -@Schema(description = "管理后台 - 参数配置创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class ConfigCreateReqVO extends ConfigBaseVO { - - @Schema(description = "参数键名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yunai.db.username") - @NotBlank(message = "参数键名长度不能为空") - @Size(max = 100, message = "参数键名长度不能超过100个字符") - private String key; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExcelVO.java deleted file mode 100644 index 12611032a..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExcelVO.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.config.vo; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 参数配置 Excel 导出响应 VO - */ -@Data -public class ConfigExcelVO { - - @ExcelProperty("参数配置序号") - private Long id; - - @ExcelProperty("参数键名") - private String configKey; - - @ExcelProperty("参数分类") - private String category; - - @ExcelProperty("参数名称") - private String name; - - @ExcelProperty("参数键值") - private String value; - - @ExcelProperty(value = "参数类型", converter = DictConvert.class) - @DictFormat(DictTypeConstants.CONFIG_TYPE) - private Integer type; - - @ExcelProperty(value = "是否可见", converter = DictConvert.class) - @DictFormat(DictTypeConstants.BOOLEAN_STRING) - private Boolean visible; - - @ExcelProperty("备注") - private String remark; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java deleted file mode 100644 index 78d289a5b..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigExportReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.config.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 参数配置导出 Request VO") -@Data -public class ConfigExportReqVO { - - @Schema(description = "参数名称", example = "模糊匹配") - private String name; - - @Schema(description = "参数键名,模糊匹配", example = "yunai.db.username") - private String key; - - @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", example = "1") - private Integer type; - - @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java index 8c3d51e7e..b4f642f69 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java @@ -1,30 +1,56 @@ package cn.iocoder.yudao.module.infra.controller.admin.config.vo; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Size; import java.time.LocalDateTime; @Schema(description = "管理后台 - 参数配置信息 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -public class ConfigRespVO extends ConfigBaseVO { +@ExcelIgnoreUnannotated +public class ConfigRespVO { @Schema(description = "参数配置序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("参数配置序号") private Long id; + @Schema(description = "参数分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "biz") + @ExcelProperty("参数分类") + private String category; + + @Schema(description = "参数名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数据库名") + @ExcelProperty("参数名称") + private String name; + @Schema(description = "参数键名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yunai.db.username") - @NotBlank(message = "参数键名长度不能为空") - @Size(max = 100, message = "参数键名长度不能超过100个字符") + @ExcelProperty("参数键名") private String key; + @Schema(description = "参数键值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("参数键值") + private String value; + @Schema(description = "参数类型,参见 SysConfigTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "参数类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.CONFIG_TYPE) private Integer type; + @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否可见", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean visible; + + @Schema(description = "备注", example = "备注一下很帅气!") + @ExcelProperty("备注") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") + @ExcelProperty("创建时间") private LocalDateTime createTime; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigSaveReqVO.java similarity index 63% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigBaseVO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigSaveReqVO.java index acd3beee6..59aaa4848 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigSaveReqVO.java @@ -8,26 +8,31 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 参数配置 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 参数配置创建/修改 Request VO") @Data -public class ConfigBaseVO { +public class ConfigSaveReqVO { + + @Schema(description = "参数配置序号", example = "1024") + private Long id; @Schema(description = "参数分组", requiredMode = Schema.RequiredMode.REQUIRED, example = "biz") @NotEmpty(message = "参数分组不能为空") - @Size(max = 50, message = "参数名称不能超过50个字符") + @Size(max = 50, message = "参数名称不能超过 50 个字符") private String category; @Schema(description = "参数名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数据库名") @NotBlank(message = "参数名称不能为空") - @Size(max = 100, message = "参数名称不能超过100个字符") + @Size(max = 100, message = "参数名称不能超过 100 个字符") private String name; + @Schema(description = "参数键名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yunai.db.username") + @NotBlank(message = "参数键名长度不能为空") + @Size(max = 100, message = "参数键名长度不能超过 100 个字符") + private String key; + @Schema(description = "参数键值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotBlank(message = "参数键值不能为空") - @Size(max = 500, message = "参数键值长度不能超过500个字符") + @Size(max = 500, message = "参数键值长度不能超过 500 个字符") private String value; @Schema(description = "是否可见", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigUpdateReqVO.java deleted file mode 100644 index b2497b1cd..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.config.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 参数配置创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ConfigUpdateReqVO extends ConfigBaseVO { - - @Schema(description = "参数配置序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "参数配置编号不能为空") - private Long id; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java index 366f382d7..85a12279e 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DataSourceConfigController.java @@ -1,15 +1,14 @@ package cn.iocoder.yudao.module.infra.controller.admin.db; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; -import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; import cn.iocoder.yudao.module.infra.service.db.DataSourceConfigService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -32,14 +31,14 @@ public class DataSourceConfigController { @PostMapping("/create") @Operation(summary = "创建数据源配置") @PreAuthorize("@ss.hasPermission('infra:data-source-config:create')") - public CommonResult createDataSourceConfig(@Valid @RequestBody DataSourceConfigCreateReqVO createReqVO) { + public CommonResult createDataSourceConfig(@Valid @RequestBody DataSourceConfigSaveReqVO createReqVO) { return success(dataSourceConfigService.createDataSourceConfig(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新数据源配置") @PreAuthorize("@ss.hasPermission('infra:data-source-config:update')") - public CommonResult updateDataSourceConfig(@Valid @RequestBody DataSourceConfigUpdateReqVO updateReqVO) { + public CommonResult updateDataSourceConfig(@Valid @RequestBody DataSourceConfigSaveReqVO updateReqVO) { dataSourceConfigService.updateDataSourceConfig(updateReqVO); return success(true); } @@ -58,8 +57,8 @@ public class DataSourceConfigController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('infra:data-source-config:query')") public CommonResult getDataSourceConfig(@RequestParam("id") Long id) { - DataSourceConfigDO dataSourceConfig = dataSourceConfigService.getDataSourceConfig(id); - return success(DataSourceConfigConvert.INSTANCE.convert(dataSourceConfig)); + DataSourceConfigDO config = dataSourceConfigService.getDataSourceConfig(id); + return success(BeanUtils.toBean(config, DataSourceConfigRespVO.class)); } @GetMapping("/list") @@ -67,7 +66,7 @@ public class DataSourceConfigController { @PreAuthorize("@ss.hasPermission('infra:data-source-config:query')") public CommonResult> getDataSourceConfigList() { List list = dataSourceConfigService.getDataSourceConfigList(); - return success(DataSourceConfigConvert.INSTANCE.convertList(list)); + return success(BeanUtils.toBean(list, DataSourceConfigRespVO.class)); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java index beef57f99..70562b021 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/DatabaseDocController.java @@ -13,9 +13,9 @@ import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourcePrope import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java deleted file mode 100755 index 598bda81b..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigCreateReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.db.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import javax.validation.constraints.*; - -@Schema(description = "管理后台 - 数据源配置创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class DataSourceConfigCreateReqVO extends DataSourceConfigBaseVO { - - @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @NotNull(message = "密码不能为空") - private String password; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java index 77ecef56c..f97952873 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigRespVO.java @@ -1,19 +1,26 @@ package cn.iocoder.yudao.module.infra.controller.admin.db.vo; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.Data; import java.time.LocalDateTime; @Schema(description = "管理后台 - 数据源配置 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class DataSourceConfigRespVO extends DataSourceConfigBaseVO { +public class DataSourceConfigRespVO { @Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Integer id; + @Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") + private String name; + + @Schema(description = "数据源连接", requiredMode = Schema.RequiredMode.REQUIRED, example = "jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro") + private String url; + + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "root") + private String username; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigSaveReqVO.java similarity index 61% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigSaveReqVO.java index d33852adb..47a6e8be3 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigBaseVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigSaveReqVO.java @@ -1,15 +1,16 @@ package cn.iocoder.yudao.module.infra.controller.admin.db.vo; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import javax.validation.constraints.*; +import lombok.Data; -/** -* 数据源配置 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 数据源配置创建/修改 Request VO") @Data -public class DataSourceConfigBaseVO { +public class DataSourceConfigSaveReqVO { + + @Schema(description = "主键编号", example = "1024") + private Long id; @Schema(description = "数据源名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") @NotNull(message = "数据源名称不能为空") @@ -23,4 +24,8 @@ public class DataSourceConfigBaseVO { @NotNull(message = "用户名不能为空") private String username; + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + @NotNull(message = "密码不能为空") + private String password; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java deleted file mode 100755 index 5cc31eab6..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/db/vo/DataSourceConfigUpdateReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.db.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import javax.validation.constraints.*; - -@Schema(description = "管理后台 - 数据源配置更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class DataSourceConfigUpdateReqVO extends DataSourceConfigBaseVO { - - @Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "主键编号不能为空") - private Long id; - - @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @NotNull(message = "密码不能为空") - private String password; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/Demo01ContactController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/Demo01ContactController.java new file mode 100644 index 000000000..5ab9d1e97 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/Demo01ContactController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; +import cn.iocoder.yudao.module.infra.service.demo.demo01.Demo01ContactService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 示例联系人") +@RestController +@RequestMapping("/infra/demo01-contact") +@Validated +public class Demo01ContactController { + + @Resource + private Demo01ContactService demo01ContactService; + + @PostMapping("/create") + @Operation(summary = "创建示例联系人") + @PreAuthorize("@ss.hasPermission('infra:demo01-contact:create')") + public CommonResult createDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO createReqVO) { + return success(demo01ContactService.createDemo01Contact(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新示例联系人") + @PreAuthorize("@ss.hasPermission('infra:demo01-contact:update')") + public CommonResult updateDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO updateReqVO) { + demo01ContactService.updateDemo01Contact(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除示例联系人") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:demo01-contact:delete')") + public CommonResult deleteDemo01Contact(@RequestParam("id") Long id) { + demo01ContactService.deleteDemo01Contact(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得示例联系人") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')") + public CommonResult getDemo01Contact(@RequestParam("id") Long id) { + Demo01ContactDO demo01Contact = demo01ContactService.getDemo01Contact(id); + return success(BeanUtils.toBean(demo01Contact, Demo01ContactRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得示例联系人分页") + @PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')") + public CommonResult> getDemo01ContactPage(@Valid Demo01ContactPageReqVO pageReqVO) { + PageResult pageResult = demo01ContactService.getDemo01ContactPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, Demo01ContactRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出示例联系人 Excel") + @PreAuthorize("@ss.hasPermission('infra:demo01-contact:export')") + @OperateLog(type = EXPORT) + public void exportDemo01ContactExcel(@Valid Demo01ContactPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = demo01ContactService.getDemo01ContactPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "示例联系人.xls", "数据", Demo01ContactRespVO.class, + BeanUtils.toBean(list, Demo01ContactRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java new file mode 100644 index 000000000..151813965 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 示例联系人分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class Demo01ContactPageReqVO extends PageParam { + + @Schema(description = "名字", example = "张三") + private String name; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java new file mode 100644 index 000000000..17ee9fef8 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 示例联系人 Response VO") +@Data +@ExcelIgnoreUnannotated +public class Demo01ContactRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("名字") + private String name; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生年") + private LocalDateTime birthday; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") + @ExcelProperty("简介") + private String description; + + @Schema(description = "头像") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java new file mode 100644 index 000000000..94157ed4d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 示例联系人新增/修改 Request VO") +@Data +public class Demo01ContactSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生年不能为空") + private LocalDateTime birthday; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "头像") + private String avatar; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java new file mode 100644 index 000000000..ebf0193ef --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; +import cn.iocoder.yudao.module.infra.service.demo.demo02.Demo02CategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 示例分类") +@RestController +@RequestMapping("/infra/demo02-category") +@Validated +public class Demo02CategoryController { + + @Resource + private Demo02CategoryService demo02CategoryService; + + @PostMapping("/create") + @Operation(summary = "创建示例分类") + @PreAuthorize("@ss.hasPermission('infra:demo02-category:create')") + public CommonResult createDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO createReqVO) { + return success(demo02CategoryService.createDemo02Category(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新示例分类") + @PreAuthorize("@ss.hasPermission('infra:demo02-category:update')") + public CommonResult updateDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO updateReqVO) { + demo02CategoryService.updateDemo02Category(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除示例分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:demo02-category:delete')") + public CommonResult deleteDemo02Category(@RequestParam("id") Long id) { + demo02CategoryService.deleteDemo02Category(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得示例分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:demo02-category:query')") + public CommonResult getDemo02Category(@RequestParam("id") Long id) { + Demo02CategoryDO demo02Category = demo02CategoryService.getDemo02Category(id); + return success(BeanUtils.toBean(demo02Category, Demo02CategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得示例分类列表") + @PreAuthorize("@ss.hasPermission('infra:demo02-category:query')") + public CommonResult> getDemo02CategoryList(@Valid Demo02CategoryListReqVO listReqVO) { + List list = demo02CategoryService.getDemo02CategoryList(listReqVO); + return success(BeanUtils.toBean(list, Demo02CategoryRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出示例分类 Excel") + @PreAuthorize("@ss.hasPermission('infra:demo02-category:export')") + @OperateLog(type = EXPORT) + public void exportDemo02CategoryExcel(@Valid Demo02CategoryListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = demo02CategoryService.getDemo02CategoryList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "示例分类.xls", "数据", Demo02CategoryRespVO.class, + BeanUtils.toBean(list, Demo02CategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java new file mode 100644 index 000000000..69fcfd936 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 示例分类列表 Request VO") +@Data +public class Demo02CategoryListReqVO { + + @Schema(description = "名字", example = "芋艿") + private String name; + + @Schema(description = "父级编号", example = "6080") + private Long parentId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java new file mode 100644 index 000000000..1f2efd46a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 示例分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class Demo02CategoryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("名字") + private String name; + + @Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080") + @ExcelProperty("父级编号") + private Long parentId; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java new file mode 100644 index 000000000..3cc501251 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 示例分类新增/修改 Request VO") +@Data +public class Demo02CategorySaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080") + @NotNull(message = "父级编号不能为空") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/Demo03StudentController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/Demo03StudentController.java new file mode 100644 index 000000000..e97f44e03 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/Demo03StudentController.java @@ -0,0 +1,197 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentRespVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; +import cn.iocoder.yudao.module.infra.service.demo.demo03.Demo03StudentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/demo03-student") +@Validated +public class Demo03StudentController { + + @Resource + private Demo03StudentService demo03StudentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')") + public CommonResult createDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO createReqVO) { + return success(demo03StudentService.createDemo03Student(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')") + public CommonResult updateDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO updateReqVO) { + demo03StudentService.updateDemo03Student(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')") + public CommonResult deleteDemo03Student(@RequestParam("id") Long id) { + demo03StudentService.deleteDemo03Student(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult getDemo03Student(@RequestParam("id") Long id) { + Demo03StudentDO demo03Student = demo03StudentService.getDemo03Student(id); + return success(BeanUtils.toBean(demo03Student, Demo03StudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult> getDemo03StudentPage(@Valid Demo03StudentPageReqVO pageReqVO) { + PageResult pageResult = demo03StudentService.getDemo03StudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, Demo03StudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:export')") + @OperateLog(type = EXPORT) + public void exportDemo03StudentExcel(@Valid Demo03StudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = demo03StudentService.getDemo03StudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", Demo03StudentRespVO.class, + BeanUtils.toBean(list, Demo03StudentRespVO.class)); + } + + // ==================== 子表(学生课程) ==================== + + @GetMapping("/demo03-course/page") + @Operation(summary = "获得学生课程分页") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult> getDemo03CoursePage(PageParam pageReqVO, + @RequestParam("studentId") Long studentId) { + return success(demo03StudentService.getDemo03CoursePage(pageReqVO, studentId)); + } + + @PostMapping("/demo03-course/create") + @Operation(summary = "创建学生课程") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')") + public CommonResult createDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) { + return success(demo03StudentService.createDemo03Course(demo03Course)); + } + + @PutMapping("/demo03-course/update") + @Operation(summary = "更新学生课程") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')") + public CommonResult updateDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) { + demo03StudentService.updateDemo03Course(demo03Course); + return success(true); + } + + @DeleteMapping("/demo03-course/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除学生课程") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')") + public CommonResult deleteDemo03Course(@RequestParam("id") Long id) { + demo03StudentService.deleteDemo03Course(id); + return success(true); + } + + @GetMapping("/demo03-course/get") + @Operation(summary = "获得学生课程") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult getDemo03Course(@RequestParam("id") Long id) { + return success(demo03StudentService.getDemo03Course(id)); + } + + @GetMapping("/demo03-course/list-by-student-id") + @Operation(summary = "获得学生课程列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult> getDemo03CourseListByStudentId(@RequestParam("studentId") Long studentId) { + return success(demo03StudentService.getDemo03CourseListByStudentId(studentId)); + } + + // ==================== 子表(学生班级) ==================== + + @GetMapping("/demo03-grade/page") + @Operation(summary = "获得学生班级分页") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult> getDemo03GradePage(PageParam pageReqVO, + @RequestParam("studentId") Long studentId) { + return success(demo03StudentService.getDemo03GradePage(pageReqVO, studentId)); + } + + @PostMapping("/demo03-grade/create") + @Operation(summary = "创建学生班级") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')") + public CommonResult createDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) { + return success(demo03StudentService.createDemo03Grade(demo03Grade)); + } + + @PutMapping("/demo03-grade/update") + @Operation(summary = "更新学生班级") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')") + public CommonResult updateDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) { + demo03StudentService.updateDemo03Grade(demo03Grade); + return success(true); + } + + @DeleteMapping("/demo03-grade/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除学生班级") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')") + public CommonResult deleteDemo03Grade(@RequestParam("id") Long id) { + demo03StudentService.deleteDemo03Grade(id); + return success(true); + } + + @GetMapping("/demo03-grade/get") + @Operation(summary = "获得学生班级") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult getDemo03Grade(@RequestParam("id") Long id) { + return success(demo03StudentService.getDemo03Grade(id)); + } + + @GetMapping("/demo03-grade/get-by-student-id") + @Operation(summary = "获得学生班级") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") + public CommonResult getDemo03GradeByStudentId(@RequestParam("studentId") Long studentId) { + return success(demo03StudentService.getDemo03GradeByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/package-info.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/package-info.java new file mode 100644 index 000000000..79682e203 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java old mode 100755 new mode 100644 similarity index 57% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java index fbdbc4589..ae8a67abc --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; @@ -11,29 +11,23 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -@Schema(description = "管理后台 - 字典类型分页 Request VO") +@Schema(description = "管理后台 - 学生分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class TestDemoPageReqVO extends PageParam { +public class Demo03StudentPageReqVO extends PageParam { - @Schema(description = "名字") + @Schema(description = "名字", example = "芋艿") private String name; - @Schema(description = "状态") - private Integer status; + @Schema(description = "性别") + private Integer sex; - @Schema(description = "类型") - private Integer type; + @Schema(description = "简介", example = "随便") + private String description; - @Schema(description = "分类") - private Integer category; - - @Schema(description = "备注") - private String remark; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java new file mode 100644 index 000000000..4ace8a8ef --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class Demo03StudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("名字") + private String name; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便") + @ExcelProperty("简介") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java new file mode 100644 index 000000000..09d322059 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo; + +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class Demo03StudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便") + @NotEmpty(message = "简介不能为空") + private String description; + + + private List demo03Courses; + + private Demo03GradeDO demo03Grade; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/package-info.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/package-info.java new file mode 100644 index 000000000..c44864636 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/package-info.java @@ -0,0 +1,8 @@ +/** + * 代码生成示例 + * + * 1. demo01:单表(增删改查) + * 2. demo02:单表(树形结构) + * 3. demo03:主子表(标准模式)+ 主子表(ERP 模式)+ 主子表(内嵌模式) + */ +package cn.iocoder.yudao.module.infra.controller.admin.demo; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.java index 1fbae0931..eb51f08c3 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileConfigController.java @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.infra.controller.admin.file; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO; -import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; import cn.iocoder.yudao.module.infra.service.file.FileConfigService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -33,14 +32,14 @@ public class FileConfigController { @PostMapping("/create") @Operation(summary = "创建文件配置") @PreAuthorize("@ss.hasPermission('infra:file-config:create')") - public CommonResult createFileConfig(@Valid @RequestBody FileConfigCreateReqVO createReqVO) { + public CommonResult createFileConfig(@Valid @RequestBody FileConfigSaveReqVO createReqVO) { return success(fileConfigService.createFileConfig(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新文件配置") @PreAuthorize("@ss.hasPermission('infra:file-config:update')") - public CommonResult updateFileConfig(@Valid @RequestBody FileConfigUpdateReqVO updateReqVO) { + public CommonResult updateFileConfig(@Valid @RequestBody FileConfigSaveReqVO updateReqVO) { fileConfigService.updateFileConfig(updateReqVO); return success(true); } @@ -67,8 +66,8 @@ public class FileConfigController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('infra:file-config:query')") public CommonResult getFileConfig(@RequestParam("id") Long id) { - FileConfigDO fileConfig = fileConfigService.getFileConfig(id); - return success(FileConfigConvert.INSTANCE.convert(fileConfig)); + FileConfigDO config = fileConfigService.getFileConfig(id); + return success(BeanUtils.toBean(config, FileConfigRespVO.class)); } @GetMapping("/page") @@ -76,7 +75,7 @@ public class FileConfigController { @PreAuthorize("@ss.hasPermission('infra:file-config:query')") public CommonResult> getFileConfigPage(@Valid FileConfigPageReqVO pageVO) { PageResult pageResult = fileConfigService.getFileConfigPage(pageVO); - return success(FileConfigConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, FileConfigRespVO.class)); } @GetMapping("/test") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index acb9360b5..d31125316 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -4,17 +4,17 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileUploadReqVO; -import cn.iocoder.yudao.module.infra.convert.file.FileConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.service.file.FileService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -86,7 +86,7 @@ public class FileController { @PreAuthorize("@ss.hasPermission('infra:file:query')") public CommonResult> getFilePage(@Valid FilePageReqVO pageVO) { PageResult pageResult = fileService.getFilePage(pageVO); - return success(FileConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, FileRespVO.class)); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigBaseVO.java deleted file mode 100755 index eccbd4bb1..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigBaseVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/** -* 文件配置 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class FileConfigBaseVO { - - @Schema(description = "配置名", requiredMode = Schema.RequiredMode.REQUIRED, example = "S3 - 阿里云") - @NotNull(message = "配置名不能为空") - private String name; - - @Schema(description = "备注", example = "我是备注") - private String remark; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java index c64556728..e3bb6fe88 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigRespVO.java @@ -3,32 +3,31 @@ package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config; import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @Schema(description = "管理后台 - 文件配置 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class FileConfigRespVO extends FileConfigBaseVO { +public class FileConfigRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; + @Schema(description = "配置名", requiredMode = Schema.RequiredMode.REQUIRED, example = "S3 - 阿里云") + private String name; + @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "存储器不能为空") private Integer storage; @Schema(description = "是否为主配置", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "是否为主配置不能为空") private Boolean master; @Schema(description = "存储配置", requiredMode = Schema.RequiredMode.REQUIRED) private FileClientConfig config; + @Schema(description = "备注", example = "我是备注") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigSaveReqVO.java old mode 100755 new mode 100644 similarity index 54% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigSaveReqVO.java index 496e32237..f4d8c9cb2 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigCreateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigSaveReqVO.java @@ -2,17 +2,21 @@ package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import javax.validation.constraints.NotNull; import java.util.Map; -@Schema(description = "管理后台 - 文件配置创建 Request VO") +@Schema(description = "管理后台 - 文件配置创建/修改 Request VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class FileConfigCreateReqVO extends FileConfigBaseVO { +public class FileConfigSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "配置名", requiredMode = Schema.RequiredMode.REQUIRED, example = "S3 - 阿里云") + @NotNull(message = "配置名不能为空") + private String name; @Schema(description = "存储器,参见 FileStorageEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "存储器不能为空") @@ -22,4 +26,7 @@ public class FileConfigCreateReqVO extends FileConfigBaseVO { @NotNull(message = "存储配置不能为空") private Map config; + @Schema(description = "备注", example = "我是备注") + private String remark; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigUpdateReqVO.java deleted file mode 100755 index ba599d424..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/config/FileConfigUpdateReqVO.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.file.vo.config; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; -import java.util.Map; - -@Schema(description = "管理后台 - 文件配置更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class FileConfigUpdateReqVO extends FileConfigBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "存储配置,配置是动态参数,所以使用 Map 接收", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "存储配置不能为空") - private Map config; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java index 641e1c23b..0d027633e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiAccessLogController.java @@ -1,18 +1,17 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExcelVO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO; -import cn.iocoder.yudao.module.infra.convert.logger.ApiAccessLogConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; import cn.iocoder.yudao.module.infra.service.logger.ApiAccessLogService; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -40,21 +39,22 @@ public class ApiAccessLogController { @GetMapping("/page") @Operation(summary = "获得API 访问日志分页") @PreAuthorize("@ss.hasPermission('infra:api-access-log:query')") - public CommonResult> getApiAccessLogPage(@Valid ApiAccessLogPageReqVO pageVO) { - PageResult pageResult = apiAccessLogService.getApiAccessLogPage(pageVO); - return success(ApiAccessLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getApiAccessLogPage(@Valid ApiAccessLogPageReqVO pageReqVO) { + PageResult pageResult = apiAccessLogService.getApiAccessLogPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ApiAccessLogRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出API 访问日志 Excel") @PreAuthorize("@ss.hasPermission('infra:api-access-log:export')") @OperateLog(type = EXPORT) - public void exportApiAccessLogExcel(@Valid ApiAccessLogExportReqVO exportReqVO, + public void exportApiAccessLogExcel(@Valid ApiAccessLogPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = apiAccessLogService.getApiAccessLogList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = apiAccessLogService.getApiAccessLogPage(exportReqVO).getList(); // 导出 Excel - List datas = ApiAccessLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "API 访问日志.xls", "数据", ApiAccessLogExcelVO.class, datas); + ExcelUtils.write(response, "API 访问日志.xls", "数据", ApiAccessLogRespVO.class, + BeanUtils.toBean(list, ApiAccessLogRespVO.class)); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java index 191bd94d0..ecb0c45d5 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/ApiErrorLogController.java @@ -1,20 +1,19 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExcelVO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO; -import cn.iocoder.yudao.module.infra.convert.logger.ApiErrorLogConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; import cn.iocoder.yudao.module.infra.service.logger.ApiErrorLogService; -import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -54,21 +53,22 @@ public class ApiErrorLogController { @GetMapping("/page") @Operation(summary = "获得 API 错误日志分页") @PreAuthorize("@ss.hasPermission('infra:api-error-log:query')") - public CommonResult> getApiErrorLogPage(@Valid ApiErrorLogPageReqVO pageVO) { - PageResult pageResult = apiErrorLogService.getApiErrorLogPage(pageVO); - return success(ApiErrorLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getApiErrorLogPage(@Valid ApiErrorLogPageReqVO pageReqVO) { + PageResult pageResult = apiErrorLogService.getApiErrorLogPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ApiErrorLogRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出 API 错误日志 Excel") @PreAuthorize("@ss.hasPermission('infra:api-error-log:export')") @OperateLog(type = EXPORT) - public void exportApiErrorLogExcel(@Valid ApiErrorLogExportReqVO exportReqVO, + public void exportApiErrorLogExcel(@Valid ApiErrorLogPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = apiErrorLogService.getApiErrorLogList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = apiErrorLogService.getApiErrorLogPage(exportReqVO).getList(); // 导出 Excel - List datas = ApiErrorLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "API 错误日志.xls", "数据", ApiErrorLogExcelVO.class, datas); + ExcelUtils.write(response, "API 错误日志.xls", "数据", ApiErrorLogRespVO.class, + BeanUtils.toBean(list, ApiErrorLogRespVO.class)); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java deleted file mode 100644 index daa3e72b7..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogBaseVO.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** -* API 访问日志 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class ApiAccessLogBaseVO { - - @Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "66600cb6-7852-11eb-9439-0242ac130002") - @NotNull(message = "链路追踪编号不能为空") - private String traceId; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "用户类型不能为空") - private Integer userType; - - @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard") - @NotNull(message = "应用名不能为空") - private String applicationName; - - @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") - @NotNull(message = "请求方法名不能为空") - private String requestMethod; - - @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy") - @NotNull(message = "请求地址不能为空") - private String requestUrl; - - @Schema(description = "请求参数") - private String requestParams; - - @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") - @NotNull(message = "用户 IP不能为空") - private String userIp; - - @Schema(description = "浏览器 UA", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0") - @NotNull(message = "浏览器 UA不能为空") - private String userAgent; - - @Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "开始请求时间不能为空") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime beginTime; - - @Schema(description = "结束请求时间", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "结束请求时间不能为空") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime endTime; - - @Schema(description = "执行时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - @NotNull(message = "执行时长不能为空") - private Integer duration; - - @Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "结果码不能为空") - private Integer resultCode; - - @Schema(description = "结果提示", example = "芋道源码,牛逼!") - private String resultMsg; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java deleted file mode 100644 index 21447743d..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExcelVO.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * API 访问日志 Excel VO - * - * @author 芋道源码 - */ -@Data -public class ApiAccessLogExcelVO { - - @ExcelProperty("日志主键") - private Long id; - - @ExcelProperty("链路追踪编号") - private String traceId; - - @ExcelProperty("用户编号") - private Long userId; - - @ExcelProperty(value = "用户类型", converter = DictConvert.class) - @DictFormat(DictTypeConstants.USER_TYPE) - private Integer userType; - - @ExcelProperty("应用名") - private String applicationName; - - @ExcelProperty("请求方法名") - private String requestMethod; - - @ExcelProperty("请求地址") - private String requestUrl; - - @ExcelProperty("请求参数") - private String requestParams; - - @ExcelProperty("用户 IP") - private String userIp; - - @ExcelProperty("浏览器 UA") - private String userAgent; - - @ExcelProperty("开始请求时间") - private LocalDateTime beginTime; - - @ExcelProperty("结束请求时间") - private LocalDateTime endTime; - - @ExcelProperty("执行时长") - private Integer duration; - - @ExcelProperty("结果码") - private Integer resultCode; - - @ExcelProperty("结果提示") - private String resultMsg; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java deleted file mode 100644 index 8010e3586..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogExportReqVO.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - API 访问日志 Excel 导出 Request VO,参数和 ApiAccessLogPageReqVO 是一致的") -@Data -public class ApiAccessLogExportReqVO { - - @Schema(description = "用户编号", example = "666") - private Long userId; - - @Schema(description = "用户类型", example = "2") - private Integer userType; - - @Schema(description = "应用名", example = "dashboard") - private String applicationName; - - @Schema(description = "请求地址,模糊匹配", example = "/xxx/yyy") - private String requestUrl; - - @Schema(description = "开始时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] beginTime; - - @Schema(description = "执行时长,大于等于,单位:毫秒", example = "100") - private Integer duration; - - @Schema(description = "结果码", example = "0") - private Integer resultCode; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index 4a6ec8ae5..5e3f3c976 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -1,21 +1,81 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; @Schema(description = "管理后台 - API 访问日志 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ApiAccessLogRespVO extends ApiAccessLogBaseVO { +@ExcelIgnoreUnannotated +public class ApiAccessLogRespVO { @Schema(description = "日志主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("日志主键") private Long id; + @Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "66600cb6-7852-11eb-9439-0242ac130002") + @ExcelProperty("链路追踪编号") + private String traceId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + @ExcelProperty("用户编号") + private Long userId; + + @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty(value = "用户类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.USER_TYPE) + private Integer userType; + + @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard") + @ExcelProperty("应用名") + private String applicationName; + + @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") + @ExcelProperty("请求方法名") + private String requestMethod; + + @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy") + @ExcelProperty("请求地址") + private String requestUrl; + + @Schema(description = "请求参数") + @ExcelProperty("请求参数") + private String requestParams; + + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") + @ExcelProperty("用户 IP") + private String userIp; + + @Schema(description = "浏览器 UA", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0") + @ExcelProperty("浏览器 UA") + private String userAgent; + + @Schema(description = "开始请求时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("开始请求时间") + private LocalDateTime beginTime; + + @Schema(description = "结束请求时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("结束请求时间") + private LocalDateTime endTime; + + @Schema(description = "执行时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @ExcelProperty("执行时长") + private Integer duration; + + @Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("结果码") + private Integer resultCode; + + @Schema(description = "结果提示", example = "芋道源码,牛逼!") + @ExcelProperty("结果提示") + private String resultMsg; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java deleted file mode 100644 index b489fd314..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogBaseVO.java +++ /dev/null @@ -1,96 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** -* API 错误日志 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class ApiErrorLogBaseVO { - - @Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "66600cb6-7852-11eb-9439-0242ac130002") - @NotNull(message = "链路追踪编号不能为空") - private String traceId; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - @NotNull(message = "用户编号不能为空") - private Integer userId; - - @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "用户类型不能为空") - private Integer userType; - - @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard") - @NotNull(message = "应用名不能为空") - private String applicationName; - - @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") - @NotNull(message = "请求方法名不能为空") - private String requestMethod; - - @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xx/yy") - @NotNull(message = "请求地址不能为空") - private String requestUrl; - - @Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "请求参数不能为空") - private String requestParams; - - @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") - @NotNull(message = "用户 IP不能为空") - private String userIp; - - @Schema(description = "浏览器 UA", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0") - @NotNull(message = "浏览器 UA不能为空") - private String userAgent; - - @Schema(description = "异常发生时间", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常发生时间不能为空") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime exceptionTime; - - @Schema(description = "异常名", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常名不能为空") - private String exceptionName; - - @Schema(description = "异常导致的消息", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常导致的消息不能为空") - private String exceptionMessage; - - @Schema(description = "异常导致的根消息", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常导致的根消息不能为空") - private String exceptionRootCauseMessage; - - @Schema(description = "异常的栈轨迹", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常的栈轨迹不能为空") - private String exceptionStackTrace; - - @Schema(description = "异常发生的类全名", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常发生的类全名不能为空") - private String exceptionClassName; - - @Schema(description = "异常发生的类文件", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常发生的类文件不能为空") - private String exceptionFileName; - - @Schema(description = "异常发生的方法名", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常发生的方法名不能为空") - private String exceptionMethodName; - - @Schema(description = "异常发生的方法所在行", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "异常发生的方法所在行不能为空") - private Integer exceptionLineNumber; - - @Schema(description = "处理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "处理状态不能为空") - private Integer processStatus; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java deleted file mode 100644 index 08f10894f..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExcelVO.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * API 错误日志 Excel VO - * - * @author 芋道源码 - */ -@Data -public class ApiErrorLogExcelVO { - - @ExcelProperty("编号") - private Integer id; - - @ExcelProperty("链路追踪编号") - private String traceId; - - @ExcelProperty("用户编号") - private Integer userId; - - @ExcelProperty(value = "用户类型", converter = DictConvert.class) - @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_TYPE) - private Integer userType; - - @ExcelProperty("应用名") - private String applicationName; - - @ExcelProperty("请求方法名") - private String requestMethod; - - @ExcelProperty("请求地址") - private String requestUrl; - - @ExcelProperty("请求参数") - private String requestParams; - - @ExcelProperty("用户 IP") - private String userIp; - - @ExcelProperty("浏览器 UA") - private String userAgent; - - @ExcelProperty("异常发生时间") - private LocalDateTime exceptionTime; - - @ExcelProperty("异常名") - private String exceptionName; - - @ExcelProperty("异常导致的消息") - private String exceptionMessage; - - @ExcelProperty("异常导致的根消息") - private String exceptionRootCauseMessage; - - @ExcelProperty("异常的栈轨迹") - private String exceptionStackTrace; - - @ExcelProperty("异常发生的类全名") - private String exceptionClassName; - - @ExcelProperty("异常发生的类文件") - private String exceptionFileName; - - @ExcelProperty("异常发生的方法名") - private String exceptionMethodName; - - @ExcelProperty("异常发生的方法所在行") - private Integer exceptionLineNumber; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - - @ExcelProperty(value = "处理状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.API_ERROR_LOG_PROCESS_STATUS) - private Integer processStatus; - - @ExcelProperty("处理时间") - private LocalDateTime processTime; - - @ExcelProperty("处理用户编号") - private Integer processUserId; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java deleted file mode 100644 index 792f2d7c0..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogExportReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - API 错误日志 Excel 导出 Request VO,参数和 ApiErrorLogPageReqVO 是一致的") -@Data -public class ApiErrorLogExportReqVO { - - @Schema(description = "用户编号", example = "666") - private Long userId; - - @Schema(description = "用户类型", example = "1") - private Integer userType; - - @Schema(description = "应用名", example = "dashboard") - private String applicationName; - - @Schema(description = "请求地址", example = "/xx/yy") - private String requestUrl; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "异常发生时间") - private LocalDateTime[] exceptionTime; - - @Schema(description = "处理状态", example = "0") - private Integer processStatus; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java index d1e547abb..2ceb0d033 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogPageReqVO.java @@ -36,4 +36,4 @@ public class ApiErrorLogPageReqVO extends PageParam { @Schema(description = "处理状态", example = "0") private Integer processStatus; -} \ No newline at end of file +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java index 5b2c8f8c3..53f52f02c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java @@ -1,28 +1,112 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; @Schema(description = "管理后台 - API 错误日志 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ApiErrorLogRespVO extends ApiErrorLogBaseVO { +@ExcelIgnoreUnannotated +public class ApiErrorLogRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") private Integer id; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; + @Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "66600cb6-7852-11eb-9439-0242ac130002") + @ExcelProperty("链路追踪编号") + private String traceId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + @ExcelProperty("用户编号") + private Integer userId; + + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "用户类型", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_TYPE) + private Integer userType; + + @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard") + @ExcelProperty("应用名") + private String applicationName; + + @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") + @ExcelProperty("请求方法名") + private String requestMethod; + + @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xx/yy") + @ExcelProperty("请求地址") + private String requestUrl; + + @Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("请求参数") + private String requestParams; + + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") + @ExcelProperty("用户 IP") + private String userIp; + + @Schema(description = "浏览器 UA", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0") + @ExcelProperty("浏览器 UA") + private String userAgent; + + @Schema(description = "异常发生时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常发生时间") + private LocalDateTime exceptionTime; + + @Schema(description = "异常名", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常名") + private String exceptionName; + + @Schema(description = "异常导致的消息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常导致的消息") + private String exceptionMessage; + + @Schema(description = "异常导致的根消息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常导致的根消息") + private String exceptionRootCauseMessage; + + @Schema(description = "异常的栈轨迹", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常的栈轨迹") + private String exceptionStackTrace; + + @Schema(description = "异常发生的类全名", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常发生的类全名") + private String exceptionClassName; + + @Schema(description = "异常发生的类文件", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常发生的类文件") + private String exceptionFileName; + + @Schema(description = "异常发生的方法名", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常发生的方法名") + private String exceptionMethodName; + + @Schema(description = "异常发生的方法所在行", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("异常发生的方法所在行") + private Integer exceptionLineNumber; + + @Schema(description = "处理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "处理状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.API_ERROR_LOG_PROCESS_STATUS) + private Integer processStatus; @Schema(description = "处理时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("处理时间") private LocalDateTime processTime; @Schema(description = "处理用户编号", example = "233") + @ExcelProperty("处理用户编号") private Integer processUserId; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http deleted file mode 100644 index ed65d0b86..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.http +++ /dev/null @@ -1,19 +0,0 @@ -### 请求 /infra/test-demo/get 接口 => 成功 -GET {{baseUrl}}/infra/test-demo/get?id=106 -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -### 请求 /infra/test-demo/update 接口 => 成功 -PUT {{baseUrl}}/infra/test-demo/update -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} -Content-Type: application/json - - -{ - "id": 106, - "name": "测试", - "status": "0", - "type": 1, - "category": 1 -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java deleted file mode 100755 index b64b49178..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/TestDemoController.java +++ /dev/null @@ -1,97 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.*; -import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import cn.iocoder.yudao.module.infra.service.test.TestDemoService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Operation; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.IOException; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Tag(name = "管理后台 - 字典类型") -@RestController -@RequestMapping("/infra/test-demo") -@Validated -public class TestDemoController { - - @Resource - private TestDemoService testDemoService; - - @PostMapping("/create") - @Operation(summary = "创建字典类型") - @PreAuthorize("@ss.hasPermission('infra:test-demo:create')") - public CommonResult createTestDemo(@Valid @RequestBody TestDemoCreateReqVO createReqVO) { - return success(testDemoService.createTestDemo(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新字典类型") - @PreAuthorize("@ss.hasPermission('infra:test-demo:update')") - public CommonResult updateTestDemo(@Valid @RequestBody TestDemoUpdateReqVO updateReqVO) { - testDemoService.updateTestDemo(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除字典类型") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:test-demo:delete')") - public CommonResult deleteTestDemo(@RequestParam("id") Long id) { - testDemoService.deleteTestDemo(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得字典类型") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('infra:test-demo:query')") - public CommonResult getTestDemo(@RequestParam("id") Long id) { - TestDemoDO testDemo = testDemoService.getTestDemo(id); - return success(TestDemoConvert.INSTANCE.convert(testDemo)); - } - - @GetMapping("/list") - @Operation(summary = "获得字典类型列表") - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") - @PreAuthorize("@ss.hasPermission('infra:test-demo:query')") - public CommonResult> getTestDemoList(@RequestParam("ids") Collection ids) { - List list = testDemoService.getTestDemoList(ids); - return success(TestDemoConvert.INSTANCE.convertList(list)); - } - - @GetMapping("/page") - @Operation(summary = "获得字典类型分页") - @PreAuthorize("@ss.hasPermission('infra:test-demo:query')") public CommonResult> getTestDemoPage(@Valid TestDemoPageReqVO pageVO) { - PageResult pageResult = testDemoService.getTestDemoPage(pageVO); - return success(TestDemoConvert.INSTANCE.convertPage(pageResult)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出字典类型 Excel") - @PreAuthorize("@ss.hasPermission('infra:test-demo:export')") @OperateLog(type = EXPORT) - public void exportTestDemoExcel(@Valid TestDemoExportReqVO exportReqVO, - HttpServletResponse response) throws IOException { - List list = testDemoService.getTestDemoList(exportReqVO); - // 导出 Excel - List datas = TestDemoConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "字典类型.xls", "数据", TestDemoExcelVO.class, datas); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java deleted file mode 100755 index a6f5d66ee..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoBaseVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/** -* 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ -@Data -public class TestDemoBaseVO { - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "名字不能为空") - private String name; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "状态不能为空") - private Integer status; - - @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "类型不能为空") - private Integer type; - - @Schema(description = "分类", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "分类不能为空") - private Integer category; - - @Schema(description = "备注") - private String remark; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoCreateReqVO.java deleted file mode 100755 index 21b9a5d92..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 字典类型创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TestDemoCreateReqVO extends TestDemoBaseVO { - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java deleted file mode 100755 index 8e1fa02c0..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExcelVO.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 字典类型 Excel VO - * - * @author 芋道源码 - */ -@Data -public class TestDemoExcelVO { - - @ExcelProperty("编号") - private Long id; - - @ExcelProperty("名字") - private String name; - - @ExcelProperty("状态") - private Integer status; - - @ExcelProperty("类型") - private Integer type; - - @ExcelProperty("分类") - private Integer category; - - @ExcelProperty("备注") - private String remark; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java deleted file mode 100755 index 20b215fd0..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoExportReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 字典类型 Excel 导出 Request VO,参数和 TestDemoPageReqVO 是一致的") -@Data -public class TestDemoExportReqVO { - - @Schema(description = "名字") - private String name; - - @Schema(description = "状态") - private Integer status; - - @Schema(description = "类型") - private Integer type; - - @Schema(description = "分类") - private Integer category; - - @Schema(description = "备注") - private String remark; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java deleted file mode 100755 index daa551ea3..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoRespVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 字典类型 Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TestDemoRespVO extends TestDemoBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) - private Long id; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoUpdateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoUpdateReqVO.java deleted file mode 100755 index 0866c4d7f..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/test/vo/TestDemoUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.infra.controller.admin.test.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 字典类型更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TestDemoUpdateReqVO extends TestDemoBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java index 1d286c52f..235e5f0d5 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/codegen/CodegenConvert.java @@ -56,7 +56,7 @@ public interface CodegenConvert { // ========== CodegenTableDO 相关 ========== -// List convertList02(List list); + List convertList05(List list); CodegenTableRespVO convert(CodegenTableDO bean); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java index 94bcc0eae..92094b0a9 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/config/ConfigConvert.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.infra.convert.config; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExcelVO; import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -19,15 +17,12 @@ public interface ConfigConvert { PageResult convertPage(PageResult page); + List convertList(List list); + @Mapping(source = "configKey", target = "key") ConfigRespVO convert(ConfigDO bean); @Mapping(source = "key", target = "configKey") - ConfigDO convert(ConfigCreateReqVO bean); - - ConfigDO convert(ConfigUpdateReqVO bean); - - @Mapping(source = "configKey", target = "key") - List convertList(List list); + ConfigDO convert(ConfigSaveReqVO bean); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java deleted file mode 100755 index d81d85cee..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/db/DataSourceConfigConvert.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.infra.convert.db; - -import java.util.*; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.*; -import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; - -/** - * 数据源配置 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface DataSourceConfigConvert { - - DataSourceConfigConvert INSTANCE = Mappers.getMapper(DataSourceConfigConvert.class); - - DataSourceConfigDO convert(DataSourceConfigCreateReqVO bean); - - DataSourceConfigDO convert(DataSourceConfigUpdateReqVO bean); - - DataSourceConfigRespVO convert(DataSourceConfigDO bean); - - List convertList(List list); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConfigConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConfigConvert.java index 442368302..7df2b57e6 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConfigConvert.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConfigConvert.java @@ -1,16 +1,11 @@ package cn.iocoder.yudao.module.infra.convert.file; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; -import java.util.List; - /** * 文件配置 Convert * @@ -22,15 +17,6 @@ public interface FileConfigConvert { FileConfigConvert INSTANCE = Mappers.getMapper(FileConfigConvert.class); @Mapping(target = "config", ignore = true) - FileConfigDO convert(FileConfigCreateReqVO bean); - - @Mapping(target = "config", ignore = true) - FileConfigDO convert(FileConfigUpdateReqVO bean); - - FileConfigRespVO convert(FileConfigDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); + FileConfigDO convert(FileConfigSaveReqVO bean); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java deleted file mode 100644 index ee7e5186b..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/file/FileConvert.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.infra.convert.file; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface FileConvert { - - FileConvert INSTANCE = Mappers.getMapper(FileConvert.class); - - FileRespVO convert(FileDO bean); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiAccessLogConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiAccessLogConvert.java deleted file mode 100644 index 03232bc75..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiAccessLogConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.infra.convert.logger; - -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLog; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExcelVO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogRespVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * API 访问日志 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface ApiAccessLogConvert { - - ApiAccessLogConvert INSTANCE = Mappers.getMapper(ApiAccessLogConvert.class); - - ApiAccessLogRespVO convert(ApiAccessLogDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - - ApiAccessLogDO convert(ApiAccessLogCreateReqDTO bean); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiErrorLogConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiErrorLogConvert.java deleted file mode 100644 index fb3a21d8c..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/logger/ApiErrorLogConvert.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.infra.convert.logger; - -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLog; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExcelVO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogRespVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * API 错误日志 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface ApiErrorLogConvert { - - ApiErrorLogConvert INSTANCE = Mappers.getMapper(ApiErrorLogConvert.class); - - ApiErrorLogRespVO convert(ApiErrorLogDO bean); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - - ApiErrorLogDO convert(ApiErrorLogCreateReqDTO bean); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/test/TestDemoConvert.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/test/TestDemoConvert.java deleted file mode 100755 index 07a29f5a2..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/convert/test/TestDemoConvert.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.infra.convert.test; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExcelVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 字典类型 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface TestDemoConvert { - - TestDemoConvert INSTANCE = Mappers.getMapper(TestDemoConvert.class); - - TestDemoDO convert(TestDemoCreateReqVO bean); - - TestDemoDO convert(TestDemoUpdateReqVO bean); - - TestDemoRespVO convert(TestDemoDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenTableDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenTableDO.java index fcad02354..faee8177e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenTableDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/codegen/CodegenTableDO.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; -import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -117,4 +116,43 @@ public class CodegenTableDO extends BaseDO { */ private Long parentMenuId; + // ========== 主子表相关字段 ========== + + /** + * 主表的编号 + * + * 关联 {@link CodegenTableDO#getId()} + */ + private Long masterTableId; + /** + * 【自己】子表关联主表的字段编号 + * + * 关联 {@link CodegenColumnDO#getId()} + */ + private Long subJoinColumnId; + /** + * 主表与子表是否一对多 + * + * true:一对多 + * false:一对一 + */ + private Boolean subJoinMany; + + // ========== 树表相关字段 ========== + + /** + * 树表的父字段编号 + * + * 关联 {@link CodegenColumnDO#getId()} + */ + private Long treeParentColumnId; + /** + * 树表的名字字段编号 + * + * 名字的用途:新增或修改时,select 框展示的字段 + * + * 关联 {@link CodegenColumnDO#getId()} + */ + private Long treeNameColumnId; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java new file mode 100644 index 000000000..753fea4f6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 示例联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_demo01_contact") +@KeySequence("infra_demo01_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Demo01ContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 出生年 + */ + private LocalDateTime birthday; + /** + * 简介 + */ + private String description; + /** + * 头像 + */ + private String avatar; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java new file mode 100644 index 000000000..2d1ea8e28 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 示例分类 DO + * + * @author 芋道源码 + */ +@TableName("infra_demo02_category") +@KeySequence("infra_demo02_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Demo02CategoryDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 父级编号 + */ + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/test/TestDemoDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java old mode 100755 new mode 100644 similarity index 52% rename from yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/test/TestDemoDO.java rename to yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java index da1f4cb53..eb10c425e --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/test/TestDemoDO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.infra.dal.dataobject.test; +package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -7,44 +7,36 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; /** - * 字典类型 DO + * 学生课程 DO * * @author 芋道源码 */ -@TableName("infra_test_demo") -@KeySequence("infra_test_demo_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("infra_demo03_course") +@KeySequence("infra_demo03_course_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class TestDemoDO extends BaseDO { +public class Demo03CourseDO extends BaseDO { /** * 编号 */ @TableId private Long id; + /** + * 学生编号 + */ + private Long studentId; /** * 名字 */ private String name; /** - * 状态 + * 分数 */ - private Integer status; - /** - * 类型 - */ - private Integer type; - /** - * 分类 - */ - private Integer category; - /** - * 备注 - */ - private String remark; + private Integer score; -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java new file mode 100644 index 000000000..4720923de --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 学生班级 DO + * + * @author 芋道源码 + */ +@TableName("infra_demo03_grade") +@KeySequence("infra_demo03_grade_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Demo03GradeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 班主任 + */ + private String teacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java new file mode 100644 index 000000000..6baf29c65 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_demo03_student") +@KeySequence("infra_demo03_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Demo03StudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 简介 + */ + private String description; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/CodegenTableMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/CodegenTableMapper.java index 006e24bd1..1e4697d33 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/CodegenTableMapper.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/codegen/CodegenTableMapper.java @@ -29,4 +29,9 @@ public interface CodegenTableMapper extends BaseMapperX { return selectList(CodegenTableDO::getDataSourceConfigId, dataSourceConfigId); } + default List selectListByTemplateTypeAndMasterTableId(Integer templateType, Long masterTableId) { + return selectList(CodegenTableDO::getTemplateType, templateType, + CodegenTableDO::getMasterTableId, masterTableId); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java index 49eea5517..466403c6e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/config/ConfigMapper.java @@ -3,13 +3,10 @@ package cn.iocoder.yudao.module.infra.dal.mysql.config; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - @Mapper public interface ConfigMapper extends BaseMapperX { @@ -25,12 +22,4 @@ public interface ConfigMapper extends BaseMapperX { .betweenIfPresent(ConfigDO::getCreateTime, reqVO.getCreateTime())); } - default List selectList(ConfigExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(ConfigDO::getName, reqVO.getName()) - .likeIfPresent(ConfigDO::getConfigKey, reqVO.getKey()) - .eqIfPresent(ConfigDO::getType, reqVO.getType()) - .betweenIfPresent(ConfigDO::getCreateTime, reqVO.getCreateTime())); - } - } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java new file mode 100644 index 000000000..916dcfc2c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo01; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 示例联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface Demo01ContactMapper extends BaseMapperX { + + default PageResult selectPage(Demo01ContactPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(Demo01ContactDO::getName, reqVO.getName()) + .eqIfPresent(Demo01ContactDO::getSex, reqVO.getSex()) + .betweenIfPresent(Demo01ContactDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(Demo01ContactDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java new file mode 100644 index 000000000..0bdd203c0 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo02; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 示例分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface Demo02CategoryMapper extends BaseMapperX { + + default List selectList(Demo02CategoryListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(Demo02CategoryDO::getName, reqVO.getName()) + .eqIfPresent(Demo02CategoryDO::getParentId, reqVO.getParentId()) + .betweenIfPresent(Demo02CategoryDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(Demo02CategoryDO::getId)); + } + + default Demo02CategoryDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(Demo02CategoryDO::getParentId, parentId, Demo02CategoryDO::getName, name); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(Demo02CategoryDO::getParentId, parentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java new file mode 100644 index 000000000..3cb3aa592 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 学生课程 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface Demo03CourseMapper extends BaseMapperX { + + default PageResult selectPage(PageParam reqVO, Long studentId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(Demo03CourseDO::getStudentId, studentId) + .orderByDesc(Demo03CourseDO::getId)); + } + + default List selectListByStudentId(Long studentId) { + return selectList(Demo03CourseDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(Demo03CourseDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java new file mode 100644 index 000000000..0440cc49e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班级 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface Demo03GradeMapper extends BaseMapperX { + + default PageResult selectPage(PageParam reqVO, Long studentId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(Demo03GradeDO::getStudentId, studentId) + .orderByDesc(Demo03GradeDO::getId)); + } + + default Demo03GradeDO selectByStudentId(Long studentId) { + return selectOne(Demo03GradeDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(Demo03GradeDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java new file mode 100644 index 000000000..eb62b72a7 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface Demo03StudentMapper extends BaseMapperX { + + default PageResult selectPage(Demo03StudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(Demo03StudentDO::getName, reqVO.getName()) + .eqIfPresent(Demo03StudentDO::getSex, reqVO.getSex()) + .eqIfPresent(Demo03StudentDO::getDescription, reqVO.getDescription()) + .betweenIfPresent(Demo03StudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(Demo03StudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java index 77c479817..dce30829f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiAccessLogMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.dal.mysql.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; import org.apache.ibatis.annotations.Delete; @@ -11,7 +10,6 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.time.LocalDateTime; -import java.util.List; /** * API 访问日志 Mapper @@ -34,19 +32,6 @@ public interface ApiAccessLogMapper extends BaseMapperX { ); } - default List selectList(ApiAccessLogExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(ApiAccessLogDO::getUserId, reqVO.getUserId()) - .eqIfPresent(ApiAccessLogDO::getUserType, reqVO.getUserType()) - .eqIfPresent(ApiAccessLogDO::getApplicationName, reqVO.getApplicationName()) - .likeIfPresent(ApiAccessLogDO::getRequestUrl, reqVO.getRequestUrl()) - .betweenIfPresent(ApiAccessLogDO::getBeginTime, reqVO.getBeginTime()) - .geIfPresent(ApiAccessLogDO::getDuration, reqVO.getDuration()) - .eqIfPresent(ApiAccessLogDO::getResultCode, reqVO.getResultCode()) - .orderByDesc(ApiAccessLogDO::getId) - ); - } - /** * 物理删除指定时间之前的日志 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java index 4a9432ef4..b597d7929 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/logger/ApiErrorLogMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.dal.mysql.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; import org.apache.ibatis.annotations.Delete; @@ -11,7 +10,6 @@ import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.time.LocalDateTime; -import java.util.List; /** * API 错误日志 Mapper @@ -33,18 +31,6 @@ public interface ApiErrorLogMapper extends BaseMapperX { ); } - default List selectList(ApiErrorLogExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(ApiErrorLogDO::getUserId, reqVO.getUserId()) - .eqIfPresent(ApiErrorLogDO::getUserType, reqVO.getUserType()) - .eqIfPresent(ApiErrorLogDO::getApplicationName, reqVO.getApplicationName()) - .likeIfPresent(ApiErrorLogDO::getRequestUrl, reqVO.getRequestUrl()) - .betweenIfPresent(ApiErrorLogDO::getExceptionTime, reqVO.getExceptionTime()) - .eqIfPresent(ApiErrorLogDO::getProcessStatus, reqVO.getProcessStatus()) - .orderByDesc(ApiErrorLogDO::getId) - ); - } - /** * 物理删除指定时间之前的日志 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/test/TestDemoMapper.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/test/TestDemoMapper.java deleted file mode 100755 index d600b3f4b..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/test/TestDemoMapper.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.infra.dal.mysql.test; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * 字典类型 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface TestDemoMapper extends BaseMapperX { - - default PageResult selectPage(TestDemoPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(TestDemoDO::getName, reqVO.getName()) - .eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus()) - .eqIfPresent(TestDemoDO::getType, reqVO.getType()) - .eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory()) - .eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark()) - .betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TestDemoDO::getId)); - } - - default List selectList(TestDemoExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(TestDemoDO::getName, reqVO.getName()) - .eqIfPresent(TestDemoDO::getStatus, reqVO.getStatus()) - .eqIfPresent(TestDemoDO::getType, reqVO.getType()) - .eqIfPresent(TestDemoDO::getCategory, reqVO.getCategory()) - .eqIfPresent(TestDemoDO::getRemark, reqVO.getRemark()) - .betweenIfPresent(TestDemoDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TestDemoDO::getId)); - } - - List selectList2(); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenColumnHtmlTypeEnum.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenColumnHtmlTypeEnum.java index 5474ba1a8..2c0cdbb8a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenColumnHtmlTypeEnum.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenColumnHtmlTypeEnum.java @@ -16,8 +16,8 @@ public enum CodegenColumnHtmlTypeEnum { RADIO("radio"), // 单选框 CHECKBOX("checkbox"), // 复选框 DATETIME("datetime"), // 日期控件 - UPLOAD_IMAGE("upload_image"), // 上传图片 - UPLOAD_FILE("upload_file"), // 上传文件 + IMAGE_UPLOAD("imageUpload"), // 上传图片 + FILE_UPLOAD("fileUpload"), // 上传文件 EDITOR("editor"), // 富文本控件 ; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenTemplateTypeEnum.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenTemplateTypeEnum.java index ce2799e34..9a218331c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenTemplateTypeEnum.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenTemplateTypeEnum.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.infra.enums.codegen; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Objects; + /** * 代码生成模板类型 * @@ -12,8 +15,13 @@ import lombok.Getter; @Getter public enum CodegenTemplateTypeEnum { - CRUD(1), // 单表(增删改查) + ONE(1), // 单表(增删改查) TREE(2), // 树表(增删改查) + + MASTER_NORMAL(10), // 主子表 - 主表 - 普通模式 + MASTER_ERP(11), // 主子表 - 主表 - ERP 模式 + MASTER_INNER(12), // 主子表 - 主表 - 内嵌模式 + SUB(15), // 主子表 - 子表 ; /** @@ -21,4 +29,25 @@ public enum CodegenTemplateTypeEnum { */ private final Integer type; + /** + * 是否为主表 + * + * @param type 类型 + * @return 是否主表 + */ + public static boolean isMaster(Integer type) { + return ObjectUtils.equalsAny(type, + MASTER_NORMAL.type, MASTER_ERP.type, MASTER_INNER.type); + } + + /** + * 是否为树表 + * + * @param type 类型 + * @return 是否树表 + */ + public static boolean isTree(Integer type) { + return Objects.equals(type, TREE.type); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java index d4d266a72..a84e854a0 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenService.java @@ -48,6 +48,14 @@ public interface CodegenService { */ void deleteCodegen(Long tableId); + /** + * 获得表定义列表 + * + * @param dataSourceConfigId 数据源配置的编号 + * @return 表定义列表 + */ + List getCodegenTableList(Long dataSourceConfigId); + /** * 获得表定义分页 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java index 029fe4162..9400e422a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenColumnMapper; import cn.iocoder.yudao.module.infra.dal.mysql.codegen.CodegenTableMapper; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenBuilder; import cn.iocoder.yudao.module.infra.service.codegen.inner.CodegenEngine; @@ -25,10 +26,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.BiPredicate; import java.util.stream.Collectors; @@ -129,6 +127,16 @@ public class CodegenServiceImpl implements CodegenService { if (codegenTableMapper.selectById(updateReqVO.getTable().getId()) == null) { throw exception(CODEGEN_TABLE_NOT_EXISTS); } + // 校验主表字段存在 + if (Objects.equals(updateReqVO.getTable().getTemplateType(), CodegenTemplateTypeEnum.SUB.getType())) { + if (codegenTableMapper.selectById(updateReqVO.getTable().getMasterTableId()) == null) { + throw exception(CODEGEN_MASTER_TABLE_NOT_EXISTS, updateReqVO.getTable().getMasterTableId()); + } + if (CollUtil.findOne(updateReqVO.getColumns(), // 关联主表的字段不存在 + column -> column.getId().equals(updateReqVO.getTable().getSubJoinColumnId())) == null) { + throw exception(CODEGEN_SUB_COLUMN_NOT_EXISTS, updateReqVO.getTable().getSubJoinColumnId()); + } + } // 更新 table 表定义 CodegenTableDO updateTableObj = CodegenConvert.INSTANCE.convert(updateReqVO.getTable()); @@ -208,6 +216,11 @@ public class CodegenServiceImpl implements CodegenService { codegenColumnMapper.deleteListByTableId(tableId); } + @Override + public List getCodegenTableList(Long dataSourceConfigId) { + return codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId); + } + @Override public PageResult getCodegenTablePage(CodegenTablePageReqVO pageReqVO) { return codegenTableMapper.selectPage(pageReqVO); @@ -235,14 +248,34 @@ public class CodegenServiceImpl implements CodegenService { throw exception(CODEGEN_COLUMN_NOT_EXISTS); } + // 如果是主子表,则加载对应的子表信息 + List subTables = null; + List> subColumnsList = null; + if (CodegenTemplateTypeEnum.isMaster(table.getTemplateType())) { + // 校验子表存在 + subTables = codegenTableMapper.selectListByTemplateTypeAndMasterTableId( + CodegenTemplateTypeEnum.SUB.getType(), tableId); + if (CollUtil.isEmpty(subTables)) { + throw exception(CODEGEN_MASTER_GENERATION_FAIL_NO_SUB_TABLE); + } + // 校验子表的关联字段存在 + subColumnsList = new ArrayList<>(); + for (CodegenTableDO subTable : subTables) { + List subColumns = codegenColumnMapper.selectListByTableId(subTable.getId()); + if (CollUtil.findOne(subColumns, column -> column.getId().equals(subTable.getSubJoinColumnId())) == null) { + throw exception(CODEGEN_SUB_COLUMN_NOT_EXISTS, subTable.getId()); + } + subColumnsList.add(subColumns); + } + } + // 执行生成 - return codegenEngine.execute(table, columns); + return codegenEngine.execute(table, columns, subTables, subColumnsList); } @Override public List getDatabaseTableList(Long dataSourceConfigId, String name, String comment) { List tables = databaseTableService.getTableList(dataSourceConfigId, name, comment); - // 移除已经生成的表 // 移除在 Codegen 中,已经存在的 Set existsTables = CollectionUtils.convertSet( codegenTableMapper.selectListByDataSourceConfigId(dataSourceConfigId), CodegenTableDO::getTableName); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java index 8293ffef0..b529c4981 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java @@ -15,6 +15,7 @@ import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.google.common.collect.Sets; import org.springframework.stereotype.Component; +import java.time.LocalDateTime; import java.util.*; import static cn.hutool.core.text.CharSequenceUtil.*; @@ -49,8 +50,8 @@ public class CodegenBuilder { .put("status", CodegenColumnHtmlTypeEnum.RADIO) .put("sex", CodegenColumnHtmlTypeEnum.RADIO) .put("type", CodegenColumnHtmlTypeEnum.SELECT) - .put("image", CodegenColumnHtmlTypeEnum.UPLOAD_IMAGE) - .put("file", CodegenColumnHtmlTypeEnum.UPLOAD_FILE) + .put("image", CodegenColumnHtmlTypeEnum.IMAGE_UPLOAD) + .put("file", CodegenColumnHtmlTypeEnum.FILE_UPLOAD) .put("content", CodegenColumnHtmlTypeEnum.EDITOR) .put("description", CodegenColumnHtmlTypeEnum.EDITOR) .put("demo", CodegenColumnHtmlTypeEnum.EDITOR) @@ -118,7 +119,7 @@ public class CodegenBuilder { table.setClassName(upperFirst(toCamelCase(subAfter(tableName, '_', false)))); // 去除结尾的表,作为类描述 table.setClassComment(StrUtil.removeSuffixIgnoreCase(table.getTableComment(), "表")); - table.setTemplateType(CodegenTemplateTypeEnum.CRUD.getType()); + table.setTemplateType(CodegenTemplateTypeEnum.ONE.getType()); } public List buildColumns(Long tableId, List tableFields) { @@ -127,6 +128,10 @@ public class CodegenBuilder { for (CodegenColumnDO column : columns) { column.setTableId(tableId); column.setOrdinalPosition(index++); + // 特殊处理:Byte => Integer + if (Byte.class.getSimpleName().equals(column.getJavaType())) { + column.setJavaType(Integer.class.getSimpleName()); + } // 初始化 Column 列的默认字段 processColumnOperation(column); // 处理 CRUD 相关的字段的默认值 processColumnUI(column); // 处理 UI 相关的字段的默认值 @@ -162,10 +167,13 @@ public class CodegenBuilder { .filter(entry -> StrUtil.endWithIgnoreCase(column.getJavaField(), entry.getKey())) .findFirst().ifPresent(entry -> column.setHtmlType(entry.getValue().getType())); // 如果是 Boolean 类型时,设置为 radio 类型. - // 其它类型,因为字段名可以相对保障,所以不进行处理。例如说 date 对应 datetime 类型. if (Boolean.class.getSimpleName().equals(column.getJavaType())) { column.setHtmlType(CodegenColumnHtmlTypeEnum.RADIO.getType()); } + // 如果是 LocalDateTime 类型,则设置为 datetime 类型 + if (LocalDateTime.class.getSimpleName().equals(column.getJavaType())) { + column.setHtmlType(CodegenColumnHtmlTypeEnum.DATETIME.getType()); + } // 兜底,设置默认为 input 类型 if (column.getHtmlType() == null) { column.setHtmlType(CodegenColumnHtmlTypeEnum.INPUT.getType()); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index 40c7a41c7..ce8351cfd 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.infra.service.codegen.inner; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.template.TemplateConfig; import cn.hutool.extra.template.TemplateEngine; @@ -12,7 +14,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -25,7 +29,9 @@ import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenColumnDO; import cn.iocoder.yudao.module.infra.dal.dataobject.codegen.CodegenTableDO; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenFrontTypeEnum; import cn.iocoder.yudao.module.infra.enums.codegen.CodegenSceneEnum; +import cn.iocoder.yudao.module.infra.enums.codegen.CodegenTemplateTypeEnum; import cn.iocoder.yudao.module.infra.framework.codegen.config.CodegenProperties; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Maps; import com.google.common.collect.Table; @@ -33,10 +39,7 @@ import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.hutool.core.map.MapUtil.getStr; import static cn.hutool.core.text.CharSequenceUtil.*; @@ -60,20 +63,19 @@ public class CodegenEngine { */ private static final Map SERVER_TEMPLATES = MapUtil.builder(new LinkedHashMap<>()) // 有序 // Java module-biz Main - .put(javaTemplatePath("controller/vo/baseVO"), javaModuleImplVOFilePath("BaseVO")) - .put(javaTemplatePath("controller/vo/createReqVO"), javaModuleImplVOFilePath("CreateReqVO")) .put(javaTemplatePath("controller/vo/pageReqVO"), javaModuleImplVOFilePath("PageReqVO")) + .put(javaTemplatePath("controller/vo/listReqVO"), javaModuleImplVOFilePath("ListReqVO")) .put(javaTemplatePath("controller/vo/respVO"), javaModuleImplVOFilePath("RespVO")) - .put(javaTemplatePath("controller/vo/updateReqVO"), javaModuleImplVOFilePath("UpdateReqVO")) - .put(javaTemplatePath("controller/vo/exportReqVO"), javaModuleImplVOFilePath("ExportReqVO")) - .put(javaTemplatePath("controller/vo/excelVO"), javaModuleImplVOFilePath("ExcelVO")) + .put(javaTemplatePath("controller/vo/saveReqVO"), javaModuleImplVOFilePath("SaveReqVO")) .put(javaTemplatePath("controller/controller"), javaModuleImplControllerFilePath()) - .put(javaTemplatePath("convert/convert"), - javaModuleImplMainFilePath("convert/${table.businessName}/${table.className}Convert")) .put(javaTemplatePath("dal/do"), javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${table.className}DO")) + .put(javaTemplatePath("dal/do_sub"), // 特殊:主子表专属逻辑 + javaModuleImplMainFilePath("dal/dataobject/${table.businessName}/${subTable.className}DO")) .put(javaTemplatePath("dal/mapper"), javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${table.className}Mapper")) + .put(javaTemplatePath("dal/mapper_sub"), // 特殊:主子表专属逻辑 + javaModuleImplMainFilePath("dal/mysql/${table.businessName}/${subTable.className}Mapper")) .put(javaTemplatePath("dal/mapper.xml"), mapperXmlFilePath()) .put(javaTemplatePath("service/serviceImpl"), javaModuleImplMainFilePath("service/${table.businessName}/${table.className}ServiceImpl")) @@ -99,34 +101,56 @@ public class CodegenEngine { private static final Table FRONT_TEMPLATES = ImmutableTable.builder() // Vue2 标准模版 .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/index.vue"), - vueFilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vueFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("api/api.js"), - vueFilePath("api/${table.moduleName}/${classNameVar}.js")) + vueFilePath("api/${table.moduleName}/${table.businessName}/index.js")) + .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/form.vue"), + vueFilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑 + vueFilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑 + vueFilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/components/form_sub_erp.vue"), // 特殊:主子表专属逻辑 + vueFilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/components/list_sub_inner.vue"), // 特殊:主子表专属逻辑 + vueFilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) + .put(CodegenFrontTypeEnum.VUE2.getType(), vueTemplatePath("views/components/list_sub_erp.vue"), // 特殊:主子表专属逻辑 + vueFilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) // Vue3 标准模版 .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_normal.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_inner.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/form_sub_erp.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}Form.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_inner.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) + .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("views/components/list_sub_erp.vue"), // 特殊:主子表专属逻辑 + vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // Vue3 Schema 模版 .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Form.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // Vue3 vben 模版 .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${classNameVar}.data.ts")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/index.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${classNameVar}/${simpleClassName}Modal.vue")) + vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${classNameVar}/index.ts")) + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .build(); @Resource @@ -149,7 +173,8 @@ public class CodegenEngine { } @PostConstruct - private void initGlobalBindingMap() { + @VisibleForTesting + void initGlobalBindingMap() { // 全局配置 globalBindingMap.put("basePackage", codegenProperties.getBasePackage()); globalBindingMap.put("baseFrameworkPackage", codegenProperties.getBasePackage() @@ -174,9 +199,126 @@ public class CodegenEngine { globalBindingMap.put("DictConvertClassName", DictConvert.class.getName()); globalBindingMap.put("OperateLogClassName", OperateLog.class.getName()); globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName()); + globalBindingMap.put("BeanUtils", BeanUtils.class.getName()); } - public Map execute(CodegenTableDO table, List columns) { + /** + * 生成代码 + * + * @param table 表定义 + * @param columns table 的字段定义数组 + * @param subTables 子表数组,当且仅当主子表时使用 + * @param subColumnsList subTables 的字段定义数组 + * @return 生成的代码,key 是路径,value 是对应代码 + */ + public Map execute(CodegenTableDO table, List columns, + List subTables, List> subColumnsList) { + // 1.1 初始化 bindMap 上下文 + Map bindingMap = initBindingMap(table, columns, subTables, subColumnsList); + // 1.2 获得模版 + Map templates = getTemplates(table.getFrontType()); + + // 2. 执行生成 + Map result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 + templates.forEach((vmPath, filePath) -> { + // 2.1 特殊:主子表专属逻辑 + if (isSubTemplate(vmPath)) { + generateSubCode(table, subTables, result, vmPath, filePath, bindingMap); + return; + // 2.2 特殊:树表专属逻辑 + } else if (isPageReqVOTemplate(vmPath)) { + // 减少多余的类生成,例如说 PageVO.java 类 + if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { + return; + } + } else if (isListReqVOTemplate(vmPath)) { + // 减少多余的类生成,例如说 ListVO.java 类 + if (!CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { + return; + } + } + // 2.3 默认生成 + generateCode(result, vmPath, filePath, bindingMap); + }); + return result; + } + + private void generateCode(Map result, String vmPath, + String filePath, Map bindingMap) { + filePath = formatFilePath(filePath, bindingMap); + String content = templateEngine.getTemplate(vmPath).render(bindingMap); + // 格式化代码 + content = prettyCode(content); + result.put(filePath, content); + } + + private void generateSubCode(CodegenTableDO table, List subTables, + Map result, String vmPath, + String filePath, Map bindingMap) { + // 没有子表,所以不生成 + if (CollUtil.isEmpty(subTables)) { + return; + } + // 主子表的模式匹配。目的:过滤掉个性化的模版 + if (vmPath.contains("_normal") + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_NORMAL.getType())) { + return; + } + if (vmPath.contains("_erp") + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_ERP.getType())) { + return; + } + if (vmPath.contains("_inner") + && ObjectUtil.notEqual(table.getTemplateType(), CodegenTemplateTypeEnum.MASTER_INNER.getType())) { + return; + } + + // 逐个生成 + for (int i = 0; i < subTables.size(); i++) { + bindingMap.put("subIndex", i); + generateCode(result, vmPath, filePath, bindingMap); + } + bindingMap.remove("subIndex"); + } + + /** + * 格式化生成后的代码 + * + * 因为尽量让 vm 模版简单,所以统一的处理都在这个方法。 + * 如果不处理,Vue 的 Pretty 格式校验可能会报错 + * + * @param content 格式化前的代码 + * @return 格式化后的代码 + */ + private String prettyCode(String content) { + // Vue 界面:去除字段后面多余的 , 逗号,解决前端的 Pretty 代码格式检查的报错 + content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }"); + // Vue 界面:去除多的 dateFormatter,只有一个的情况下,说明没使用到 + if (StrUtil.count(content, "dateFormatter") == 1) { + content = StrUtils.removeLineContains(content, "dateFormatter"); + } + // Vue2 界面:修正 $refs + if (StrUtil.count(content, "this.refs") >= 1) { + content = content.replace("this.refs", "this.$refs"); + } + // Vue 界面:去除多的 dict 相关,只有一个的情况下,说明没使用到 + if (StrUtil.count(content, "getIntDictOptions") == 1) { + content = content.replace("getIntDictOptions, ", ""); + } + if (StrUtil.count(content, "getStrDictOptions") == 1) { + content = content.replace("getStrDictOptions, ", ""); + } + if (StrUtil.count(content, "getBoolDictOptions") == 1) { + content = content.replace("getBoolDictOptions, ", ""); + } + if (StrUtil.count(content, "DICT_TYPE.") == 0) { + content = StrUtils.removeLineContains(content, "DICT_TYPE"); + } + return content; + } + + private Map initBindingMap(CodegenTableDO table, List columns, + List subTables, List> subColumnsList) { // 创建 bindingMap Map bindingMap = new HashMap<>(globalBindingMap); bindingMap.put("table", table); @@ -196,17 +338,54 @@ public class CodegenEngine { // permission 前缀 bindingMap.put("permissionPrefix", table.getModuleName() + ":" + simpleClassNameStrikeCase); - // 执行生成 - Map templates = getTemplates(table.getFrontType()); - Map result = Maps.newLinkedHashMapWithExpectedSize(templates.size()); // 有序 - templates.forEach((vmPath, filePath) -> { - filePath = formatFilePath(filePath, bindingMap); - String content = templateEngine.getTemplate(vmPath).render(bindingMap); - // 去除字段后面多余的 , 逗号 - content = content.replaceAll(",\n}", "\n}").replaceAll(",\n }", "\n }"); - result.put(filePath, content); - }); - return result; + // 特殊:树表专属逻辑 + if (CodegenTemplateTypeEnum.isTree(table.getTemplateType())) { + CodegenColumnDO treeParentColumn = CollUtil.findOne(columns, + column -> Objects.equals(column.getId(), table.getTreeParentColumnId())); + bindingMap.put("treeParentColumn", treeParentColumn); + bindingMap.put("treeParentColumn_javaField_underlineCase", toUnderlineCase(treeParentColumn.getJavaField())); + CodegenColumnDO treeNameColumn = CollUtil.findOne(columns, + column -> Objects.equals(column.getId(), table.getTreeNameColumnId())); + bindingMap.put("treeNameColumn", treeNameColumn); + bindingMap.put("treeNameColumn_javaField_underlineCase", toUnderlineCase(treeNameColumn.getJavaField())); + } + + // 特殊:主子表专属逻辑 + if (CollUtil.isNotEmpty(subTables)) { + // 创建 bindingMap + bindingMap.put("subTables", subTables); + bindingMap.put("subColumnsList", subColumnsList); + List subPrimaryColumns = new ArrayList<>(); + List subJoinColumns = new ArrayList<>(); + List subJoinColumnStrikeCases = new ArrayList<>(); + List subSimpleClassNames = new ArrayList<>(); + List subClassNameVars = new ArrayList<>(); + List simpleClassNameUnderlineCases = new ArrayList<>(); + List subSimpleClassNameStrikeCases = new ArrayList<>(); + for (int i = 0; i < subTables.size(); i++) { + CodegenTableDO subTable = subTables.get(i); + List subColumns = subColumnsList.get(i); + subPrimaryColumns.add(CollectionUtils.findFirst(subColumns, CodegenColumnDO::getPrimaryKey)); // + CodegenColumnDO subColumn = CollectionUtils.findFirst(subColumns, // 关联的字段 + column -> Objects.equals(column.getId(), subTable.getSubJoinColumnId())); + subJoinColumns.add(subColumn); + subJoinColumnStrikeCases.add(toSymbolCase(subColumn.getJavaField(), '-')); // 将 DictType 转换成 dict-type + // className 相关 + String subSimpleClassName = removePrefix(subTable.getClassName(), upperFirst(subTable.getModuleName())); + subSimpleClassNames.add(subSimpleClassName); + simpleClassNameUnderlineCases.add(toUnderlineCase(subSimpleClassName)); // 将 DictType 转换成 dict_type + subClassNameVars.add(lowerFirst(subSimpleClassName)); // 将 DictType 转换成 dictType,用于变量 + subSimpleClassNameStrikeCases.add(toSymbolCase(subSimpleClassName, '-')); // 将 DictType 转换成 dict-type + } + bindingMap.put("subPrimaryColumns", subPrimaryColumns); + bindingMap.put("subJoinColumns", subJoinColumns); + bindingMap.put("subJoinColumn_strikeCases", subJoinColumnStrikeCases); + bindingMap.put("subSimpleClassNames", subSimpleClassNames); + bindingMap.put("simpleClassNameUnderlineCases", simpleClassNameUnderlineCases); + bindingMap.put("subClassNameVars", subClassNameVars); + bindingMap.put("subSimpleClassName_strikeCases", subSimpleClassNameStrikeCases); + } + return bindingMap; } private Map getTemplates(Integer frontType) { @@ -216,6 +395,7 @@ public class CodegenEngine { return templates; } + @SuppressWarnings("unchecked") private String formatFilePath(String filePath, Map bindingMap) { filePath = StrUtil.replace(filePath, "${basePackage}", getStr(bindingMap, "basePackage").replaceAll("\\.", "/")); @@ -232,6 +412,16 @@ public class CodegenEngine { filePath = StrUtil.replace(filePath, "${table.moduleName}", table.getModuleName()); filePath = StrUtil.replace(filePath, "${table.businessName}", table.getBusinessName()); filePath = StrUtil.replace(filePath, "${table.className}", table.getClassName()); + // 特殊:主子表专属逻辑 + Integer subIndex = (Integer) bindingMap.get("subIndex"); + if (subIndex != null) { + CodegenTableDO subTable = ((List) bindingMap.get("subTables")).get(subIndex); + filePath = StrUtil.replace(filePath, "${subTable.moduleName}", subTable.getModuleName()); + filePath = StrUtil.replace(filePath, "${subTable.businessName}", subTable.getBusinessName()); + filePath = StrUtil.replace(filePath, "${subTable.className}", subTable.getClassName()); + filePath = StrUtil.replace(filePath, "${subSimpleClassName}", + ((List) bindingMap.get("subSimpleClassNames")).get(subIndex)); + } return filePath; } @@ -278,7 +468,7 @@ public class CodegenEngine { } private static String vueFilePath(String path) { - return "yudao-ui-${sceneEnum.basePackage}/" + // 顶级目录 + return "yudao-ui-${sceneEnum.basePackage}-vue2/" + // 顶级目录 "src/" + path; } @@ -298,4 +488,17 @@ public class CodegenEngine { private static String vue3VbenTemplatePath(String path) { return "codegen/vue3_vben/" + path + ".vm"; } + + private static boolean isSubTemplate(String path) { + return path.contains("_sub"); + } + + private static boolean isPageReqVOTemplate(String path) { + return path.contains("pageReqVO"); + } + + private static boolean isListReqVOTemplate(String path) { + return path.contains("listReqVO"); + } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java index abd82e54a..a6979023f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigService.java @@ -1,14 +1,11 @@ package cn.iocoder.yudao.module.infra.service.config; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import javax.validation.Valid; -import java.util.List; /** * 参数配置 Service 接口 @@ -20,17 +17,17 @@ public interface ConfigService { /** * 创建参数配置 * - * @param reqVO 创建信息 + * @param createReqVO 创建信息 * @return 配置编号 */ - Long createConfig(@Valid ConfigCreateReqVO reqVO); + Long createConfig(@Valid ConfigSaveReqVO createReqVO); /** * 更新参数配置 * - * @param reqVO 更新信息 + * @param updateReqVO 更新信息 */ - void updateConfig(@Valid ConfigUpdateReqVO reqVO); + void updateConfig(@Valid ConfigSaveReqVO updateReqVO); /** * 删除参数配置 @@ -63,13 +60,4 @@ public interface ConfigService { */ PageResult getConfigPage(@Valid ConfigPageReqVO reqVO); - /** - * 获得参数配置列表 - * - * @param reqVO 列表 - * @return 列表 - */ - List getConfigList(@Valid ConfigExportReqVO reqVO); - - } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java index 51c912be7..6d14ad9fc 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/config/ConfigServiceImpl.java @@ -1,11 +1,8 @@ package cn.iocoder.yudao.module.infra.service.config; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.config.vo.ConfigSaveReqVO; import cn.iocoder.yudao.module.infra.convert.config.ConfigConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.config.ConfigDO; import cn.iocoder.yudao.module.infra.dal.mysql.config.ConfigMapper; @@ -16,7 +13,6 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; @@ -33,22 +29,26 @@ public class ConfigServiceImpl implements ConfigService { private ConfigMapper configMapper; @Override - public Long createConfig(ConfigCreateReqVO reqVO) { - // 校验正确性 - validateConfigForCreateOrUpdate(null, reqVO.getKey()); + public Long createConfig(ConfigSaveReqVO createReqVO) { + // 校验参数配置 key 的唯一性 + validateConfigKeyUnique(null, createReqVO.getKey()); + // 插入参数配置 - ConfigDO config = ConfigConvert.INSTANCE.convert(reqVO); + ConfigDO config = ConfigConvert.INSTANCE.convert(createReqVO); config.setType(ConfigTypeEnum.CUSTOM.getType()); configMapper.insert(config); return config.getId(); } @Override - public void updateConfig(ConfigUpdateReqVO reqVO) { - // 校验正确性 - validateConfigForCreateOrUpdate(reqVO.getId(), null); // 不允许更新 key + public void updateConfig(ConfigSaveReqVO updateReqVO) { + // 校验自己存在 + validateConfigExists(updateReqVO.getId()); + // 校验参数配置 key 的唯一性 + validateConfigKeyUnique(updateReqVO.getId(), updateReqVO.getKey()); + // 更新参数配置 - ConfigDO updateObj = ConfigConvert.INSTANCE.convert(reqVO); + ConfigDO updateObj = ConfigConvert.INSTANCE.convert(updateReqVO); configMapper.updateById(updateObj); } @@ -75,22 +75,8 @@ public class ConfigServiceImpl implements ConfigService { } @Override - public PageResult getConfigPage(ConfigPageReqVO reqVO) { - return configMapper.selectPage(reqVO); - } - - @Override - public List getConfigList(ConfigExportReqVO reqVO) { - return configMapper.selectList(reqVO); - } - - private void validateConfigForCreateOrUpdate(Long id, String key) { - // 校验自己存在 - validateConfigExists(id); - // 校验参数配置 key 的唯一性 - if (StrUtil.isNotEmpty(key)) { - validateConfigKeyUnique(id, key); - } + public PageResult getConfigPage(ConfigPageReqVO pageReqVO) { + return configMapper.selectPage(pageReqVO); } @VisibleForTesting diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java index 002d00944..2838f44d7 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigService.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.infra.service.db; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; import javax.validation.Valid; @@ -20,14 +19,14 @@ public interface DataSourceConfigService { * @param createReqVO 创建信息 * @return 编号 */ - Long createDataSourceConfig(@Valid DataSourceConfigCreateReqVO createReqVO); + Long createDataSourceConfig(@Valid DataSourceConfigSaveReqVO createReqVO); /** * 更新数据源配置 * * @param updateReqVO 更新信息 */ - void updateDataSourceConfig(@Valid DataSourceConfigUpdateReqVO updateReqVO); + void updateDataSourceConfig(@Valid DataSourceConfigSaveReqVO updateReqVO); /** * 删除数据源配置 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java index e4365c205..006fb738f 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/db/DataSourceConfigServiceImpl.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.infra.service.db; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigUpdateReqVO; -import cn.iocoder.yudao.module.infra.convert.db.DataSourceConfigConvert; +import cn.iocoder.yudao.module.infra.controller.admin.db.vo.DataSourceConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.db.DataSourceConfigDO; import cn.iocoder.yudao.module.infra.dal.mysql.db.DataSourceConfigMapper; import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; @@ -35,21 +34,21 @@ public class DataSourceConfigServiceImpl implements DataSourceConfigService { private DynamicDataSourceProperties dynamicDataSourceProperties; @Override - public Long createDataSourceConfig(DataSourceConfigCreateReqVO createReqVO) { - DataSourceConfigDO dataSourceConfig = DataSourceConfigConvert.INSTANCE.convert(createReqVO); - validateConnectionOK(dataSourceConfig); + public Long createDataSourceConfig(DataSourceConfigSaveReqVO createReqVO) { + DataSourceConfigDO config = BeanUtils.toBean(createReqVO, DataSourceConfigDO.class); + validateConnectionOK(config); // 插入 - dataSourceConfigMapper.insert(dataSourceConfig); + dataSourceConfigMapper.insert(config); // 返回 - return dataSourceConfig.getId(); + return config.getId(); } @Override - public void updateDataSourceConfig(DataSourceConfigUpdateReqVO updateReqVO) { + public void updateDataSourceConfig(DataSourceConfigSaveReqVO updateReqVO) { // 校验存在 validateDataSourceConfigExists(updateReqVO.getId()); - DataSourceConfigDO updateObj = DataSourceConfigConvert.INSTANCE.convert(updateReqVO); + DataSourceConfigDO updateObj = BeanUtils.toBean(updateReqVO, DataSourceConfigDO.class); validateConnectionOK(updateObj); // 更新 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactService.java new file mode 100644 index 000000000..57303f06b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.infra.service.demo.demo01; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; + +import javax.validation.Valid; + +/** + * 示例联系人 Service 接口 + * + * @author 芋道源码 + */ +public interface Demo01ContactService { + + /** + * 创建示例联系人 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDemo01Contact(@Valid Demo01ContactSaveReqVO createReqVO); + + /** + * 更新示例联系人 + * + * @param updateReqVO 更新信息 + */ + void updateDemo01Contact(@Valid Demo01ContactSaveReqVO updateReqVO); + + /** + * 删除示例联系人 + * + * @param id 编号 + */ + void deleteDemo01Contact(Long id); + + /** + * 获得示例联系人 + * + * @param id 编号 + * @return 示例联系人 + */ + Demo01ContactDO getDemo01Contact(Long id); + + /** + * 获得示例联系人分页 + * + * @param pageReqVO 分页查询 + * @return 示例联系人分页 + */ + PageResult getDemo01ContactPage(Demo01ContactPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java new file mode 100644 index 000000000..6b2648b83 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.service.demo.demo01; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo01.Demo01ContactMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.DEMO01_CONTACT_NOT_EXISTS; + +/** + * 示例联系人 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class Demo01ContactServiceImpl implements Demo01ContactService { + + @Resource + private Demo01ContactMapper demo01ContactMapper; + + @Override + public Long createDemo01Contact(Demo01ContactSaveReqVO createReqVO) { + // 插入 + Demo01ContactDO demo01Contact = BeanUtils.toBean(createReqVO, Demo01ContactDO.class); + demo01ContactMapper.insert(demo01Contact); + // 返回 + return demo01Contact.getId(); + } + + @Override + public void updateDemo01Contact(Demo01ContactSaveReqVO updateReqVO) { + // 校验存在 + validateDemo01ContactExists(updateReqVO.getId()); + // 更新 + Demo01ContactDO updateObj = BeanUtils.toBean(updateReqVO, Demo01ContactDO.class); + demo01ContactMapper.updateById(updateObj); + } + + @Override + public void deleteDemo01Contact(Long id) { + // 校验存在 + validateDemo01ContactExists(id); + // 删除 + demo01ContactMapper.deleteById(id); + } + + private void validateDemo01ContactExists(Long id) { + if (demo01ContactMapper.selectById(id) == null) { + throw exception(DEMO01_CONTACT_NOT_EXISTS); + } + } + + @Override + public Demo01ContactDO getDemo01Contact(Long id) { + return demo01ContactMapper.selectById(id); + } + + @Override + public PageResult getDemo01ContactPage(Demo01ContactPageReqVO pageReqVO) { + return demo01ContactMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryService.java new file mode 100644 index 000000000..47c4978a0 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.infra.service.demo.demo02; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 示例分类 Service 接口 + * + * @author 芋道源码 + */ +public interface Demo02CategoryService { + + /** + * 创建示例分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDemo02Category(@Valid Demo02CategorySaveReqVO createReqVO); + + /** + * 更新示例分类 + * + * @param updateReqVO 更新信息 + */ + void updateDemo02Category(@Valid Demo02CategorySaveReqVO updateReqVO); + + /** + * 删除示例分类 + * + * @param id 编号 + */ + void deleteDemo02Category(Long id); + + /** + * 获得示例分类 + * + * @param id 编号 + * @return 示例分类 + */ + Demo02CategoryDO getDemo02Category(Long id); + + /** + * 获得示例分类列表 + * + * @param listReqVO 查询条件 + * @return 示例分类列表 + */ + List getDemo02CategoryList(Demo02CategoryListReqVO listReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java new file mode 100644 index 000000000..7ab4ec56b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.infra.service.demo.demo02; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo02.Demo02CategoryMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 示例分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class Demo02CategoryServiceImpl implements Demo02CategoryService { + + @Resource + private Demo02CategoryMapper demo02CategoryMapper; + + @Override + public Long createDemo02Category(Demo02CategorySaveReqVO createReqVO) { + // 校验父级编号的有效性 + validateParentDemo02Category(null, createReqVO.getParentId()); + // 校验名字的唯一性 + validateDemo02CategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + Demo02CategoryDO demo02Category = BeanUtils.toBean(createReqVO, Demo02CategoryDO.class); + demo02CategoryMapper.insert(demo02Category); + // 返回 + return demo02Category.getId(); + } + + @Override + public void updateDemo02Category(Demo02CategorySaveReqVO updateReqVO) { + // 校验存在 + validateDemo02CategoryExists(updateReqVO.getId()); + // 校验父级编号的有效性 + validateParentDemo02Category(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验名字的唯一性 + validateDemo02CategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + Demo02CategoryDO updateObj = BeanUtils.toBean(updateReqVO, Demo02CategoryDO.class); + demo02CategoryMapper.updateById(updateObj); + } + + @Override + public void deleteDemo02Category(Long id) { + // 校验存在 + validateDemo02CategoryExists(id); + // 校验是否有子示例分类 + if (demo02CategoryMapper.selectCountByParentId(id) > 0) { + throw exception(DEMO02_CATEGORY_EXITS_CHILDREN); + } + // 删除 + demo02CategoryMapper.deleteById(id); + } + + private void validateDemo02CategoryExists(Long id) { + if (demo02CategoryMapper.selectById(id) == null) { + throw exception(DEMO02_CATEGORY_NOT_EXISTS); + } + } + + private void validateParentDemo02Category(Long id, Long parentId) { + if (parentId == null || Demo02CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父示例分类 + if (Objects.equals(id, parentId)) { + throw exception(DEMO02_CATEGORY_PARENT_ERROR); + } + // 2. 父示例分类不存在 + Demo02CategoryDO parentDemo02Category = demo02CategoryMapper.selectById(parentId); + if (parentDemo02Category == null) { + throw exception(DEMO02_CATEGORY_PARENT_NOT_EXITS); + } + // 3. 递归校验父示例分类,如果父示例分类是自己的子示例分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentDemo02Category.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(DEMO02_CATEGORY_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父示例分类 + if (parentId == null || Demo02CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentDemo02Category = demo02CategoryMapper.selectById(parentId); + if (parentDemo02Category == null) { + break; + } + } + } + + private void validateDemo02CategoryNameUnique(Long id, Long parentId, String name) { + Demo02CategoryDO demo02Category = demo02CategoryMapper.selectByParentIdAndName(parentId, name); + if (demo02Category == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的示例分类 + if (id == null) { + throw exception(DEMO02_CATEGORY_NAME_DUPLICATE); + } + if (!Objects.equals(demo02Category.getId(), id)) { + throw exception(DEMO02_CATEGORY_NAME_DUPLICATE); + } + } + + @Override + public Demo02CategoryDO getDemo02Category(Long id) { + return demo02CategoryMapper.selectById(id); + } + + @Override + public List getDemo02CategoryList(Demo02CategoryListReqVO listReqVO) { + return demo02CategoryMapper.selectList(listReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentService.java new file mode 100644 index 000000000..c9a4c592e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentService.java @@ -0,0 +1,158 @@ +package cn.iocoder.yudao.module.infra.service.demo.demo03; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; + +import javax.validation.Valid; +import java.util.List; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface Demo03StudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDemo03Student(@Valid Demo03StudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateDemo03Student(@Valid Demo03StudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteDemo03Student(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + Demo03StudentDO getDemo03Student(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getDemo03StudentPage(Demo03StudentPageReqVO pageReqVO); + + + // ==================== 子表(学生课程) ==================== + + /** + * 获得学生课程列表 + * + * @param studentId 学生编号 + * @return 学生课程列表 + */ + List getDemo03CourseListByStudentId(Long studentId); + + /** + * 获得学生课程分页 + * + * @param pageReqVO 分页查询 + * @param studentId 学生编号 + * @return 学生课程分页 + */ + PageResult getDemo03CoursePage(PageParam pageReqVO, Long studentId); + + /** + * 创建学生课程 + * + * @param demo03Course 创建信息 + * @return 编号 + */ + Long createDemo03Course(@Valid Demo03CourseDO demo03Course); + + /** + * 更新学生课程 + * + * @param demo03Course 更新信息 + */ + void updateDemo03Course(@Valid Demo03CourseDO demo03Course); + + /** + * 删除学生课程 + * + * @param id 编号 + */ + void deleteDemo03Course(Long id); + + /** + * 获得学生课程 + * + * @param id 编号 + * @return 学生课程 + */ + Demo03CourseDO getDemo03Course(Long id); + + // ==================== 子表(学生班级) ==================== + + /** + * 获得学生班级 + * + * @param studentId 学生编号 + * @return 学生班级 + */ + Demo03GradeDO getDemo03GradeByStudentId(Long studentId); + + /** + * 获得学生班级分页 + * + * @param pageReqVO 分页查询 + * @param studentId 学生编号 + * @return 学生班级分页 + */ + PageResult getDemo03GradePage(PageParam pageReqVO, Long studentId); + + /** + * 创建学生班级 + * + * @param demo03Grade 创建信息 + * @return 编号 + */ + Long createDemo03Grade(@Valid Demo03GradeDO demo03Grade); + + /** + * 更新学生班级 + * + * @param demo03Grade 更新信息 + */ + void updateDemo03Grade(@Valid Demo03GradeDO demo03Grade); + + /** + * 删除学生班级 + * + * @param id 编号 + */ + void deleteDemo03Grade(Long id); + + /** + * 获得学生班级 + * + * @param id 编号 + * @return 学生班级 + */ + Demo03GradeDO getDemo03Grade(Long id); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java new file mode 100644 index 000000000..7b69e4ac7 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java @@ -0,0 +1,217 @@ +package cn.iocoder.yudao.module.infra.service.demo.demo03; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03CourseMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03GradeMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class Demo03StudentServiceImpl implements Demo03StudentService { + + @Resource + private Demo03StudentMapper demo03StudentMapper; + @Resource + private Demo03CourseMapper demo03CourseMapper; + @Resource + private Demo03GradeMapper demo03GradeMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createDemo03Student(Demo03StudentSaveReqVO createReqVO) { + // 插入 + Demo03StudentDO demo03Student = BeanUtils.toBean(createReqVO, Demo03StudentDO.class); + demo03StudentMapper.insert(demo03Student); + + // 插入子表 + createDemo03CourseList(demo03Student.getId(), createReqVO.getDemo03Courses()); + createDemo03Grade(demo03Student.getId(), createReqVO.getDemo03Grade()); + // 返回 + return demo03Student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDemo03Student(Demo03StudentSaveReqVO updateReqVO) { + // 校验存在 + validateDemo03StudentExists(updateReqVO.getId()); + // 更新 + Demo03StudentDO updateObj = BeanUtils.toBean(updateReqVO, Demo03StudentDO.class); + demo03StudentMapper.updateById(updateObj); + + // 更新子表 + updateDemo03CourseList(updateReqVO.getId(), updateReqVO.getDemo03Courses()); + updateDemo03Grade(updateReqVO.getId(), updateReqVO.getDemo03Grade()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteDemo03Student(Long id) { + // 校验存在 + validateDemo03StudentExists(id); + // 删除 + demo03StudentMapper.deleteById(id); + + // 删除子表 + deleteDemo03CourseByStudentId(id); + deleteDemo03GradeByStudentId(id); + } + + private void validateDemo03StudentExists(Long id) { + if (demo03StudentMapper.selectById(id) == null) { + throw exception(DEMO03_STUDENT_NOT_EXISTS); + } + } + + @Override + public Demo03StudentDO getDemo03Student(Long id) { + return demo03StudentMapper.selectById(id); + } + + @Override + public PageResult getDemo03StudentPage(Demo03StudentPageReqVO pageReqVO) { + return demo03StudentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生课程) ==================== + + @Override + public List getDemo03CourseListByStudentId(Long studentId) { + return demo03CourseMapper.selectListByStudentId(studentId); + } + + private void createDemo03CourseList(Long studentId, List list) { + if (list != null) { + list.forEach(o -> o.setStudentId(studentId)); + } + demo03CourseMapper.insertBatch(list); + } + + private void updateDemo03CourseList(Long studentId, List list) { + deleteDemo03CourseByStudentId(studentId); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createDemo03CourseList(studentId, list); + } + + private void deleteDemo03CourseByStudentId(Long studentId) { + demo03CourseMapper.deleteByStudentId(studentId); + } + + @Override + public PageResult getDemo03CoursePage(PageParam pageReqVO, Long studentId) { + return demo03CourseMapper.selectPage(pageReqVO, studentId); + } + + @Override + public Long createDemo03Course(Demo03CourseDO demo03Course) { + demo03CourseMapper.insert(demo03Course); + return demo03Course.getId(); + } + + @Override + public void updateDemo03Course(Demo03CourseDO demo03Course) { + demo03CourseMapper.updateById(demo03Course); + } + + @Override + public void deleteDemo03Course(Long id) { + demo03CourseMapper.deleteById(id); + } + + @Override + public Demo03CourseDO getDemo03Course(Long id) { + return demo03CourseMapper.selectById(id); + } + + // ==================== 子表(学生班级) ==================== + + @Override + public Demo03GradeDO getDemo03GradeByStudentId(Long studentId) { + return demo03GradeMapper.selectByStudentId(studentId); + } + + private void createDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) { + if (demo03Grade == null) { + return; + } + demo03Grade.setStudentId(studentId); + demo03GradeMapper.insert(demo03Grade); + } + + private void updateDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) { + if (demo03Grade == null) { + return; + } + demo03Grade.setStudentId(studentId); + demo03Grade.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 + demo03GradeMapper.insertOrUpdate(demo03Grade); + } + + private void deleteDemo03GradeByStudentId(Long studentId) { + demo03GradeMapper.deleteByStudentId(studentId); + } + + @Override + public PageResult getDemo03GradePage(PageParam pageReqVO, Long studentId) { + return demo03GradeMapper.selectPage(pageReqVO, studentId); + } + + @Override + public Long createDemo03Grade(Demo03GradeDO demo03Grade) { + // 校验是否已经存在 + if (demo03GradeMapper.selectByStudentId(demo03Grade.getStudentId()) != null) { + throw exception(DEMO03_GRADE_EXISTS); + } + demo03GradeMapper.insert(demo03Grade); + return demo03Grade.getId(); + } + + @Override + public void updateDemo03Grade(Demo03GradeDO demo03Grade) { + // 校验存在 + validateDemo03GradeExists(demo03Grade.getId()); + // 更新 + demo03GradeMapper.updateById(demo03Grade); + } + + @Override + public void deleteDemo03Grade(Long id) { + // 校验存在 + validateDemo03GradeExists(id); + // 删除 + demo03GradeMapper.deleteById(id); + } + + @Override + public Demo03GradeDO getDemo03Grade(Long id) { + return demo03GradeMapper.selectById(id); + } + + private void validateDemo03GradeExists(Long id) { + if (demo03GradeMapper.selectById(id) == null) { + throw exception(DEMO03_GRADE_NOT_EXISTS); + } + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java index 1b279391a..e43088098 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigService.java @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.infra.service.file; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.file.core.client.FileClient; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; import javax.validation.Valid; @@ -22,14 +21,14 @@ public interface FileConfigService { * @param createReqVO 创建信息 * @return 编号 */ - Long createFileConfig(@Valid FileConfigCreateReqVO createReqVO); + Long createFileConfig(@Valid FileConfigSaveReqVO createReqVO); /** * 更新文件配置 * * @param updateReqVO 更新信息 */ - void updateFileConfig(@Valid FileConfigUpdateReqVO updateReqVO); + void updateFileConfig(@Valid FileConfigSaveReqVO updateReqVO); /** * 更新文件配置为 Master diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java index ac6c6b453..f401996cc 100755 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileConfigServiceImpl.java @@ -9,9 +9,8 @@ import cn.iocoder.yudao.framework.file.core.client.FileClient; import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; import cn.iocoder.yudao.framework.file.core.client.FileClientFactory; import cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigSaveReqVO; import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO; import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper; @@ -75,7 +74,7 @@ public class FileConfigServiceImpl implements FileConfigService { private Validator validator; @Override - public Long createFileConfig(FileConfigCreateReqVO createReqVO) { + public Long createFileConfig(FileConfigSaveReqVO createReqVO) { FileConfigDO fileConfig = FileConfigConvert.INSTANCE.convert(createReqVO) .setConfig(parseClientConfig(createReqVO.getStorage(), createReqVO.getConfig())) .setMaster(false); // 默认非 master @@ -84,7 +83,7 @@ public class FileConfigServiceImpl implements FileConfigService { } @Override - public void updateFileConfig(FileConfigUpdateReqVO updateReqVO) { + public void updateFileConfig(FileConfigSaveReqVO updateReqVO) { // 校验存在 FileConfigDO config = validateFileConfigExists(updateReqVO.getId()); // 更新 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java index 3f2a005e1..fd4e841af 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogService.java @@ -2,12 +2,9 @@ package cn.iocoder.yudao.module.infra.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; -import java.util.List; - /** * API 访问日志 Service 接口 * @@ -30,14 +27,6 @@ public interface ApiAccessLogService { */ PageResult getApiAccessLogPage(ApiAccessLogPageReqVO pageReqVO); - /** - * 获得 API 访问日志列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return API 访问日志分页 - */ - List getApiAccessLogList(ApiAccessLogExportReqVO exportReqVO); - /** * 清理 exceedDay 天前的访问日志 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java index 12655542a..2d9c05c31 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.infra.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog.ApiAccessLogPageReqVO; -import cn.iocoder.yudao.module.infra.convert.logger.ApiAccessLogConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiAccessLogDO; import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiAccessLogMapper; import lombok.extern.slf4j.Slf4j; @@ -13,7 +12,6 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.List; /** * API 访问日志 Service 实现类 @@ -30,7 +28,7 @@ public class ApiAccessLogServiceImpl implements ApiAccessLogService { @Override public void createApiAccessLog(ApiAccessLogCreateReqDTO createDTO) { - ApiAccessLogDO apiAccessLog = ApiAccessLogConvert.INSTANCE.convert(createDTO); + ApiAccessLogDO apiAccessLog = BeanUtils.toBean(createDTO, ApiAccessLogDO.class); apiAccessLogMapper.insert(apiAccessLog); } @@ -39,11 +37,6 @@ public class ApiAccessLogServiceImpl implements ApiAccessLogService { return apiAccessLogMapper.selectPage(pageReqVO); } - @Override - public List getApiAccessLogList(ApiAccessLogExportReqVO exportReqVO) { - return apiAccessLogMapper.selectList(exportReqVO); - } - @Override @SuppressWarnings("DuplicatedCode") public Integer cleanAccessLog(Integer exceedDay, Integer deleteLimit) { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java index 04c1efd39..82eb3c4c0 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogService.java @@ -2,12 +2,9 @@ package cn.iocoder.yudao.module.infra.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; -import java.util.List; - /** * API 错误日志 Service 接口 * @@ -30,14 +27,6 @@ public interface ApiErrorLogService { */ PageResult getApiErrorLogPage(ApiErrorLogPageReqVO pageReqVO); - /** - * 获得 API 错误日志列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return API 错误日志分页 - */ - List getApiErrorLogList(ApiErrorLogExportReqVO exportReqVO); - /** * 更新 API 错误日志已处理 * diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java index 14a0141ef..102635392 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.infra.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; -import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogExportReqVO; import cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog.ApiErrorLogPageReqVO; -import cn.iocoder.yudao.module.infra.convert.logger.ApiErrorLogConvert; import cn.iocoder.yudao.module.infra.dal.dataobject.logger.ApiErrorLogDO; import cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper; import cn.iocoder.yudao.module.infra.enums.logger.ApiErrorLogProcessStatusEnum; @@ -14,7 +13,6 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.API_ERROR_LOG_NOT_FOUND; @@ -35,7 +33,7 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService { @Override public void createApiErrorLog(ApiErrorLogCreateReqDTO createDTO) { - ApiErrorLogDO apiErrorLog = ApiErrorLogConvert.INSTANCE.convert(createDTO) + ApiErrorLogDO apiErrorLog = BeanUtils.toBean(createDTO, ApiErrorLogDO.class) .setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus()); apiErrorLogMapper.insert(apiErrorLog); } @@ -45,11 +43,6 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService { return apiErrorLogMapper.selectPage(pageReqVO); } - @Override - public List getApiErrorLogList(ApiErrorLogExportReqVO exportReqVO) { - return apiErrorLogMapper.selectList(exportReqVO); - } - @Override public void updateApiErrorLogProcess(Long id, Integer processStatus, Long processUserId) { ApiErrorLogDO errorLog = apiErrorLogMapper.selectById(id); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java deleted file mode 100755 index 8b33f2824..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoService.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.module.infra.service.test; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; - -import javax.validation.Valid; -import java.util.Collection; -import java.util.List; - -/** - * 字典类型 Service 接口 - * - * @author 芋道源码 - */ -public interface TestDemoService { - - /** - * 创建字典类型 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createTestDemo(@Valid TestDemoCreateReqVO createReqVO); - - /** - * 更新字典类型 - * - * @param updateReqVO 更新信息 - */ - void updateTestDemo(@Valid TestDemoUpdateReqVO updateReqVO); - - /** - * 删除字典类型 - * - * @param id 编号 - */ - void deleteTestDemo(Long id); - - /** - * 获得字典类型 - * - * @param id 编号 - * @return 字典类型 - */ - TestDemoDO getTestDemo(Long id); - - /** - * 获得字典类型列表 - * - * @param ids 编号 - * @return 字典类型列表 - */ - List getTestDemoList(Collection ids); - - /** - * 获得字典类型分页 - * - * @param pageReqVO 分页查询 - * @return 字典类型分页 - */ - PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO); - - /** - * 获得字典类型列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 字典类型列表 - */ - List getTestDemoList(TestDemoExportReqVO exportReqVO); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java deleted file mode 100755 index f476b5a72..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/test/TestDemoServiceImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.iocoder.yudao.module.infra.service.test; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoCreateReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoExportReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoPageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.test.vo.TestDemoUpdateReqVO; -import cn.iocoder.yudao.module.infra.convert.test.TestDemoConvert; -import cn.iocoder.yudao.module.infra.dal.dataobject.test.TestDemoDO; -import cn.iocoder.yudao.module.infra.dal.mysql.test.TestDemoMapper; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.TEST_DEMO_NOT_EXISTS; - -/** - * 字典类型 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class TestDemoServiceImpl implements TestDemoService { - - @Resource - private TestDemoMapper testDemoMapper; - - @Override - public Long createTestDemo(TestDemoCreateReqVO createReqVO) { - // 插入 - TestDemoDO testDemo = TestDemoConvert.INSTANCE.convert(createReqVO); - testDemoMapper.insert(testDemo); - // 返回 - return testDemo.getId(); - } - - @Override - @CacheEvict(value = "test", key = "#updateReqVO.id") - public void updateTestDemo(TestDemoUpdateReqVO updateReqVO) { - // 校验存在 - validateTestDemoExists(updateReqVO.getId()); - // 更新 - TestDemoDO updateObj = TestDemoConvert.INSTANCE.convert(updateReqVO); - testDemoMapper.updateById(updateObj); - } - - @Override - @CacheEvict(value = "test", key = "#id") - public void deleteTestDemo(Long id) { - // 校验存在 - validateTestDemoExists(id); - // 删除 - testDemoMapper.deleteById(id); - } - - private void validateTestDemoExists(Long id) { - if (testDemoMapper.selectById(id) == null) { - throw exception(TEST_DEMO_NOT_EXISTS); - } - } - - @Override - @Cacheable(cacheNames = "test", key = "#id") - public TestDemoDO getTestDemo(Long id) { - return testDemoMapper.selectById(id); - } - - @Override - public List getTestDemoList(Collection ids) { - return testDemoMapper.selectBatchIds(ids); - } - - @Override - public PageResult getTestDemoPage(TestDemoPageReqVO pageReqVO) { -// testDemoMapper.selectList2(); - return testDemoMapper.selectPage(pageReqVO); - } - - @Override - public List getTestDemoList(TestDemoExportReqVO exportReqVO) { - return testDemoMapper.selectList(exportReqVO); - } - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java new file mode 100644 index 000000000..9ccf6070e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.infra.websocket; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; +import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; +import cn.iocoder.yudao.module.infra.websocket.message.DemoReceiveMessage; +import cn.iocoder.yudao.module.infra.websocket.message.DemoSendMessage; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.WebSocketSession; + +import javax.annotation.Resource; + +/** + * WebSocket 示例:单发消息 + * + * @author 芋道源码 + */ +@Component +public class DemoWebSocketMessageListener implements WebSocketMessageListener { + + @Resource + private WebSocketMessageSender webSocketMessageSender; + + @Override + public void onMessage(WebSocketSession session, DemoSendMessage message) { + Long fromUserId = WebSocketFrameworkUtils.getLoginUserId(session); + // 情况一:单发 + if (message.getToUserId() != null) { + DemoReceiveMessage toMessage = new DemoReceiveMessage().setFromUserId(fromUserId) + .setText(message.getText()).setSingle(true); + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), message.getToUserId(), // 给指定用户 + "demo-message-receive", toMessage); + return; + } + // 情况二:群发 + DemoReceiveMessage toMessage = new DemoReceiveMessage().setFromUserId(fromUserId) + .setText(message.getText()).setSingle(false); + webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), // 给所有用户 + "demo-message-receive", toMessage); + } + + @Override + public String getType() { + return "demo-message-send"; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/DemoReceiveMessage.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/DemoReceiveMessage.java new file mode 100644 index 000000000..03a246cf9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/DemoReceiveMessage.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.infra.websocket.message; + +import lombok.Data; + +/** + * 示例:server -> client 同步消息 + * + * @author 芋道源码 + */ +@Data +public class DemoReceiveMessage { + + /** + * 接收人的编号 + */ + private Long fromUserId; + /** + * 内容 + */ + private String text; + + /** + * 是否单聊 + */ + private Boolean single; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/DemoSendMessage.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/DemoSendMessage.java new file mode 100644 index 000000000..f0c14f5d3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/websocket/message/DemoSendMessage.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.infra.websocket.message; + +import lombok.Data; + +/** + * 示例:client -> server 发送消息 + * + * @author 芋道源码 + */ +@Data +public class DemoSendMessage { + + /** + * 发送给谁 + * + * 如果为空,说明发送给所有人 + */ + private Long toUserId; + /** + * 内容 + */ + private String text; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml index 357acc316..3e6c2130e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-dev.yaml @@ -60,6 +60,21 @@ spring: --- #################### MQ 消息队列相关配置 #################### +# rocketmq 配置项,对应 RocketMQProperties 配置类 +rocketmq: + name-server: 127.0.0.1:9876 # RocketMQ Namesrv + +spring: + # RabbitMQ 配置项,对应 RabbitProperties 配置类 + rabbitmq: + host: 127.0.0.1 # RabbitMQ 服务的地址 + port: 5672 # RabbitMQ 服务的端口 + username: guest # RabbitMQ 服务的账号 + password: guest # RabbitMQ 服务的密码 + # Kafka 配置项,对应 KafkaProperties 配置类 + kafka: + bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 + --- #################### 定时任务相关配置 #################### xxl: job: diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml index 896a7b3d2..af3b2cfa5 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application-local.yaml @@ -75,6 +75,21 @@ spring: --- #################### MQ 消息队列相关配置 #################### +# rocketmq 配置项,对应 RocketMQProperties 配置类 +rocketmq: + name-server: 127.0.0.1:9876 # RocketMQ Namesrv + +spring: + # RabbitMQ 配置项,对应 RabbitProperties 配置类 + rabbitmq: + host: 127.0.0.1 # RabbitMQ 服务的地址 + port: 5672 # RabbitMQ 服务的端口 + username: guest # RabbitMQ 服务的账号 + password: guest # RabbitMQ 服务的密码 + # Kafka 配置项,对应 KafkaProperties 配置类 + kafka: + bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 + --- #################### 定时任务相关配置 #################### xxl: job: diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml index b6aa6fe2e..dea79c8be 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 @@ -72,7 +72,31 @@ spring: --- #################### RPC 远程调用相关配置 #################### ---- #################### MQ 消息队列相关配置 #################### +--- #################### 消息队列相关 #################### + +# rocketmq 配置项,对应 RocketMQProperties 配置类 +rocketmq: + # Producer 配置项 + producer: + group: ${spring.application.name}_PRODUCER # 生产者分组 + +spring: + # Kafka 配置项,对应 KafkaProperties 配置类 + kafka: + # Kafka Producer 配置项 + producer: + acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。 + retries: 3 # 发送失败时,重试发送的次数 + value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化 + # Kafka Consumer 配置项 + consumer: + auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解 + value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer + properties: + spring.json.trusted.packages: '*' + # Kafka Consumer Listener 监听器配置 + listener: + missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错 --- #################### 定时任务相关配置 #################### @@ -92,6 +116,19 @@ yudao: web: admin-ui: url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址 + websocket: + enable: true # websocket的开关 + path: /infra/ws # 路径 + sender-type: local # 消息发送的类型,可选值为 local、redis、rocketmq、kafka、rabbitmq + sender-rocketmq: + topic: ${spring.application.name}-websocket # 消息发送的 RocketMQ Topic + consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 RocketMQ Consumer Group + sender-rabbitmq: + exchange: ${spring.application.name}-websocket-exchange # 消息发送的 RabbitMQ Exchange + queue: ${spring.application.name}-websocket-queue # 消息发送的 RabbitMQ Queue + sender-kafka: + topic: ${spring.application.name}-websocket # 消息发送的 Kafka Topic + consumer-group: ${spring.application.name}-websocket-consumer # 消息发送的 Kafka Consumer Group swagger: title: 管理后台 description: 提供管理员管理的所有功能 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm index a8c1f62c5..4c047c948 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm @@ -15,8 +15,10 @@ import javax.servlet.http.*; import java.util.*; import java.io.IOException; +import ${PageParamClassName}; import ${PageResultClassName}; import ${CommonResultClassName}; +import ${BeanUtils}; import static ${CommonResultClassName}.success; import ${ExcelUtilsClassName}; @@ -26,7 +28,10 @@ import static ${OperateTypeEnumClassName}.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; -import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; +#end import ${basePackage}.module.${table.moduleName}.service.${table.businessName}.${table.className}Service; @Tag(name = "${sceneEnum.name} - ${table.classComment}") @@ -41,17 +46,19 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { @PostMapping("/create") @Operation(summary = "创建${table.classComment}") -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')")#end - - public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')") +#end + public CommonResult<${primaryColumn.javaType}> create${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) { return success(${classNameVar}Service.create${simpleClassName}(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新${table.classComment}") -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')")#end - - public CommonResult update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')") +#end + public CommonResult update${simpleClassName}(@Valid @RequestBody ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) { ${classNameVar}Service.update${simpleClassName}(updateReqVO); return success(true); } @@ -59,8 +66,9 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { @DeleteMapping("/delete") @Operation(summary = "删除${table.classComment}") @Parameter(name = "id", description = "编号", required = true) -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')")#end - +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')") +#end public CommonResult delete${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { ${classNameVar}Service.delete${simpleClassName}(id); return success(true); @@ -69,43 +77,157 @@ public class ${sceneEnum.prefixClass}${table.className}Controller { @GetMapping("/get") @Operation(summary = "获得${table.classComment}") @Parameter(name = "id", description = "编号", required = true, example = "1024") -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end - +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end public CommonResult<${sceneEnum.prefixClass}${table.className}RespVO> get${simpleClassName}(@RequestParam("id") ${primaryColumn.javaType} id) { ${table.className}DO ${classNameVar} = ${classNameVar}Service.get${simpleClassName}(id); - return success(${table.className}Convert.INSTANCE.convert(${classNameVar})); - } - - @GetMapping("/list") - @Operation(summary = "获得${table.classComment}列表") - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end - - public CommonResult> get${simpleClassName}List(@RequestParam("ids") Collection<${primaryColumn.javaType}> ids) { - List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(ids); - return success(${table.className}Convert.INSTANCE.convertList(list)); + return success(BeanUtils.toBean(${classNameVar}, ${sceneEnum.prefixClass}${table.className}RespVO.class)); } +#if ( $table.templateType != 2 ) @GetMapping("/page") @Operation(summary = "获得${table.classComment}分页") -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')")#end - - public CommonResult> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageVO) { - PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageVO); - return success(${table.className}Convert.INSTANCE.convertPage(pageResult)); +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end + public CommonResult> get${simpleClassName}Page(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) { + PageResult<${table.className}DO> pageResult = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO); + return success(BeanUtils.toBean(pageResult, ${sceneEnum.prefixClass}${table.className}RespVO.class)); } +## 特殊:树表专属逻辑(树不需要分页接口) +#else + @GetMapping("/list") + @Operation(summary = "获得${table.classComment}列表") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end + public CommonResult> get${simpleClassName}List(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) { + List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO); + return success(BeanUtils.toBean(list, ${sceneEnum.prefixClass}${table.className}RespVO.class)); + } + +#end @GetMapping("/export-excel") @Operation(summary = "导出${table.classComment} Excel") -#if ($sceneEnum.scene == 1) @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')")#end - +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:export')") +#end @OperateLog(type = EXPORT) - public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO, +#if ( $table.templateType != 2 ) + public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO, HttpServletResponse response) throws IOException { - List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(exportReqVO); + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}Page(pageReqVO).getList(); // 导出 Excel - List<${sceneEnum.prefixClass}${table.className}ExcelVO> datas = ${table.className}Convert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${sceneEnum.prefixClass}${table.className}ExcelVO.class, datas); + ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}RespVO.class, + BeanUtils.toBean(list, ${table.className}RespVO.class)); + } +## 特殊:树表专属逻辑(树不需要分页接口) +#else + public void export${simpleClassName}Excel(@Valid ${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "${table.classComment}.xls", "数据", ${table.className}RespVO.class, + BeanUtils.toBean(list, ${table.className}RespVO.class)); + } +#end + +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index)) +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) + // ==================== 子表($subTable.classComment) ==================== + +## 情况一:MASTER_ERP 时,需要分查询页子表 +#if ( $table.templateType == 11 ) + @GetMapping("/${subSimpleClassName_strikeCase}/page") + @Operation(summary = "获得${subTable.classComment}分页") + @Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end + public CommonResult> get${subSimpleClassName}Page(PageParam pageReqVO, + @RequestParam("${subJoinColumn.javaField}") ${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return success(${classNameVar}Service.get${subSimpleClassName}Page(pageReqVO, ${subJoinColumn.javaField})); } -} +## 情况二:非 MASTER_ERP 时,需要列表查询子表 +#else + #if ( $subTable.subJoinMany ) + @GetMapping("/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}") + @Operation(summary = "获得${subTable.classComment}列表") + @Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end + public CommonResult> get${subSimpleClassName}ListBy${SubJoinColumnName}(@RequestParam("${subJoinColumn.javaField}") ${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return success(${classNameVar}Service.get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField})); + } + + #else + @GetMapping("/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}") + @Operation(summary = "获得${subTable.classComment}") + @Parameter(name = "${subJoinColumn.javaField}", description = "${subJoinColumn.columnComment}") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end + public CommonResult<${subTable.className}DO> get${subSimpleClassName}By${SubJoinColumnName}(@RequestParam("${subJoinColumn.javaField}") ${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return success(${classNameVar}Service.get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField})); + } + + #end +#end +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 +#if ( $table.templateType == 11 ) + @PostMapping("/${subSimpleClassName_strikeCase}/create") + @Operation(summary = "创建${subTable.classComment}") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:create')") +#end + public CommonResult<${subPrimaryColumn.javaType}> create${subSimpleClassName}(@Valid @RequestBody ${subTable.className}DO ${subClassNameVar}) { + return success(${classNameVar}Service.create${subSimpleClassName}(${subClassNameVar})); + } + + @PutMapping("/${subSimpleClassName_strikeCase}/update") + @Operation(summary = "更新${subTable.classComment}") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:update')") +#end + public CommonResult update${subSimpleClassName}(@Valid @RequestBody ${subTable.className}DO ${subClassNameVar}) { + ${classNameVar}Service.update${subSimpleClassName}(${subClassNameVar}); + return success(true); + } + + @DeleteMapping("/${subSimpleClassName_strikeCase}/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除${subTable.classComment}") +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:delete')") +#end + public CommonResult delete${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) { + ${classNameVar}Service.delete${subSimpleClassName}(id); + return success(true); + } + + @GetMapping("/${subSimpleClassName_strikeCase}/get") + @Operation(summary = "获得${subTable.classComment}") + @Parameter(name = "id", description = "编号", required = true) +#if ($sceneEnum.scene == 1) + @PreAuthorize("@ss.hasPermission('${permissionPrefix}:query')") +#end + public CommonResult<${subTable.className}DO> get${subSimpleClassName}(@RequestParam("id") ${subPrimaryColumn.javaType} id) { + return success(${classNameVar}Service.get${subSimpleClassName}(id)); + } + +#end +#end +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm deleted file mode 100644 index 98b09f272..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/_column.vm +++ /dev/null @@ -1,13 +0,0 @@ -## 提供给 baseVO、createVO、updateVO 生成字段 - @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end) -#if (!${column.nullable})## 判断 @NotEmpty 和 @NotNull 注解 -#if (${field.fieldType} == 'String') - @NotEmpty(message = "${column.columnComment}不能为空") -#else - @NotNull(message = "${column.columnComment}不能为空") -#end -#end -#if (${column.javaType} == "LocalDateTime")## 时间类型 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) -#end - private ${column.javaType} ${column.javaField}; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm deleted file mode 100644 index cc612e337..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/baseVO.vm +++ /dev/null @@ -1,39 +0,0 @@ -package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -#foreach ($column in $columns) -#if (${column.javaType} == "BigDecimal") -import java.math.BigDecimal; -#end -#if (${column.javaType} == "LocalDateTime") -import java.time.LocalDateTime; -#end -#end -import javax.validation.constraints.*; -## 处理 Date 字段的引入 -#foreach ($column in $columns) -#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult} - && ${column.javaType} == "LocalDateTime")## 时间类型 -import org.springframework.format.annotation.DateTimeFormat; - -import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -#break -#end -#end - -/** - * ${table.classComment} Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class ${sceneEnum.prefixClass}${table.className}BaseVO { - -#foreach ($column in $columns) -#if (${column.createOperation} && ${column.updateOperation} && ${column.listOperationResult})##通用操作 - #parse("codegen/java/controller/vo/_column.vm") - -#end -#end -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm deleted file mode 100644 index d4f6f8ea9..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/createReqVO.vm +++ /dev/null @@ -1,30 +0,0 @@ -package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; - -import lombok.*; -import java.util.*; -import io.swagger.v3.oas.annotations.media.Schema; -import javax.validation.constraints.*; -## 处理 Date 字段的引入 -#foreach ($column in $columns) -#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}) - && ${column.javaType} == "LocalDateTime")## 时间类型 -import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; -import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -#break -#end -#end - -@Schema(description = "${sceneEnum.name} - ${table.classComment}创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ${sceneEnum.prefixClass}${table.className}CreateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO { - -#foreach ($column in $columns) -#if (${column.createOperation} && (!${column.updateOperation} || !${column.listOperationResult}))##不是通用字段 - #parse("codegen/java/controller/vo/_column.vm") - -#end -#end -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm deleted file mode 100644 index 15c6660c8..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/excelVO.vm +++ /dev/null @@ -1,45 +0,0 @@ -package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -#foreach ($column in $columns) -#if (${column.javaType} == "BigDecimal") -import java.math.BigDecimal; -#end -#if (${column.javaType} == "LocalDateTime") -import java.time.LocalDateTime; -#end -#end - -import com.alibaba.excel.annotation.ExcelProperty; -#foreach ($column in $columns) -#if ("$!column.dictType" != "")## 有设置数据字典 -import ${DictFormatClassName}; -import ${DictConvertClassName}; - -#break -#end -#end - -/** - * ${table.classComment} Excel VO - * - * @author ${table.author} - */ -@Data -public class ${sceneEnum.prefixClass}${table.className}ExcelVO { - -#foreach ($column in $columns) - #if (${column.listOperationResult})##返回字段 - #if ("$!column.dictType" != "")##处理枚举值 - @ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class) - @DictFormat("${column.dictType}") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中 - #else - @ExcelProperty("${column.columnComment}") - #end - private ${column.javaType} ${column.javaField}; - - #end -#end -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/listReqVO.vm similarity index 84% rename from yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm rename to yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/listReqVO.vm index d3ef4aacd..46b6a259d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/exportReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/listReqVO.vm @@ -4,9 +4,15 @@ import lombok.*; import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; import ${PageParamClassName}; -## 处理 Date 字段的引入 #foreach ($column in $columns) -#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 +#if (${column.javaType} == "BigDecimal") +import java.math.BigDecimal; +#break +#end +#end +## 处理 LocalDateTime 字段的引入 +#foreach ($column in $columns) +#if (${column.listOperation} && ${column.javaType} == "LocalDateTime") import java.time.LocalDateTime; import org.springframework.format.annotation.DateTimeFormat; @@ -20,9 +26,9 @@ import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; private ${column.javaType}#if ("$!prefix" != "") ${prefix}${JavaField}#else ${column.javaField}#end; #end -@Schema(description = "${sceneEnum.name} - ${table.classComment} Excel 导出 Request VO,参数和 ${table.className}PageReqVO 是一致的") +@Schema(description = "${sceneEnum.name} - ${table.classComment}列表 Request VO") @Data -public class ${sceneEnum.prefixClass}${table.className}ExportReqVO { +public class ${sceneEnum.prefixClass}${table.className}ListReqVO { #foreach ($column in $columns) #if (${column.listOperation})##查询操作 @@ -36,4 +42,4 @@ public class ${sceneEnum.prefixClass}${table.className}ExportReqVO { #end #end -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm index 6f9868da3..003bac902 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/pageReqVO.vm @@ -4,9 +4,15 @@ import lombok.*; import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; import ${PageParamClassName}; -## 处理 Date 字段的引入 #foreach ($column in $columns) -#if (${column.listOperation} && ${column.javaType} == "LocalDateTime")## 时间类型 +#if (${column.javaType} == "BigDecimal") +import java.math.BigDecimal; +#break +#end +#end +## 处理 LocalDateTime 字段的引入 +#foreach ($column in $columns) +#if (${column.listOperationCondition} && ${column.javaType} == "LocalDateTime") import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; @@ -38,4 +44,4 @@ public class ${sceneEnum.prefixClass}${table.className}PageReqVO extends PagePar #end #end -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm index 517d8bcd5..54c16671d 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/respVO.vm @@ -2,24 +2,53 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; +import java.util.*; +## 处理 BigDecimal 字段的引入 +import java.util.*; #foreach ($column in $columns) -#if (${column.javaType} == "LocalDateTime") +#if (${column.javaType} == "BigDecimal") +import java.math.BigDecimal; +#break +#end +#end +## 处理 LocalDateTime 字段的引入 +#foreach ($column in $columns) +#if (${column.listOperationResult} && ${column.javaType} == "LocalDateTime") +import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; #break #end #end +## 处理 Excel 导出 +import com.alibaba.excel.annotation.*; +#foreach ($column in $columns) +#if ("$!column.dictType" != "")## 有设置数据字典 +import ${DictFormatClassName}; +import ${DictConvertClassName}; +#break +#end +#end @Schema(description = "${sceneEnum.name} - ${table.classComment} Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ${sceneEnum.prefixClass}${table.className}RespVO extends ${sceneEnum.prefixClass}${table.className}BaseVO { +@ExcelIgnoreUnannotated +public class ${sceneEnum.prefixClass}${table.className}RespVO { +## 逐个处理字段 #foreach ($column in $columns) -#if (${column.listOperationResult} && (!${column.createOperation} || !${column.updateOperation}))##不是通用字段 +#if (${column.listOperationResult}) +## 1. 处理 Swagger 注解 @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end) +## 2. 处理 Excel 导出 +#if ("$!column.dictType" != "")##处理枚举值 + @ExcelProperty(value = "${column.columnComment}", converter = DictConvert.class) + @DictFormat("${column.dictType}") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 +#else + @ExcelProperty("${column.columnComment}") +#end +## 3. 处理字段定义 private ${column.javaType} ${column.javaField}; #end #end -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm new file mode 100644 index 000000000..89829cc99 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm @@ -0,0 +1,65 @@ +package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +## 处理 BigDecimal 字段的引入 +import java.util.*; +#foreach ($column in $columns) +#if (${column.javaType} == "BigDecimal") +import java.math.BigDecimal; +#break +#end +#end +## 处理 LocalDateTime 字段的引入 +#foreach ($column in $columns) +#if ((${column.createOperation} || ${column.updateOperation}) && ${column.javaType} == "LocalDateTime") +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +#break +#end +#end +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; +#end + +@Schema(description = "${sceneEnum.name} - ${table.classComment}新增/修改 Request VO") +@Data +public class ${sceneEnum.prefixClass}${table.className}SaveReqVO { + +## 逐个处理字段 +#foreach ($column in $columns) +#if (${column.createOperation} || ${column.updateOperation}) +## 1. 处理 Swagger 注解 + @Schema(description = "${column.columnComment}"#if (!${column.nullable}), requiredMode = Schema.RequiredMode.REQUIRED#end#if ("$!column.example" != ""), example = "${column.example}"#end) +## 2. 处理 Validator 参数校验 +#if (!${column.nullable} && !${column.primaryKey}) +#if (${column.javaType} == 'String') + @NotEmpty(message = "${column.columnComment}不能为空") +#else + @NotNull(message = "${column.columnComment}不能为空") +#end +#end +## 3. 处理字段定义 + private ${column.javaType} ${column.javaField}; + +#end +#end +## 特殊:主子表专属逻辑(非 ERP 模式) +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) + #if ( $subTable.subJoinMany) + @Schema(description = "${subTable.classComment}列表") + private List<${subTable.className}DO> ${subClassNameVars.get($index)}s; + + #else + @Schema(description = "${subTable.classComment}") + private ${subTable.className}DO ${subClassNameVars.get($index)}; + + #end +#end +#end +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm deleted file mode 100644 index 48d74321d..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/updateReqVO.vm +++ /dev/null @@ -1,30 +0,0 @@ -package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import javax.validation.constraints.*; -## 处理 Date 字段的引入 -#foreach ($column in $columns) -#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}) - && ${column.javaType} == "LocalDateTime")## 时间类型 -import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; -import static ${DateUtilsClassName}.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -#break -#end -#end - -@Schema(description = "${sceneEnum.name} - ${table.classComment}更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ${sceneEnum.prefixClass}${table.className}UpdateReqVO extends ${sceneEnum.prefixClass}${table.className}BaseVO { - -#foreach ($column in $columns) -#if (${column.updateOperation} && (!${column.createOperation} || !${column.listOperationResult}))##不是通用字段 - #parse("codegen/java/controller/vo/_column.vm") - -#end -#end -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/convert/convert.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/convert/convert.vm deleted file mode 100644 index 6176e0f54..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/convert/convert.vm +++ /dev/null @@ -1,34 +0,0 @@ -package ${basePackage}.module.${table.moduleName}.convert.${table.businessName}; - -import java.util.*; - -import ${PageResultClassName}; - -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; -import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; -import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; - -/** - * ${table.classComment} Convert - * - * @author ${table.author} - */ -@Mapper -public interface ${table.className}Convert { - - ${table.className}Convert INSTANCE = Mappers.getMapper(${table.className}Convert.class); - - ${table.className}DO convert(${sceneEnum.prefixClass}${table.className}CreateReqVO bean); - - ${table.className}DO convert(${sceneEnum.prefixClass}${table.className}UpdateReqVO bean); - - ${sceneEnum.prefixClass}${table.className}RespVO convert(${table.className}DO bean); - - List<${sceneEnum.prefixClass}${table.className}RespVO> convertList(List<${table.className}DO> list); - - PageResult<${sceneEnum.prefixClass}${table.className}RespVO> convertPage(PageResult<${table.className}DO> page); - - List<${sceneEnum.prefixClass}${table.className}ExcelVO> convertList02(List<${table.className}DO> list); - -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm index d551d4b30..b019d6e12 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do.vm @@ -28,6 +28,11 @@ import ${BaseDOClassName}; @AllArgsConstructor public class ${table.className}DO extends BaseDO { +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) + public static final Long ${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT = 0L; + +#end #foreach ($column in $columns) #if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段 /** @@ -44,4 +49,4 @@ public class ${table.className}DO extends BaseDO { #end #end -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do_sub.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do_sub.vm new file mode 100644 index 000000000..16be55e8a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/do_sub.vm @@ -0,0 +1,49 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +package ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}; + +import lombok.*; +import java.util.*; +#foreach ($column in $subColumns) +#if (${column.javaType} == "BigDecimal") +import java.math.BigDecimal; +#end +#if (${column.javaType} == "LocalDateTime") +import java.time.LocalDateTime; +#end +#end +import com.baomidou.mybatisplus.annotation.*; +import ${BaseDOClassName}; + +/** + * ${subTable.classComment} DO + * + * @author ${subTable.author} + */ +@TableName("${subTable.tableName.toLowerCase()}") +@KeySequence("${subTable.tableName.toLowerCase()}_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ${subTable.className}DO extends BaseDO { + +#foreach ($column in $subColumns) +#if (!${baseDOFields.contains(${column.javaField})})##排除 BaseDO 的字段 + /** + * ${column.columnComment} + #if ("$!column.dictType" != "")##处理枚举值 + * + * 枚举 {@link TODO ${column.dictType} 对应的类} + #end + */ + #if (${column.primaryKey})##处理主键 + @TableId#if (${column.javaType} == 'String')(type = IdType.INPUT)#end + #end + private ${column.javaType} ${column.javaField}; +#end +#end + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.vm index 615ae337b..b98b471fd 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.vm @@ -49,18 +49,34 @@ import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePack @Mapper public interface ${table.className}Mapper extends BaseMapperX<${table.className}DO> { +## 特殊:树表专属逻辑(树不需要分页接口) +#if ( $table.templateType != 2 ) default PageResult<${table.className}DO> selectPage(${sceneEnum.prefixClass}${table.className}PageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX<${table.className}DO>() #listCondition() .orderByDesc(${table.className}DO::getId));## 大多数情况下,id 倒序 } - - default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ExportReqVO reqVO) { +#else + default List<${table.className}DO> selectList(${sceneEnum.prefixClass}${table.className}ListReqVO reqVO) { return selectList(new LambdaQueryWrapperX<${table.className}DO>() #listCondition() .orderByDesc(${table.className}DO::getId));## 大多数情况下,id 倒序 } +#end -} +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 + default ${table.className}DO selectBy${TreeParentJavaField}And${TreeNameJavaField}(Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) { + return selectOne(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField}, ${table.className}DO::get${TreeNameJavaField}, ${treeNameColumn.javaField}); + } + + default Long selectCountBy${TreeParentJavaField}(${treeParentColumn.javaType} ${treeParentColumn.javaField}) { + return selectCount(${table.className}DO::get${TreeParentJavaField}, ${treeParentColumn.javaField}); + } + +#end +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm index d930db916..290378d36 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper.xml.vm @@ -9,4 +9,4 @@ 文档可见:https://www.iocoder.cn/MyBatis/x-plugins/ --> - + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper_sub.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper_sub.vm new file mode 100644 index 000000000..e5589e99d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/dal/mapper_sub.vm @@ -0,0 +1,51 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subJoinColumnsList.get($subIndex))##当前字段数组 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 +package ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName}; + +import java.util.*; + +import ${PageResultClassName}; +import ${PageParamClassName}; +import ${QueryWrapperClassName}; +import ${BaseMapperClassName}; +import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ${subTable.classComment} Mapper + * + * @author ${subTable.author} + */ +@Mapper +public interface ${subTable.className}Mapper extends BaseMapperX<${subTable.className}DO> { + +## 情况一:MASTER_ERP 时,需要分查询页子表 +#if ( $table.templateType == 11 ) + default PageResult<${subTable.className}DO> selectPage(PageParam reqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return selectPage(reqVO, new LambdaQueryWrapperX<${subTable.className}DO>() + .eq(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField}) + .orderByDesc(${subTable.className}DO::getId));## 大多数情况下,id 倒序 + + } + +## 情况二:非 MASTER_ERP 时,需要列表查询子表 +#else + #if ( $subTable.subJoinMany) + default List<${subTable.className}DO> selectListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return selectList(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField}); + } + + #else + default ${subTable.className}DO selectBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return selectOne(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField}); + } + + #end + #end + default int deleteBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return delete(${subTable.className}DO::get${SubJoinColumnName}, ${subJoinColumn.javaField}); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm index a9a6daf25..b7e21e631 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/enums/errorcode.vm @@ -1,3 +1,22 @@ // TODO 待办:请将下面的错误码复制到 yudao-module-${table.moduleName}-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! // ========== ${table.classComment} TODO 补充编号 ========== ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${table.classComment}不存在"); +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子${table.classComment},无法删除"); +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级${table.classComment}不存在"); +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父${table.classComment}"); +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该${treeNameColumn.columnComment}的${table.classComment}"); +ErrorCode ${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD = new ErrorCode(TODO 补充编号, "不能设置自己的子${table.className}为父${table.className}"); +#end +## 特殊:主子表专属逻辑 +#if ( $table.templateType == 11 )## 特殊:ERP 情况 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($simpleClassNameUnderlineCase = $simpleClassNameUnderlineCases.get($index)) +ErrorCode ${simpleClassNameUnderlineCase.toUpperCase()}_NOT_EXISTS = new ErrorCode(TODO 补充编号, "${subTable.classComment}不存在"); +#if ( !$subTable.subJoinMany ) +ErrorCode ${simpleClassNameUnderlineCase.toUpperCase()}_EXISTS = new ErrorCode(TODO 补充编号, "${subTable.classComment}已存在"); +#end +#end +#end \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm index b8c637698..4085889d9 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm @@ -4,7 +4,12 @@ import java.util.*; import javax.validation.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; +#end import ${PageResultClassName}; +import ${PageParamClassName}; /** * ${table.classComment} Service 接口 @@ -19,14 +24,14 @@ public interface ${table.className}Service { * @param createReqVO 创建信息 * @return 编号 */ - ${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO); + ${primaryColumn.javaType} create${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO); /** * 更新${table.classComment} * * @param updateReqVO 更新信息 */ - void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO); + void update${simpleClassName}(@Valid ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO); /** * 删除${table.classComment} @@ -43,14 +48,8 @@ public interface ${table.className}Service { */ ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id); - /** - * 获得${table.classComment}列表 - * - * @param ids 编号 - * @return ${table.classComment}列表 - */ - List<${table.className}DO> get${simpleClassName}List(Collection<${primaryColumn.javaType}> ids); - +## 特殊:树表专属逻辑(树不需要分页接口) +#if ( $table.templateType != 2 ) /** * 获得${table.classComment}分页 * @@ -58,13 +57,91 @@ public interface ${table.className}Service { * @return ${table.classComment}分页 */ PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO); - +#else /** - * 获得${table.classComment}列表, 用于 Excel 导出 + * 获得${table.classComment}列表 * - * @param exportReqVO 查询条件 + * @param listReqVO 查询条件 * @return ${table.classComment}列表 */ - List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO); + List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO); +#end -} +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 +#set ($subClassNameVar = $subClassNameVars.get($index)) + // ==================== 子表($subTable.classComment) ==================== + +## 情况一:MASTER_ERP 时,需要分查询页子表 +#if ( $table.templateType == 11 ) + /** + * 获得${subTable.classComment}分页 + * + * @param pageReqVO 分页查询 + * @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment} + * @return ${subTable.classComment}分页 + */ + PageResult<${subTable.className}DO> get${subSimpleClassName}Page(PageParam pageReqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField}); + +## 情况二:非 MASTER_ERP 时,需要列表查询子表 +#else + #if ( $subTable.subJoinMany ) + /** + * 获得${subTable.classComment}列表 + * + * @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment} + * @return ${subTable.classComment}列表 + */ + List<${subTable.className}DO> get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}); + + #else + /** + * 获得${subTable.classComment} + * + * @param ${subJoinColumn.javaField} ${subJoinColumn.columnComment} + * @return ${subTable.classComment} + */ + ${subTable.className}DO get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}); + + #end +#end +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 +#if ( $table.templateType == 11 ) + /** + * 创建${subTable.classComment} + * + * @param ${subClassNameVar} 创建信息 + * @return 编号 + */ + ${subPrimaryColumn.javaType} create${subSimpleClassName}(@Valid ${subTable.className}DO ${subClassNameVar}); + + /** + * 更新${subTable.classComment} + * + * @param ${subClassNameVar} 更新信息 + */ + void update${subSimpleClassName}(@Valid ${subTable.className}DO ${subClassNameVar}); + + /** + * 删除${subTable.classComment} + * + * @param id 编号 + */ + void delete${subSimpleClassName}(${subPrimaryColumn.javaType} id); + + /** + * 获得${subTable.classComment} + * + * @param id 编号 + * @return ${subTable.classComment} + */ + ${subTable.className}DO get${subSimpleClassName}(${subPrimaryColumn.javaType} id); + +#end +#end +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm index 9cb6e8b27..6aa2fb2e9 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm @@ -3,21 +3,29 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; import org.springframework.stereotype.Service; import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +import ${basePackage}.module.${subTable.moduleName}.dal.dataobject.${subTable.businessName}.${subTable.className}DO; +#end import ${PageResultClassName}; +import ${PageParamClassName}; +import ${BeanUtils}; -import ${basePackage}.module.${table.moduleName}.convert.${table.businessName}.${table.className}Convert; import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +import ${basePackage}.module.${subTable.moduleName}.dal.mysql.${subTable.businessName}.${subTable.className}Mapper; +#end import static ${ServiceExceptionUtilClassName}.exception; import static ${basePackage}.module.${table.moduleName}.enums.ErrorCodeConstants.*; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; - /** * ${table.classComment} Service 实现类 * @@ -29,31 +37,121 @@ public class ${table.className}ServiceImpl implements ${table.className}Service @Resource private ${table.className}Mapper ${classNameVar}Mapper; +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) + @Resource + private ${subTable.className}Mapper ${subClassNameVars.get($index)}Mapper; +#end @Override - public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}CreateReqVO createReqVO) { +## 特殊:主子表专属逻辑(非 ERP 模式) +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) + @Transactional(rollbackFor = Exception.class) +#end + public ${primaryColumn.javaType} create${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO) { +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 + // 校验${treeParentColumn.columnComment}的有效性 + validateParent${simpleClassName}(null, createReqVO.get${TreeParentJavaField}()); + // 校验${treeNameColumn.columnComment}的唯一性 + validate${simpleClassName}${TreeNameJavaField}Unique(null, createReqVO.get${TreeParentJavaField}(), createReqVO.get${TreeNameJavaField}()); + +#end // 插入 - ${table.className}DO ${classNameVar} = ${table.className}Convert.INSTANCE.convert(createReqVO); + ${table.className}DO ${classNameVar} = BeanUtils.toBean(createReqVO, ${table.className}DO.class); ${classNameVar}Mapper.insert(${classNameVar}); +## 特殊:主子表专属逻辑(非 ERP 模式) +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) + + // 插入子表 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + #if ( $subTable.subJoinMany) + create${subSimpleClassName}List(${classNameVar}.getId(), createReqVO.get${subSimpleClassNames.get($index)}s()); + #else + create${subSimpleClassName}(${classNameVar}.getId(), createReqVO.get${subSimpleClassNames.get($index)}()); + #end +#end +#end // 返回 return ${classNameVar}.getId(); } @Override - public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}UpdateReqVO updateReqVO) { +## 特殊:主子表专属逻辑(非 ERP 模式) +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11 ) + @Transactional(rollbackFor = Exception.class) +#end + public void update${simpleClassName}(${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO) { // 校验存在 validate${simpleClassName}Exists(updateReqVO.getId()); +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 + // 校验${treeParentColumn.columnComment}的有效性 + validateParent${simpleClassName}(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}()); + // 校验${treeNameColumn.columnComment}的唯一性 + validate${simpleClassName}${TreeNameJavaField}Unique(updateReqVO.getId(), updateReqVO.get${TreeParentJavaField}(), updateReqVO.get${TreeNameJavaField}()); + +#end // 更新 - ${table.className}DO updateObj = ${table.className}Convert.INSTANCE.convert(updateReqVO); + ${table.className}DO updateObj = BeanUtils.toBean(updateReqVO, ${table.className}DO.class); ${classNameVar}Mapper.updateById(updateObj); +## 特殊:主子表专属逻辑(非 ERP 模式) +#if ( $subTables && $subTables.size() > 0 && $table.templateType != 11) + + // 更新子表 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + #if ( $subTable.subJoinMany) + update${subSimpleClassName}List(updateReqVO.getId(), updateReqVO.get${subSimpleClassNames.get($index)}s()); + #else + update${subSimpleClassName}(updateReqVO.getId(), updateReqVO.get${subSimpleClassNames.get($index)}()); + #end +#end +#end } @Override +## 特殊:主子表专属逻辑 +#if ( $subTables && $subTables.size() > 0) + @Transactional(rollbackFor = Exception.class) +#end public void delete${simpleClassName}(${primaryColumn.javaType} id) { // 校验存在 validate${simpleClassName}Exists(id); +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) +#set ($ParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 + // 校验是否有子${table.classComment} + if (${classNameVar}Mapper.selectCountBy${ParentJavaField}(id) > 0) { + throw exception(${simpleClassName_underlineCase.toUpperCase()}_EXITS_CHILDREN); + } +#end // 删除 ${classNameVar}Mapper.deleteById(id); +## 特殊:主子表专属逻辑 +#if ( $subTables && $subTables.size() > 0) + + // 删除子表 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + delete${subSimpleClassName}By${SubJoinColumnName}(id); +#end +#end } private void validate${simpleClassName}Exists(${primaryColumn.javaType} id) { @@ -62,27 +160,191 @@ public class ${table.className}ServiceImpl implements ${table.className}Service } } +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) +#set ($TreeParentJavaField = $treeParentColumn.javaField.substring(0,1).toUpperCase() + ${treeParentColumn.javaField.substring(1)})##首字母大写 +#set ($TreeNameJavaField = $treeNameColumn.javaField.substring(0,1).toUpperCase() + ${treeNameColumn.javaField.substring(1)})##首字母大写 + private void validateParent${simpleClassName}(Long id, Long ${treeParentColumn.javaField}) { + if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) { + return; + } + // 1. 不能设置自己为父${table.classComment} + if (Objects.equals(id, ${treeParentColumn.javaField})) { + throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_ERROR); + } + // 2. 父${table.classComment}不存在 + ${simpleClassName}DO parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField}); + if (parent${simpleClassName} == null) { + throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_NOT_EXITS); + } + // 3. 递归校验父${table.classComment},如果父${table.classComment}是自己的子${table.classComment},则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + ${treeParentColumn.javaField} = parent${simpleClassName}.get${TreeParentJavaField}(); + if (Objects.equals(id, ${treeParentColumn.javaField})) { + throw exception(${simpleClassName_underlineCase.toUpperCase()}_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父${table.classComment} + if (${treeParentColumn.javaField} == null || ${simpleClassName}DO.${treeParentColumn_javaField_underlineCase.toUpperCase()}_ROOT.equals(${treeParentColumn.javaField})) { + break; + } + parent${simpleClassName} = ${classNameVar}Mapper.selectById(${treeParentColumn.javaField}); + if (parent${simpleClassName} == null) { + break; + } + } + } + + private void validate${simpleClassName}${TreeNameJavaField}Unique(Long id, Long ${treeParentColumn.javaField}, String ${treeNameColumn.javaField}) { + ${simpleClassName}DO ${classNameVar} = ${classNameVar}Mapper.selectBy${TreeParentJavaField}And${TreeNameJavaField}(${treeParentColumn.javaField}, ${treeNameColumn.javaField}); + if (${classNameVar} == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的${table.classComment} + if (id == null) { + throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE); + } + if (!Objects.equals(${classNameVar}.getId(), id)) { + throw exception(${simpleClassName_underlineCase.toUpperCase()}_${treeNameColumn_javaField_underlineCase.toUpperCase()}_DUPLICATE); + } + } + +#end @Override public ${table.className}DO get${simpleClassName}(${primaryColumn.javaType} id) { return ${classNameVar}Mapper.selectById(id); } - @Override - public List<${table.className}DO> get${simpleClassName}List(Collection<${primaryColumn.javaType}> ids) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return ${classNameVar}Mapper.selectBatchIds(ids); - } - +## 特殊:树表专属逻辑(树不需要分页接口) +#if ( $table.templateType != 2 ) @Override public PageResult<${table.className}DO> get${simpleClassName}Page(${sceneEnum.prefixClass}${table.className}PageReqVO pageReqVO) { return ${classNameVar}Mapper.selectPage(pageReqVO); } - +#else @Override - public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ExportReqVO exportReqVO) { - return ${classNameVar}Mapper.selectList(exportReqVO); + public List<${table.className}DO> get${simpleClassName}List(${sceneEnum.prefixClass}${table.className}ListReqVO listReqVO) { + return ${classNameVar}Mapper.selectList(listReqVO); + } +#end + +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($simpleClassNameUnderlineCase = $simpleClassNameUnderlineCases.get($index)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 +#set ($subClassNameVar = $subClassNameVars.get($index)) + // ==================== 子表($subTable.classComment) ==================== + +## 情况一:MASTER_ERP 时,需要分查询页子表 +#if ( $table.templateType == 11 ) + @Override + public PageResult<${subTable.className}DO> get${subSimpleClassName}Page(PageParam pageReqVO, ${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return ${subClassNameVars.get($index)}Mapper.selectPage(pageReqVO, ${subJoinColumn.javaField}); } -} +## 情况二:非 MASTER_ERP 时,需要列表查询子表 +#else + #if ( $subTable.subJoinMany ) + @Override + public List<${subTable.className}DO> get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return ${subClassNameVars.get($index)}Mapper.selectListBy${SubJoinColumnName}(${subJoinColumn.javaField}); + } + + #else + @Override + public ${subTable.className}DO get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaType} ${subJoinColumn.javaField}) { + return ${subClassNameVars.get($index)}Mapper.selectBy${SubJoinColumnName}(${subJoinColumn.javaField}); + } + + #end +#end +## 情况一:MASTER_ERP 时,支持单个的新增、修改、删除操作 +#if ( $table.templateType == 11 ) + @Override + public ${subPrimaryColumn.javaType} create${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) { +## 特殊:一对一时,需要保证只有一条,不能重复插入 +#if ( !$subTable.subJoinMany) + // 校验是否已经存在 + if (${subClassNameVars.get($index)}Mapper.selectBy${SubJoinColumnName}(${subClassNameVar}.get${SubJoinColumnName}()) != null) { + throw exception(${simpleClassNameUnderlineCase.toUpperCase()}_EXISTS); + } + // 插入 +#end + ${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar}); + return ${subClassNameVar}.getId(); + } + + @Override + public void update${subSimpleClassName}(${subTable.className}DO ${subClassNameVar}) { + // 校验存在 + validate${subSimpleClassName}Exists(${subClassNameVar}.getId()); + // 更新 + ${subClassNameVars.get($index)}Mapper.updateById(${subClassNameVar}); + } + + @Override + public void delete${subSimpleClassName}(${subPrimaryColumn.javaType} id) { + // 校验存在 + validate${subSimpleClassName}Exists(id); + // 删除 + ${subClassNameVars.get($index)}Mapper.deleteById(id); + } + + @Override + public ${subTable.className}DO get${subSimpleClassName}(${subPrimaryColumn.javaType} id) { + return ${subClassNameVars.get($index)}Mapper.selectById(id); + } + + private void validate${subSimpleClassName}Exists(${subPrimaryColumn.javaType} id) { + if (${subClassNameVar}Mapper.selectById(id) == null) { + throw exception(${simpleClassNameUnderlineCase.toUpperCase()}_NOT_EXISTS); + } + } + +## 情况二:非 MASTER_ERP 时,支持批量的新增、修改操作 +#else + #if ( $subTable.subJoinMany) + private void create${subSimpleClassName}List(${primaryColumn.javaType} ${subJoinColumn.javaField}, List<${subTable.className}DO> list) { + list.forEach(o -> o.set$SubJoinColumnName(${subJoinColumn.javaField})); + ${subClassNameVars.get($index)}Mapper.insertBatch(list); + } + + private void update${subSimpleClassName}List(${primaryColumn.javaType} ${subJoinColumn.javaField}, List<${subTable.className}DO> list) { + delete${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + create${subSimpleClassName}List(${subJoinColumn.javaField}, list); + } + + #else + private void create${subSimpleClassName}(${primaryColumn.javaType} ${subJoinColumn.javaField}, ${subTable.className}DO ${subClassNameVar}) { + if (${subClassNameVar} == null) { + return; + } + ${subClassNameVar}.set$SubJoinColumnName(${subJoinColumn.javaField}); + ${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar}); + } + + private void update${subSimpleClassName}(${primaryColumn.javaType} ${subJoinColumn.javaField}, ${subTable.className}DO ${subClassNameVar}) { + if (${subClassNameVar} == null) { + return; + } + ${subClassNameVar}.set$SubJoinColumnName(${subJoinColumn.javaField}); + ${subClassNameVar}.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 + ${subClassNameVars.get($index)}Mapper.insertOrUpdate(${subClassNameVar}); + } + + #end +#end + private void delete${subSimpleClassName}By${SubJoinColumnName}(${primaryColumn.javaType} ${subJoinColumn.javaField}) { + ${subClassNameVars.get($index)}Mapper.deleteBy${SubJoinColumnName}(${subJoinColumn.javaField}); + } + +#end +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm index ec1b45a96..eeac3ce66 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm @@ -77,15 +77,15 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest { @Test public void testCreate${simpleClassName}_success() { // 准备参数 - ${sceneEnum.prefixClass}${table.className}CreateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}CreateReqVO.class); + ${sceneEnum.prefixClass}${table.className}SaveReqVO createReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class).setId(null); // 调用 - ${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(reqVO); + ${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(createReqVO); // 断言 assertNotNull(${classNameVar}Id); // 校验记录的属性是否正确 ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(${classNameVar}Id); - assertPojoEquals(reqVO, ${classNameVar}); + assertPojoEquals(createReqVO, ${classNameVar}, "id"); } @Test @@ -94,24 +94,24 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest { ${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class); ${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据 // 准备参数 - ${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class, o -> { + ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class, o -> { o.setId(db${simpleClassName}.getId()); // 设置更新的 ID }); // 调用 - ${classNameVar}Service.update${simpleClassName}(reqVO); + ${classNameVar}Service.update${simpleClassName}(updateReqVO); // 校验是否更新正确 - ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(reqVO.getId()); // 获取最新的 - assertPojoEquals(reqVO, ${classNameVar}); + ${table.className}DO ${classNameVar} = ${classNameVar}Mapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, ${classNameVar}); } @Test public void testUpdate${simpleClassName}_notExists() { // 准备参数 - ${sceneEnum.prefixClass}${table.className}UpdateReqVO reqVO = randomPojo(${sceneEnum.prefixClass}${table.className}UpdateReqVO.class); + ${sceneEnum.prefixClass}${table.className}SaveReqVO updateReqVO = randomPojo(${sceneEnum.prefixClass}${table.className}SaveReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(reqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); + assertServiceException(() -> ${classNameVar}Service.update${simpleClassName}(updateReqVO), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); } @Test @@ -137,6 +137,8 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> ${classNameVar}Service.delete${simpleClassName}(id), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS); } +## 特殊:树表专属逻辑(树不需要分页接口) +#if ( $table.templateType != 2 ) @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGet${simpleClassName}Page() { @@ -149,11 +151,11 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest { assertEquals(1, pageResult.getList().size()); assertPojoEquals(db${simpleClassName}, pageResult.getList().get(0)); } - +#else @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGet${simpleClassName}List() { - #getPageCondition("ExportReqVO") + #getPageCondition("ListReqVO") // 调用 List<${table.className}DO> list = ${classNameVar}Service.get${simpleClassName}List(reqVO); @@ -161,5 +163,6 @@ public class ${table.className}ServiceImplTest extends BaseDbUnitTest { assertEquals(1, list.size()); assertPojoEquals(db${simpleClassName}, list.get(0)); } +#end -} +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/h2.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/h2.vm index 20c33ad59..b22389b0b 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/h2.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/h2.vm @@ -23,6 +23,8 @@ CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" ( "${column.columnName}" ${dataType} DEFAULT '', #elseif (${column.columnName} == 'deleted') "deleted" bit NOT NULL DEFAULT FALSE, + #elseif (${column.columnName} == 'tenantId') + "tenant_id" bigint NOT NULL DEFAULT 0, #else "${column.columnName.toLowerCase()}" ${dataType}#if (${column.nullable} == false) NOT NULL#end, #end @@ -32,4 +34,4 @@ CREATE TABLE IF NOT EXISTS "${table.tableName.toLowerCase()}" ( ) COMMENT '${table.tableComment}'; -- 将该删表 SQL 语句,添加到 yudao-module-${table.moduleName}-biz 模块的 test/resources/sql/clean.sql 文件里 -DELETE FROM "${table.tableName}"; +DELETE FROM "${table.tableName}"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/sql.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/sql.vm index 902ca7414..41b107dba 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/sql.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/sql/sql.vm @@ -5,7 +5,7 @@ INSERT INTO system_menu( ) VALUES ( '${table.classComment}管理', '', 2, 0, ${table.parentMenuId}, - '${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 0, '${table.className}' + '${simpleClassName_strikeCase}', '', '${table.moduleName}/${table.businessName}/index', 0, '${table.className}' ); -- 按钮父菜单ID @@ -25,4 +25,4 @@ VALUES ( '${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId, '', '', '', 0 ); -#end +#end \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm index 5e9da3238..bfe2dc007 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm @@ -35,21 +35,113 @@ export function get${simpleClassName}(id) { }) } +#if ( $table.templateType != 2 ) // 获得${table.classComment}分页 -export function get${simpleClassName}Page(query) { +export function get${simpleClassName}Page(params) { return request({ url: '${baseURL}/page', method: 'get', - params: query + params }) } - +#else +// 获得${table.classComment}列表 +export function get${simpleClassName}List(params) { + return request({ + url: '${baseURL}/list', + method: 'get', + params + }) +} +#end // 导出${table.classComment} Excel -export function export${simpleClassName}Excel(query) { +export function export${simpleClassName}Excel(params) { return request({ url: '${baseURL}/export-excel', method: 'get', - params: query, + params, responseType: 'blob' }) } +## 特殊:主子表专属逻辑 TODO @puhui999:下面方法的【空格】不太对 +#foreach ($subTable in $subTables) + #set ($index = $foreach.count - 1) + #set ($subSimpleClassName = $subSimpleClassNames.get($index)) + #set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 + #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 + #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index)) + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) + #set ($subClassNameVar = $subClassNameVars.get($index)) + +// ==================== 子表($subTable.classComment) ==================== + ## 情况一:MASTER_ERP 时,需要分查询页子表 + #if ( $table.templateType == 11 ) + + // 获得${subTable.classComment}分页 + export function get${subSimpleClassName}Page(params) { + return request({ + url: '${baseURL}/${subSimpleClassName_strikeCase}/page', + method: 'get', + params + }) + } + ## 情况二:非 MASTER_ERP 时,需要列表查询子表 + #else + #if ( $subTable.subJoinMany ) + + // 获得${subTable.classComment}列表 + export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) { + return request({ + url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField}, + method: 'get' + }) + } + #else + + // 获得${subTable.classComment} + export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}) { + return request({ + url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField}, + method: 'get' + }) + } + #end + #end + ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 + #if ( $table.templateType == 11 ) + // 新增${subTable.classComment} + export function create${subSimpleClassName}(data) { + return request({ + url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, + method: 'post', + data + }) + } + + // 修改${subTable.classComment} + export function update${subSimpleClassName}(data) { + return request({ + url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, + method: 'post', + data + }) + } + + // 删除${subTable.classComment} + export function delete${subSimpleClassName}(id) { + return request({ + url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id, + method: 'delete' + }) + } + + // 获得${subTable.classComment} + export function get${subSimpleClassName}(id) { + return request({ + url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id, + method: 'get' + }) + } + #end +#end \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_erp.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_erp.vue.vm new file mode 100644 index 000000000..99aa91af1 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_erp.vue.vm @@ -0,0 +1,205 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_inner.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_inner.vue.vm new file mode 100644 index 000000000..ca266be9d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_inner.vue.vm @@ -0,0 +1,2 @@ +## 主表的 normal 和 inner 使用相同的 form 表单 +#parse("codegen/vue/views/components/form_sub_normal.vue.vm") \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_normal.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_normal.vue.vm new file mode 100644 index 000000000..48a404a3b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/form_sub_normal.vue.vm @@ -0,0 +1,347 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/list_sub_erp.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/list_sub_erp.vue.vm new file mode 100644 index 000000000..589736b6e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/list_sub_erp.vue.vm @@ -0,0 +1,165 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/list_sub_inner.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/list_sub_inner.vue.vm new file mode 100644 index 000000000..90b8e4153 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/components/list_sub_inner.vue.vm @@ -0,0 +1,4 @@ +## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点: +## 1)inner 使用 list 不分页,erp 使用 page 分页 +## 2)erp 支持单个子表的新增、修改、删除,inner 不支持 +#parse("codegen/vue/views/components/list_sub_erp.vue.vm") \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/form.vue.vm new file mode 100644 index 000000000..634d05d3b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/form.vue.vm @@ -0,0 +1,320 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm index 7a6add604..2328007a0 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/views/index.vue.vm @@ -1,6 +1,5 @@ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm index 401796db8..c4b0b4332 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm @@ -15,10 +15,17 @@ export interface ${simpleClassName}VO { #end } -// 查询${table.classComment}列表 +#if ( $table.templateType != 2 ) +// 查询${table.classComment}分页 export const get${simpleClassName}Page = async (params) => { return await request.get({ url: `${baseURL}/page`, params }) } +#else +// 查询${table.classComment}列表 +export const get${simpleClassName}List = async (params) => { + return await request.get({ url: `${baseURL}/list`, params }) +} +#end // 查询${table.classComment}详情 export const get${simpleClassName} = async (id: number) => { @@ -44,3 +51,61 @@ export const delete${simpleClassName} = async (id: number) => { export const export${simpleClassName} = async (params) => { return await request.download({ url: `${baseURL}/export-excel`, params }) } +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index)) +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) + +// ==================== 子表($subTable.classComment) ==================== +## 情况一:MASTER_ERP 时,需要分查询页子表 +#if ( $table.templateType == 11 ) + +// 获得${subTable.classComment}分页 +export const get${subSimpleClassName}Page = async (params) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/page`, params }) +} +## 情况二:非 MASTER_ERP 时,需要列表查询子表 +#else + #if ( $subTable.subJoinMany ) + +// 获得${subTable.classComment}列表 +export const get${subSimpleClassName}ListBy${SubJoinColumnName} = async (${subJoinColumn.javaField}) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) +} + #else + +// 获得${subTable.classComment} +export const get${subSimpleClassName}By${SubJoinColumnName} = async (${subJoinColumn.javaField}) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) +} + #end +#end +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 +#if ( $table.templateType == 11 ) +// 新增${subTable.classComment} +export const create${subSimpleClassName} = async (data) => { + return await request.post({ url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, data }) +} + +// 修改${subTable.classComment} +export const update${subSimpleClassName} = async (data) => { + return await request.put({ url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, data }) +} + +// 删除${subTable.classComment} +export const delete${subSimpleClassName} = async (id: number) => { + return await request.delete({ url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id }) +} + +// 获得${subTable.classComment} +export const get${subSimpleClassName} = async (id: number) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id }) +} +#end +#end \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm new file mode 100644 index 000000000..ed318875e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm @@ -0,0 +1,205 @@ +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_inner.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_inner.vue.vm new file mode 100644 index 000000000..d8542c3d5 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_inner.vue.vm @@ -0,0 +1,2 @@ +## 主表的 normal 和 inner 使用相同的 form 表单 +#parse("codegen/vue3/views/components/form_sub_normal.vue.vm") \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_normal.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_normal.vue.vm new file mode 100644 index 000000000..90df79812 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_normal.vue.vm @@ -0,0 +1,362 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm new file mode 100644 index 000000000..5ad208b3b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm @@ -0,0 +1,181 @@ +#set ($subTable = $subTables.get($subIndex))##当前表 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex)) +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_inner.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_inner.vue.vm new file mode 100644 index 000000000..3fe648892 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/list_sub_inner.vue.vm @@ -0,0 +1,4 @@ +## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点: +## 1)inner 使用 list 不分页,erp 使用 page 分页 +## 2)erp 支持单个子表的新增、修改、删除,inner 不支持 +#parse("codegen/vue3/views/components/list_sub_erp.vue.vm") \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm index 4e23f2f08..1c1553622 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm @@ -7,7 +7,6 @@ label-width="100px" v-loading="formLoading" > -#set ($dictMethods = [])## 使用到的 dict 字典方法 #foreach($column in $columns) #if ($column.createOperation || $column.updateOperation) #set ($dictType = $column.dictType) @@ -23,31 +22,41 @@ #elseif ($javaType == "Boolean") #set ($dictMethod = "getBoolDictOptions") #end - #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 + #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id ) + + + + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里 #elseif($column.htmlType == "imageUpload")## 图片上传 - #set ($hasImageUploadColumn = true) - + #elseif($column.htmlType == "fileUpload")## 文件上传 - #set ($hasFileUploadColumn = true) - + #elseif($column.htmlType == "editor")## 文本编辑器 - + #elseif($column.htmlType == "select")## 下拉框 #if ("" != $dictType)## 有数据字典 - #if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import - #set($ignore = $dictMethods.add($dictMethod) ) - #end #if ("" != $dictType)## 有数据字典 - #if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import - #set($ignore = $dictMethods.add($dictMethod) ) - #end #if ("" != $dictType)## 有数据字典 - #if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import - #set($ignore = $dictMethods.add($dictMethod) ) - #end +## 特殊:主子表专属逻辑 +#if ( $table.templateType == 10 || $table.templateType == 12 ) + + + #foreach ($subTable in $subTables) + #set ($index = $foreach.count - 1) + #set ($subClassNameVar = $subClassNameVars.get($index)) + #set ($subSimpleClassName = $subSimpleClassNames.get($index)) + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) + + <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData.id" /> + + #end + +#end +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) + +/** 获得${table.classComment}树 */ +const get${simpleClassName}Tree = async () => { + ${classNameVar}Tree.value = [] + const data = await ${simpleClassName}Api.get${simpleClassName}List() + const root: Tree = { id: 0, name: '顶级${table.classComment}', children: [] } + root.children = handleTree(data, 'id', '${treeParentColumn.javaField}') + ${classNameVar}Tree.value.push(root) +} +#end + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm index 477654a37..eab90c12a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm @@ -8,7 +8,6 @@ :inline="true" label-width="68px" > - #set ($dictMethods = [])## 使用到的 dict 字典方法 #foreach($column in $columns) #if ($column.listOperation) #set ($dictType = $column.dictType) @@ -36,20 +35,13 @@ #elseif ($column.htmlType == "select" || $column.htmlType == "radio") - #if ($javaField.length() + $comment.length() > 8) - #else - - #end #if ("" != $dictType)## 设置了 dictType 数据字典的情况 - #if (!$dictMethods.contains($dictMethod))## 如果不存在,则添加到 dictMethods 数组中,后续好 import - #set($ignore = $dictMethods.add($dictMethod) ) - #end 搜索 重置 - #if ($permissionPrefix.length() <= 12) - - #else - #end 新增 导出 +## 特殊:树表专属逻辑 +#if ( $table.templateType == 2 ) + + 展开/折叠 + +#end +## 特殊:主子表专属逻辑 +#if ( $table.templateType == 11 && $subTables && $subTables.size() > 0 ) + +## 特殊:树表专属逻辑 +#elseif ( $table.templateType == 2 ) + +#else +#end +## 特殊:主子表专属逻辑 +#if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 ) + + + + +#end #foreach($column in $columns) #if ($column.listOperationResult) #set ($dictType=$column.dictType) @@ -134,7 +170,7 @@ :formatter="dateFormatter" width="180px" /> - #elseif("" != $column.dictType)## 数据字典 + #elseif($column.dictType && "" != $column.dictType)## 数据字典 + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm index cbc6a17ba..ff4fa810a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm @@ -1,10 +1,5 @@ import type { CrudSchema } from '@/hooks/web/useCrudSchemas' -#foreach ($column in $columns) - #if ($column.listOperationResult && $column.htmlType == "datetime") import { dateFormatter } from '@/utils/formatTime' - #break - #end -#end // 表单校验 export const rules = reactive({ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm index 45b8aa260..52f20a2f5 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm @@ -8,7 +8,7 @@ diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentContactList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentContactList new file mode 100644 index 000000000..00f1ce040 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentContactList @@ -0,0 +1,129 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentForm new file mode 100644 index 000000000..d89e5066d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentForm @@ -0,0 +1,149 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherForm new file mode 100644 index 000000000..874a03bbc --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherForm @@ -0,0 +1,151 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherList new file mode 100644 index 000000000..7d561a0ee --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/StudentTeacherList @@ -0,0 +1,129 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/index new file mode 100644 index 000000000..9c7588f2a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_erp/vue/index @@ -0,0 +1,233 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/assert.json new file mode 100644 index 000000000..f95ae9af1 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/assert.json @@ -0,0 +1,73 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/index.vue" +}, { + "contentPath" : "js/student", + "filePath" : "yudao-ui-admin-vue2/src/api/infra/student.js" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/StudentForm.vue" +}, { + "contentPath" : "vue/StudentContactForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/components/StudentContactForm.vue" +}, { + "contentPath" : "vue/StudentTeacherForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/components/StudentTeacherForm.vue" +}, { + "contentPath" : "vue/StudentContactList", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/components/StudentContactList.vue" +}, { + "contentPath" : "vue/StudentTeacherList", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/components/StudentTeacherList.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..f8be66202 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentContactDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentContactDO new file mode 100644 index 000000000..17c668eaa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentContactMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentContactMapper new file mode 100644 index 000000000..35bbd53c2 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentContactMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default List selectListByStudentId(Long studentId) { + return selectList(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentController new file mode 100644 index 000000000..b9a587b44 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentController @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/list-by-student-id") + @Operation(summary = "获得学生联系人列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactListByStudentId(studentId)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/get-by-student-id") + @Operation(summary = "获得学生班主任") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..faa491dfb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentSaveReqVO @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + + @Schema(description = "学生联系人列表") + private List studentContacts; + + @Schema(description = "学生班主任") + private InfraStudentTeacherDO studentTeacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentService new file mode 100644 index 000000000..afa7d22eb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentService @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人列表 + * + * @param studentId 学生编号 + * @return 学生联系人列表 + */ + List getStudentContactListByStudentId(Long studentId); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任 + * + * @param studentId 学生编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentServiceImpl new file mode 100644 index 000000000..c57cba613 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentServiceImpl @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + // 插入子表 + createStudentContactList(student.getId(), createReqVO.getStudentContacts()); + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher()); + // 返回 + return student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + + // 更新子表 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts()); + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public List getStudentContactListByStudentId(Long studentId) { + return studentContactMapper.selectListByStudentId(studentId); + } + + private void createStudentContactList(Long studentId, List list) { + list.forEach(o -> o.setStudentId(studentId)); + studentContactMapper.insertBatch(list); + } + + private void updateStudentContactList(Long studentId, List list) { + deleteStudentContactByStudentId(studentId); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createStudentContactList(studentId, list); + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) { + return studentTeacherMapper.selectByStudentId(studentId); + } + + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacherMapper.insert(studentTeacher); + } + + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 + studentTeacherMapper.insertOrUpdate(studentTeacher); + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentTeacherDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentTeacherDO new file mode 100644 index 000000000..c19cf9fab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentTeacherMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentTeacherMapper new file mode 100644 index 000000000..0521bbaf4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/java/InfraStudentTeacherMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/js/student b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/js/student new file mode 100644 index 000000000..b4e6ac5e4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/js/student @@ -0,0 +1,74 @@ +import request from '@/utils/request' + +// 创建学生 +export function createStudent(data) { + return request({ + url: '/infra/student/create', + method: 'post', + data: data + }) +} + +// 更新学生 +export function updateStudent(data) { + return request({ + url: '/infra/student/update', + method: 'put', + data: data + }) +} + +// 删除学生 +export function deleteStudent(id) { + return request({ + url: '/infra/student/delete?id=' + id, + method: 'delete' + }) +} + +// 获得学生 +export function getStudent(id) { + return request({ + url: '/infra/student/get?id=' + id, + method: 'get' + }) +} + +// 获得学生分页 +export function getStudentPage(params) { + return request({ + url: '/infra/student/page', + method: 'get', + params + }) +} +// 导出学生 Excel +export function exportStudentExcel(params) { + return request({ + url: '/infra/student/export-excel', + method: 'get', + params, + responseType: 'blob' + }) +} + +// ==================== 子表(学生联系人) ==================== + + // 获得学生联系人列表 + export function getStudentContactListByStudentId(studentId) { + return request({ + url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId, + method: 'get' + }) + } + +// ==================== 子表(学生班主任) ==================== + + // 获得学生班主任 + export function getStudentTeacherByStudentId(studentId) { + return request({ + url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId, + method: 'get' + }) + } + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/sql/sql new file mode 100644 index 000000000..83df27926 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentContactForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentContactForm new file mode 100644 index 000000000..c953bfa13 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentContactForm @@ -0,0 +1,177 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentContactList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentContactList new file mode 100644 index 000000000..c0a8710e9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentContactList @@ -0,0 +1,89 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentForm new file mode 100644 index 000000000..6d93b6122 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentForm @@ -0,0 +1,180 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherForm new file mode 100644 index 000000000..0dac19bb3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherForm @@ -0,0 +1,127 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherList new file mode 100644 index 000000000..9f572742d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/StudentTeacherList @@ -0,0 +1,93 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/index new file mode 100644 index 000000000..ddeafdf29 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/vue/index @@ -0,0 +1,222 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/xml/InfraStudentMapper similarity index 68% rename from yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml rename to yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/xml/InfraStudentMapper index 287f58d82..155aa5c27 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/test/TestDemoMapper.xml +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_inner/xml/InfraStudentMapper @@ -1,6 +1,6 @@ - + - - - + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/assert.json new file mode 100644 index 000000000..844cc753c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/assert.json @@ -0,0 +1,67 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/index.vue" +}, { + "contentPath" : "js/student", + "filePath" : "yudao-ui-admin-vue2/src/api/infra/student.js" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/StudentForm.vue" +}, { + "contentPath" : "vue/StudentContactForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/components/StudentContactForm.vue" +}, { + "contentPath" : "vue/StudentTeacherForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/components/StudentTeacherForm.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..f8be66202 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentContactDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentContactDO new file mode 100644 index 000000000..17c668eaa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentContactMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentContactMapper new file mode 100644 index 000000000..35bbd53c2 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentContactMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default List selectListByStudentId(Long studentId) { + return selectList(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentController new file mode 100644 index 000000000..b9a587b44 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentController @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/list-by-student-id") + @Operation(summary = "获得学生联系人列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactListByStudentId(studentId)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/get-by-student-id") + @Operation(summary = "获得学生班主任") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..faa491dfb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentSaveReqVO @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + + @Schema(description = "学生联系人列表") + private List studentContacts; + + @Schema(description = "学生班主任") + private InfraStudentTeacherDO studentTeacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentService new file mode 100644 index 000000000..afa7d22eb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentService @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人列表 + * + * @param studentId 学生编号 + * @return 学生联系人列表 + */ + List getStudentContactListByStudentId(Long studentId); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任 + * + * @param studentId 学生编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentServiceImpl new file mode 100644 index 000000000..c57cba613 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentServiceImpl @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + // 插入子表 + createStudentContactList(student.getId(), createReqVO.getStudentContacts()); + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher()); + // 返回 + return student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + + // 更新子表 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts()); + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public List getStudentContactListByStudentId(Long studentId) { + return studentContactMapper.selectListByStudentId(studentId); + } + + private void createStudentContactList(Long studentId, List list) { + list.forEach(o -> o.setStudentId(studentId)); + studentContactMapper.insertBatch(list); + } + + private void updateStudentContactList(Long studentId, List list) { + deleteStudentContactByStudentId(studentId); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createStudentContactList(studentId, list); + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) { + return studentTeacherMapper.selectByStudentId(studentId); + } + + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacherMapper.insert(studentTeacher); + } + + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 + studentTeacherMapper.insertOrUpdate(studentTeacher); + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentTeacherDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentTeacherDO new file mode 100644 index 000000000..c19cf9fab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentTeacherMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentTeacherMapper new file mode 100644 index 000000000..0521bbaf4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/java/InfraStudentTeacherMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/js/student b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/js/student new file mode 100644 index 000000000..b4e6ac5e4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/js/student @@ -0,0 +1,74 @@ +import request from '@/utils/request' + +// 创建学生 +export function createStudent(data) { + return request({ + url: '/infra/student/create', + method: 'post', + data: data + }) +} + +// 更新学生 +export function updateStudent(data) { + return request({ + url: '/infra/student/update', + method: 'put', + data: data + }) +} + +// 删除学生 +export function deleteStudent(id) { + return request({ + url: '/infra/student/delete?id=' + id, + method: 'delete' + }) +} + +// 获得学生 +export function getStudent(id) { + return request({ + url: '/infra/student/get?id=' + id, + method: 'get' + }) +} + +// 获得学生分页 +export function getStudentPage(params) { + return request({ + url: '/infra/student/page', + method: 'get', + params + }) +} +// 导出学生 Excel +export function exportStudentExcel(params) { + return request({ + url: '/infra/student/export-excel', + method: 'get', + params, + responseType: 'blob' + }) +} + +// ==================== 子表(学生联系人) ==================== + + // 获得学生联系人列表 + export function getStudentContactListByStudentId(studentId) { + return request({ + url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId, + method: 'get' + }) + } + +// ==================== 子表(学生班主任) ==================== + + // 获得学生班主任 + export function getStudentTeacherByStudentId(studentId) { + return request({ + url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId, + method: 'get' + }) + } + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/sql/sql new file mode 100644 index 000000000..83df27926 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentContactForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentContactForm new file mode 100644 index 000000000..c953bfa13 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentContactForm @@ -0,0 +1,177 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentForm new file mode 100644 index 000000000..6d93b6122 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentForm @@ -0,0 +1,180 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentTeacherForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentTeacherForm new file mode 100644 index 000000000..0dac19bb3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/StudentTeacherForm @@ -0,0 +1,127 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/index new file mode 100644 index 000000000..460758127 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/vue/index @@ -0,0 +1,205 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/xml/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/xml/InfraStudentMapper new file mode 100644 index 000000000..155aa5c27 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_master_normal/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/assert.json new file mode 100644 index 000000000..ccb00a814 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/assert.json @@ -0,0 +1,49 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/index.vue" +}, { + "contentPath" : "js/student", + "filePath" : "yudao-ui-admin-vue2/src/api/infra/student.js" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/StudentForm.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..f8be66202 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentController new file mode 100644 index 000000000..3796982c4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentController @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..43e7f147d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentSaveReqVO @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentService new file mode 100644 index 000000000..c4a0e1792 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentService @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentServiceImpl new file mode 100644 index 000000000..2292a66f3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentServiceImpl @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + + @Override + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + // 返回 + return student.getId(); + } + + @Override + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + } + + @Override + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/js/student b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/js/student new file mode 100644 index 000000000..44db46806 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/js/student @@ -0,0 +1,53 @@ +import request from '@/utils/request' + +// 创建学生 +export function createStudent(data) { + return request({ + url: '/infra/student/create', + method: 'post', + data: data + }) +} + +// 更新学生 +export function updateStudent(data) { + return request({ + url: '/infra/student/update', + method: 'put', + data: data + }) +} + +// 删除学生 +export function deleteStudent(id) { + return request({ + url: '/infra/student/delete?id=' + id, + method: 'delete' + }) +} + +// 获得学生 +export function getStudent(id) { + return request({ + url: '/infra/student/get?id=' + id, + method: 'get' + }) +} + +// 获得学生分页 +export function getStudentPage(params) { + return request({ + url: '/infra/student/page', + method: 'get', + params + }) +} +// 导出学生 Excel +export function exportStudentExcel(params) { + return request({ + url: '/infra/student/export-excel', + method: 'get', + params, + responseType: 'blob' + }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/sql/sql new file mode 100644 index 000000000..83df27926 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/vue/StudentForm new file mode 100644 index 000000000..d89e5066d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/vue/StudentForm @@ -0,0 +1,149 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/vue/index new file mode 100644 index 000000000..460758127 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/vue/index @@ -0,0 +1,205 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/xml/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/xml/InfraStudentMapper new file mode 100644 index 000000000..155aa5c27 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_one/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/assert.json new file mode 100644 index 000000000..470a9dec8 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/assert.json @@ -0,0 +1,49 @@ +[ { + "contentPath" : "java/InfraCategoryListReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategoryListReqVO.java" +}, { + "contentPath" : "java/InfraCategoryRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategoryRespVO.java" +}, { + "contentPath" : "java/InfraCategorySaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategorySaveReqVO.java" +}, { + "contentPath" : "java/InfraCategoryController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraCategoryController.java" +}, { + "contentPath" : "java/InfraCategoryDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraCategoryDO.java" +}, { + "contentPath" : "java/InfraCategoryMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraCategoryMapper.java" +}, { + "contentPath" : "xml/InfraCategoryMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraCategoryMapper.xml" +}, { + "contentPath" : "java/InfraCategoryServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryServiceImpl.java" +}, { + "contentPath" : "java/InfraCategoryService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryService.java" +}, { + "contentPath" : "java/InfraCategoryServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/index.vue" +}, { + "contentPath" : "js/category", + "filePath" : "yudao-ui-admin-vue2/src/api/infra/category.js" +}, { + "contentPath" : "vue/CategoryForm", + "filePath" : "yudao-ui-admin-vue2/src/views/infra/demo/CategoryForm.vue" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..36df6752e --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,8 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 分类 TODO 补充编号 ========== +ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(TODO 补充编号, "分类不存在"); +ErrorCode CATEGORY_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子分类,无法删除"); +ErrorCode CATEGORY_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级分类不存在"); +ErrorCode CATEGORY_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父分类"); +ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该名字的分类"); +ErrorCode CATEGORY_PARENT_IS_CHILD = new ErrorCode(TODO 补充编号, "不能设置自己的子InfraCategory为父InfraCategory"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryController new file mode 100644 index 000000000..a7b2f8163 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryController @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraCategoryService; + +@Tag(name = "管理后台 - 分类") +@RestController +@RequestMapping("/infra/category") +@Validated +public class InfraCategoryController { + + @Resource + private InfraCategoryService categoryService; + + @PostMapping("/create") + @Operation(summary = "创建分类") + @PreAuthorize("@ss.hasPermission('infra:category:create')") + public CommonResult createCategory(@Valid @RequestBody InfraCategorySaveReqVO createReqVO) { + return success(categoryService.createCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新分类") + @PreAuthorize("@ss.hasPermission('infra:category:update')") + public CommonResult updateCategory(@Valid @RequestBody InfraCategorySaveReqVO updateReqVO) { + categoryService.updateCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:category:delete')") + public CommonResult deleteCategory(@RequestParam("id") Long id) { + categoryService.deleteCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:category:query')") + public CommonResult getCategory(@RequestParam("id") Long id) { + InfraCategoryDO category = categoryService.getCategory(id); + return success(BeanUtils.toBean(category, InfraCategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得分类列表") + @PreAuthorize("@ss.hasPermission('infra:category:query')") + public CommonResult> getCategoryList(@Valid InfraCategoryListReqVO listReqVO) { + List list = categoryService.getCategoryList(listReqVO); + return success(BeanUtils.toBean(list, InfraCategoryRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出分类 Excel") + @PreAuthorize("@ss.hasPermission('infra:category:export')") + @OperateLog(type = EXPORT) + public void exportCategoryExcel(@Valid InfraCategoryListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = categoryService.getCategoryList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "分类.xls", "数据", InfraCategoryRespVO.class, + BeanUtils.toBean(list, InfraCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryDO new file mode 100644 index 000000000..9bf21c08b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryDO @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 分类 DO + * + * @author 芋道源码 + */ +@TableName("infra_category") +@KeySequence("infra_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraCategoryDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 父编号 + */ + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryListReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryListReqVO new file mode 100644 index 000000000..e5c6f181f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryListReqVO @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - 分类列表 Request VO") +@Data +public class InfraCategoryListReqVO { + + @Schema(description = "名字", example = "芋头") + private String name; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryMapper new file mode 100644 index 000000000..9dadbf1d9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryMapper @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraCategoryMapper extends BaseMapperX { + + default List selectList(InfraCategoryListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(InfraCategoryDO::getName, reqVO.getName()) + .orderByDesc(InfraCategoryDO::getId)); + } + + default InfraCategoryDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(InfraCategoryDO::getParentId, parentId, InfraCategoryDO::getName, name); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(InfraCategoryDO::getParentId, parentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO new file mode 100644 index 000000000..6325d866c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraCategoryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "父编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @ExcelProperty("父编号") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategorySaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategorySaveReqVO new file mode 100644 index 000000000..3c03b977f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategorySaveReqVO @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; + +@Schema(description = "管理后台 - 分类新增/修改 Request VO") +@Data +public class InfraCategorySaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "父编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @NotNull(message = "父编号不能为空") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryService new file mode 100644 index 000000000..9d0ae1afa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryService @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 分类 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraCategoryService { + + /** + * 创建分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCategory(@Valid InfraCategorySaveReqVO createReqVO); + + /** + * 更新分类 + * + * @param updateReqVO 更新信息 + */ + void updateCategory(@Valid InfraCategorySaveReqVO updateReqVO); + + /** + * 删除分类 + * + * @param id 编号 + */ + void deleteCategory(Long id); + + /** + * 获得分类 + * + * @param id 编号 + * @return 分类 + */ + InfraCategoryDO getCategory(Long id); + + /** + * 获得分类列表 + * + * @param listReqVO 查询条件 + * @return 分类列表 + */ + List getCategoryList(InfraCategoryListReqVO listReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryServiceImpl new file mode 100644 index 000000000..351568b18 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryServiceImpl @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraCategoryMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraCategoryServiceImpl implements InfraCategoryService { + + @Resource + private InfraCategoryMapper categoryMapper; + + @Override + public Long createCategory(InfraCategorySaveReqVO createReqVO) { + // 校验父编号的有效性 + validateParentCategory(null, createReqVO.getParentId()); + // 校验名字的唯一性 + validateCategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + InfraCategoryDO category = BeanUtils.toBean(createReqVO, InfraCategoryDO.class); + categoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateCategory(InfraCategorySaveReqVO updateReqVO) { + // 校验存在 + validateCategoryExists(updateReqVO.getId()); + // 校验父编号的有效性 + validateParentCategory(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验名字的唯一性 + validateCategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + InfraCategoryDO updateObj = BeanUtils.toBean(updateReqVO, InfraCategoryDO.class); + categoryMapper.updateById(updateObj); + } + + @Override + public void deleteCategory(Long id) { + // 校验存在 + validateCategoryExists(id); + // 校验是否有子分类 + if (categoryMapper.selectCountByParentId(id) > 0) { + throw exception(CATEGORY_EXITS_CHILDREN); + } + // 删除 + categoryMapper.deleteById(id); + } + + private void validateCategoryExists(Long id) { + if (categoryMapper.selectById(id) == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + } + + private void validateParentCategory(Long id, Long parentId) { + if (parentId == null || CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父分类 + if (Objects.equals(id, parentId)) { + throw exception(CATEGORY_PARENT_ERROR); + } + // 2. 父分类不存在 + CategoryDO parentCategory = categoryMapper.selectById(parentId); + if (parentCategory == null) { + throw exception(CATEGORY_PARENT_NOT_EXITS); + } + // 3. 递归校验父分类,如果父分类是自己的子分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentCategory.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(CATEGORY_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父分类 + if (parentId == null || CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentCategory = categoryMapper.selectById(parentId); + if (parentCategory == null) { + break; + } + } + } + + private void validateCategoryNameUnique(Long id, Long parentId, String name) { + CategoryDO category = categoryMapper.selectByParentIdAndName(parentId, name); + if (category == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的分类 + if (id == null) { + throw exception(CATEGORY_NAME_DUPLICATE); + } + if (!Objects.equals(category.getId(), id)) { + throw exception(CATEGORY_NAME_DUPLICATE); + } + } + + @Override + public InfraCategoryDO getCategory(Long id) { + return categoryMapper.selectById(id); + } + + @Override + public List getCategoryList(InfraCategoryListReqVO listReqVO) { + return categoryMapper.selectList(listReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryServiceImplTest new file mode 100644 index 000000000..efb70fd33 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/java/InfraCategoryServiceImplTest @@ -0,0 +1,129 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraCategoryMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraCategoryServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraCategoryServiceImpl.class) +public class InfraCategoryServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraCategoryServiceImpl categoryService; + + @Resource + private InfraCategoryMapper categoryMapper; + + @Test + public void testCreateCategory_success() { + // 准备参数 + InfraCategorySaveReqVO createReqVO = randomPojo(InfraCategorySaveReqVO.class).setId(null); + + // 调用 + Long categoryId = categoryService.createCategory(createReqVO); + // 断言 + assertNotNull(categoryId); + // 校验记录的属性是否正确 + InfraCategoryDO category = categoryMapper.selectById(categoryId); + assertPojoEquals(createReqVO, category, "id"); + } + + @Test + public void testUpdateCategory_success() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraCategorySaveReqVO updateReqVO = randomPojo(InfraCategorySaveReqVO.class, o -> { + o.setId(dbCategory.getId()); // 设置更新的 ID + }); + + // 调用 + categoryService.updateCategory(updateReqVO); + // 校验是否更新正确 + InfraCategoryDO category = categoryMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, category); + } + + @Test + public void testUpdateCategory_notExists() { + // 准备参数 + InfraCategorySaveReqVO updateReqVO = randomPojo(InfraCategorySaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.updateCategory(updateReqVO), CATEGORY_NOT_EXISTS); + } + + @Test + public void testDeleteCategory_success() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCategory.getId(); + + // 调用 + categoryService.deleteCategory(id); + // 校验数据不存在了 + assertNull(categoryMapper.selectById(id)); + } + + @Test + public void testDeleteCategory_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCategoryList() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class, o -> { // 等会查询到 + o.setName(null); + }); + categoryMapper.insert(dbCategory); + // 测试 name 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); + // 准备参数 + InfraCategoryListReqVO reqVO = new InfraCategoryListReqVO(); + reqVO.setName(null); + + // 调用 + List list = categoryService.getCategoryList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCategory, list.get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/js/category b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/js/category new file mode 100644 index 000000000..1e6ffdcea --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/js/category @@ -0,0 +1,53 @@ +import request from '@/utils/request' + +// 创建分类 +export function createCategory(data) { + return request({ + url: '/infra/category/create', + method: 'post', + data: data + }) +} + +// 更新分类 +export function updateCategory(data) { + return request({ + url: '/infra/category/update', + method: 'put', + data: data + }) +} + +// 删除分类 +export function deleteCategory(id) { + return request({ + url: '/infra/category/delete?id=' + id, + method: 'delete' + }) +} + +// 获得分类 +export function getCategory(id) { + return request({ + url: '/infra/category/get?id=' + id, + method: 'get' + }) +} + +// 获得分类列表 +export function getCategoryList(params) { + return request({ + url: '/infra/category/list', + method: 'get', + params + }) +} +// 导出分类 Excel +export function exportCategoryExcel(params) { + return request({ + url: '/infra/category/export-excel', + method: 'get', + params, + responseType: 'blob' + }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/sql/h2 new file mode 100644 index 000000000..4141766cf --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/sql/h2 @@ -0,0 +1,10 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_category" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" bigint NOT NULL, + PRIMARY KEY ("id") +) COMMENT '分类表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_category"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/sql/sql new file mode 100644 index 000000000..81409488a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '分类管理', '', 2, 0, 888, + 'category', '', 'infra/demo/index', 0, 'InfraCategory' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类查询', 'infra:category:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类创建', 'infra:category:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类更新', 'infra:category:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类删除', 'infra:category:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类导出', 'infra:category:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/vue/CategoryForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/vue/CategoryForm new file mode 100644 index 000000000..7fa06e8cf --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/vue/CategoryForm @@ -0,0 +1,130 @@ + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/vue/index new file mode 100644 index 000000000..88da68254 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/vue/index @@ -0,0 +1,161 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/xml/InfraCategoryMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/xml/InfraCategoryMapper new file mode 100644 index 000000000..025ac8507 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue2_tree/xml/InfraCategoryMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/assert.json new file mode 100644 index 000000000..0937ba914 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/assert.json @@ -0,0 +1,73 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue" +}, { + "contentPath" : "vue/StudentContactForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue" +}, { + "contentPath" : "vue/StudentTeacherForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue" +}, { + "contentPath" : "vue/StudentContactList", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue" +}, { + "contentPath" : "vue/StudentTeacherList", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..5e64b117f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,6 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); +ErrorCode STUDENT_CONTACT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生联系人不存在"); +ErrorCode STUDENT_TEACHER_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任不存在"); +ErrorCode STUDENT_TEACHER_EXISTS = new ErrorCode(TODO 补充编号, "学生班主任已存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactDO new file mode 100644 index 000000000..17c668eaa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactMapper new file mode 100644 index 000000000..ca662d19c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentContactMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default PageResult selectPage(PageParam reqVO, Long studentId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(InfraStudentContactDO::getStudentId, studentId) + .orderByDesc(InfraStudentContactDO::getId)); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentController new file mode 100644 index 000000000..d6f20183d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentController @@ -0,0 +1,183 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/page") + @Operation(summary = "获得学生联系人分页") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactPage(PageParam pageReqVO, + @RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactPage(pageReqVO, studentId)); + } + + @PostMapping("/student-contact/create") + @Operation(summary = "创建学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) { + return success(studentService.createStudentContact(studentContact)); + } + + @PutMapping("/student-contact/update") + @Operation(summary = "更新学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudentContact(@Valid @RequestBody InfraStudentContactDO studentContact) { + studentService.updateStudentContact(studentContact); + return success(true); + } + + @DeleteMapping("/student-contact/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除学生联系人") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentContact(@RequestParam("id") Long id) { + studentService.deleteStudentContact(id); + return success(true); + } + + @GetMapping("/student-contact/get") + @Operation(summary = "获得学生联系人") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentContact(@RequestParam("id") Long id) { + return success(studentService.getStudentContact(id)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/page") + @Operation(summary = "获得学生班主任分页") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentTeacherPage(PageParam pageReqVO, + @RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherPage(pageReqVO, studentId)); + } + + @PostMapping("/student-teacher/create") + @Operation(summary = "创建学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) { + return success(studentService.createStudentTeacher(studentTeacher)); + } + + @PutMapping("/student-teacher/update") + @Operation(summary = "更新学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudentTeacher(@Valid @RequestBody InfraStudentTeacherDO studentTeacher) { + studentService.updateStudentTeacher(studentTeacher); + return success(true); + } + + @DeleteMapping("/student-teacher/delete") + @Parameter(name = "id", description = "编号", required = true) + @Operation(summary = "删除学生班主任") + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudentTeacher(@RequestParam("id") Long id) { + studentService.deleteStudentTeacher(id); + return success(true); + } + + @GetMapping("/student-teacher/get") + @Operation(summary = "获得学生班主任") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacher(@RequestParam("id") Long id) { + return success(studentService.getStudentTeacher(id)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..eaadf7432 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentSaveReqVO @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentService new file mode 100644 index 000000000..7df090d7f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentService @@ -0,0 +1,139 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人分页 + * + * @param pageReqVO 分页查询 + * @param studentId 学生编号 + * @return 学生联系人分页 + */ + PageResult getStudentContactPage(PageParam pageReqVO, Long studentId); + + /** + * 创建学生联系人 + * + * @param studentContact 创建信息 + * @return 编号 + */ + Long createStudentContact(@Valid InfraStudentContactDO studentContact); + + /** + * 更新学生联系人 + * + * @param studentContact 更新信息 + */ + void updateStudentContact(@Valid InfraStudentContactDO studentContact); + + /** + * 删除学生联系人 + * + * @param id 编号 + */ + void deleteStudentContact(Long id); + + /** + * 获得学生联系人 + * + * @param id 编号 + * @return 学生联系人 + */ + InfraStudentContactDO getStudentContact(Long id); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任分页 + * + * @param pageReqVO 分页查询 + * @param studentId 学生编号 + * @return 学生班主任分页 + */ + PageResult getStudentTeacherPage(PageParam pageReqVO, Long studentId); + + /** + * 创建学生班主任 + * + * @param studentTeacher 创建信息 + * @return 编号 + */ + Long createStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher); + + /** + * 更新学生班主任 + * + * @param studentTeacher 更新信息 + */ + void updateStudentTeacher(@Valid InfraStudentTeacherDO studentTeacher); + + /** + * 删除学生班主任 + * + * @param id 编号 + */ + void deleteStudentTeacher(Long id); + + /** + * 获得学生班主任 + * + * @param id 编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacher(Long id); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImpl new file mode 100644 index 000000000..793b2dd22 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImpl @@ -0,0 +1,180 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + // 返回 + return student.getId(); + } + + @Override + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public PageResult getStudentContactPage(PageParam pageReqVO, Long studentId) { + return studentContactMapper.selectPage(pageReqVO, studentId); + } + + @Override + public Long createStudentContact(InfraStudentContactDO studentContact) { + studentContactMapper.insert(studentContact); + return studentContact.getId(); + } + + @Override + public void updateStudentContact(InfraStudentContactDO studentContact) { + // 校验存在 + validateStudentContactExists(studentContact.getId()); + // 更新 + studentContactMapper.updateById(studentContact); + } + + @Override + public void deleteStudentContact(Long id) { + // 校验存在 + validateStudentContactExists(id); + // 删除 + studentContactMapper.deleteById(id); + } + + @Override + public InfraStudentContactDO getStudentContact(Long id) { + return studentContactMapper.selectById(id); + } + + private void validateStudentContactExists(Long id) { + if (studentContactMapper.selectById(id) == null) { + throw exception(STUDENT_CONTACT_NOT_EXISTS); + } + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public PageResult getStudentTeacherPage(PageParam pageReqVO, Long studentId) { + return studentTeacherMapper.selectPage(pageReqVO, studentId); + } + + @Override + public Long createStudentTeacher(InfraStudentTeacherDO studentTeacher) { + // 校验是否已经存在 + if (studentTeacherMapper.selectByStudentId(studentTeacher.getStudentId()) != null) { + throw exception(STUDENT_TEACHER_EXISTS); + } + // 插入 + studentTeacherMapper.insert(studentTeacher); + return studentTeacher.getId(); + } + + @Override + public void updateStudentTeacher(InfraStudentTeacherDO studentTeacher) { + // 校验存在 + validateStudentTeacherExists(studentTeacher.getId()); + // 更新 + studentTeacherMapper.updateById(studentTeacher); + } + + @Override + public void deleteStudentTeacher(Long id) { + // 校验存在 + validateStudentTeacherExists(id); + // 删除 + studentTeacherMapper.deleteById(id); + } + + @Override + public InfraStudentTeacherDO getStudentTeacher(Long id) { + return studentTeacherMapper.selectById(id); + } + + private void validateStudentTeacherExists(Long id) { + if (studentTeacherMapper.selectById(id) == null) { + throw exception(STUDENT_TEACHER_NOT_EXISTS); + } + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherDO new file mode 100644 index 000000000..c19cf9fab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherMapper new file mode 100644 index 000000000..994212dab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/java/InfraStudentTeacherMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default PageResult selectPage(PageParam reqVO, Long studentId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(InfraStudentTeacherDO::getStudentId, studentId) + .orderByDesc(InfraStudentTeacherDO::getId)); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/sql new file mode 100644 index 000000000..4551d0de6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/ts/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/ts/index new file mode 100644 index 000000000..41eb94dd6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/ts/index @@ -0,0 +1,95 @@ +import request from '@/config/axios' + +export interface StudentVO { + id: number + name: string + description: string + birthday: Date + sex: number + enabled: boolean + avatar: string + video: string + memo: string +} + +// 查询学生分页 +export const getStudentPage = async (params) => { + return await request.get({ url: `/infra/student/page`, params }) +} + +// 查询学生详情 +export const getStudent = async (id: number) => { + return await request.get({ url: `/infra/student/get?id=` + id }) +} + +// 新增学生 +export const createStudent = async (data: StudentVO) => { + return await request.post({ url: `/infra/student/create`, data }) +} + +// 修改学生 +export const updateStudent = async (data: StudentVO) => { + return await request.put({ url: `/infra/student/update`, data }) +} + +// 删除学生 +export const deleteStudent = async (id: number) => { + return await request.delete({ url: `/infra/student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportStudent = async (params) => { + return await request.download({ url: `/infra/student/export-excel`, params }) +} + +// ==================== 子表(学生联系人) ==================== + +// 获得学生联系人分页 +export const getStudentContactPage = async (params) => { + return await request.get({ url: `/infra/student/student-contact/page`, params }) +} +// 新增学生联系人 +export const createStudentContact = async (data) => { + return await request.post({ url: `/infra/student/student-contact/create`, data }) +} + +// 修改学生联系人 +export const updateStudentContact = async (data) => { + return await request.put({ url: `/infra/student/student-contact/update`, data }) +} + +// 删除学生联系人 +export const deleteStudentContact = async (id: number) => { + return await request.delete({ url: `/infra/student/student-contact/delete?id=` + id }) +} + +// 获得学生联系人 +export const getStudentContact = async (id: number) => { + return await request.get({ url: `/infra/student/student-contact/get?id=` + id }) +} + +// ==================== 子表(学生班主任) ==================== + +// 获得学生班主任分页 +export const getStudentTeacherPage = async (params) => { + return await request.get({ url: `/infra/student/student-teacher/page`, params }) +} +// 新增学生班主任 +export const createStudentTeacher = async (data) => { + return await request.post({ url: `/infra/student/student-teacher/create`, data }) +} + +// 修改学生班主任 +export const updateStudentTeacher = async (data) => { + return await request.put({ url: `/infra/student/student-teacher/update`, data }) +} + +// 删除学生班主任 +export const deleteStudentTeacher = async (id: number) => { + return await request.delete({ url: `/infra/student/student-teacher/delete?id=` + id }) +} + +// 获得学生班主任 +export const getStudentTeacher = async (id: number) => { + return await request.get({ url: `/infra/student/student-teacher/get?id=` + id }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactForm new file mode 100644 index 000000000..3c98b67fa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactForm @@ -0,0 +1,155 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactList new file mode 100644 index 000000000..eada66a75 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentContactList @@ -0,0 +1,146 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentForm new file mode 100644 index 000000000..2e3fc0387 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentForm @@ -0,0 +1,152 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherForm new file mode 100644 index 000000000..242fd57f5 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherForm @@ -0,0 +1,155 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherList new file mode 100644 index 000000000..1eba0a3d0 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/StudentTeacherList @@ -0,0 +1,146 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/index new file mode 100644 index 000000000..f1b5a2724 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/vue/index @@ -0,0 +1,278 @@ + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/xml/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/xml/InfraStudentMapper new file mode 100644 index 000000000..155aa5c27 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_erp/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/assert.json new file mode 100644 index 000000000..0937ba914 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/assert.json @@ -0,0 +1,73 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue" +}, { + "contentPath" : "vue/StudentContactForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue" +}, { + "contentPath" : "vue/StudentTeacherForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue" +}, { + "contentPath" : "vue/StudentContactList", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactList.vue" +}, { + "contentPath" : "vue/StudentTeacherList", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherList.vue" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..72162a859 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactDO new file mode 100644 index 000000000..17c668eaa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactMapper new file mode 100644 index 000000000..35bbd53c2 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentContactMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default List selectListByStudentId(Long studentId) { + return selectList(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentController new file mode 100644 index 000000000..b9a587b44 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentController @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/list-by-student-id") + @Operation(summary = "获得学生联系人列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactListByStudentId(studentId)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/get-by-student-id") + @Operation(summary = "获得学生班主任") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..faa491dfb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentSaveReqVO @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + + @Schema(description = "学生联系人列表") + private List studentContacts; + + @Schema(description = "学生班主任") + private InfraStudentTeacherDO studentTeacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentService new file mode 100644 index 000000000..afa7d22eb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentService @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人列表 + * + * @param studentId 学生编号 + * @return 学生联系人列表 + */ + List getStudentContactListByStudentId(Long studentId); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任 + * + * @param studentId 学生编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImpl new file mode 100644 index 000000000..c57cba613 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImpl @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + // 插入子表 + createStudentContactList(student.getId(), createReqVO.getStudentContacts()); + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher()); + // 返回 + return student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + + // 更新子表 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts()); + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public List getStudentContactListByStudentId(Long studentId) { + return studentContactMapper.selectListByStudentId(studentId); + } + + private void createStudentContactList(Long studentId, List list) { + list.forEach(o -> o.setStudentId(studentId)); + studentContactMapper.insertBatch(list); + } + + private void updateStudentContactList(Long studentId, List list) { + deleteStudentContactByStudentId(studentId); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createStudentContactList(studentId, list); + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) { + return studentTeacherMapper.selectByStudentId(studentId); + } + + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacherMapper.insert(studentTeacher); + } + + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 + studentTeacherMapper.insertOrUpdate(studentTeacher); + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherDO new file mode 100644 index 000000000..c19cf9fab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherMapper new file mode 100644 index 000000000..0521bbaf4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/java/InfraStudentTeacherMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/sql new file mode 100644 index 000000000..4551d0de6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/ts/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/ts/index new file mode 100644 index 000000000..6afca54c3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/ts/index @@ -0,0 +1,57 @@ +import request from '@/config/axios' + +export interface StudentVO { + id: number + name: string + description: string + birthday: Date + sex: number + enabled: boolean + avatar: string + video: string + memo: string +} + +// 查询学生分页 +export const getStudentPage = async (params) => { + return await request.get({ url: `/infra/student/page`, params }) +} + +// 查询学生详情 +export const getStudent = async (id: number) => { + return await request.get({ url: `/infra/student/get?id=` + id }) +} + +// 新增学生 +export const createStudent = async (data: StudentVO) => { + return await request.post({ url: `/infra/student/create`, data }) +} + +// 修改学生 +export const updateStudent = async (data: StudentVO) => { + return await request.put({ url: `/infra/student/update`, data }) +} + +// 删除学生 +export const deleteStudent = async (id: number) => { + return await request.delete({ url: `/infra/student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportStudent = async (params) => { + return await request.download({ url: `/infra/student/export-excel`, params }) +} + +// ==================== 子表(学生联系人) ==================== + +// 获得学生联系人列表 +export const getStudentContactListByStudentId = async (studentId) => { + return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId }) +} + +// ==================== 子表(学生班主任) ==================== + +// 获得学生班主任 +export const getStudentTeacherByStudentId = async (studentId) => { + return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactForm new file mode 100644 index 000000000..20f129e5b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactForm @@ -0,0 +1,174 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactList new file mode 100644 index 000000000..d0e89dac2 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentContactList @@ -0,0 +1,72 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentForm new file mode 100644 index 000000000..d77df42d9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentForm @@ -0,0 +1,184 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherForm new file mode 100644 index 000000000..6027db882 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherForm @@ -0,0 +1,122 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherList b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherList new file mode 100644 index 000000000..e510adcf4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/StudentTeacherList @@ -0,0 +1,76 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/index new file mode 100644 index 000000000..e50091add --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/vue/index @@ -0,0 +1,267 @@ + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/xml/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/xml/InfraStudentMapper new file mode 100644 index 000000000..155aa5c27 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_inner/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/assert.json new file mode 100644 index 000000000..60e7f4767 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/assert.json @@ -0,0 +1,67 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentContactDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentContactDO.java" +}, { + "contentPath" : "java/InfraStudentTeacherDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentTeacherDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "java/InfraStudentContactMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentContactMapper.java" +}, { + "contentPath" : "java/InfraStudentTeacherMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentTeacherMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue" +}, { + "contentPath" : "vue/StudentContactForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentContactForm.vue" +}, { + "contentPath" : "vue/StudentTeacherForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/components/StudentTeacherForm.vue" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..72162a859 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactDO new file mode 100644 index 000000000..17c668eaa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生联系人 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_contact") +@KeySequence("infra_student_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentContactDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactMapper new file mode 100644 index 000000000..35bbd53c2 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentContactMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentContactMapper extends BaseMapperX { + + default List selectListByStudentId(Long studentId) { + return selectList(InfraStudentContactDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentContactDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentController new file mode 100644 index 000000000..b9a587b44 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentController @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + + // ==================== 子表(学生联系人) ==================== + + @GetMapping("/student-contact/list-by-student-id") + @Operation(summary = "获得学生联系人列表") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentContactListByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentContactListByStudentId(studentId)); + } + + // ==================== 子表(学生班主任) ==================== + + @GetMapping("/student-teacher/get-by-student-id") + @Operation(summary = "获得学生班主任") + @Parameter(name = "studentId", description = "学生编号") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudentTeacherByStudentId(@RequestParam("studentId") Long studentId) { + return success(studentService.getStudentTeacherByStudentId(studentId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..faa491dfb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentSaveReqVO @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + + @Schema(description = "学生联系人列表") + private List studentContacts; + + @Schema(description = "学生班主任") + private InfraStudentTeacherDO studentTeacher; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentService new file mode 100644 index 000000000..afa7d22eb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentService @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + + // ==================== 子表(学生联系人) ==================== + + /** + * 获得学生联系人列表 + * + * @param studentId 学生编号 + * @return 学生联系人列表 + */ + List getStudentContactListByStudentId(Long studentId); + + // ==================== 子表(学生班主任) ==================== + + /** + * 获得学生班主任 + * + * @param studentId 学生编号 + * @return 学生班主任 + */ + InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImpl new file mode 100644 index 000000000..c57cba613 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImpl @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentContactDO; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentContactMapper; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentTeacherMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + @Resource + private InfraStudentContactMapper studentContactMapper; + @Resource + private InfraStudentTeacherMapper studentTeacherMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + + // 插入子表 + createStudentContactList(student.getId(), createReqVO.getStudentContacts()); + createStudentTeacher(student.getId(), createReqVO.getStudentTeacher()); + // 返回 + return student.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + + // 更新子表 + updateStudentContactList(updateReqVO.getId(), updateReqVO.getStudentContacts()); + updateStudentTeacher(updateReqVO.getId(), updateReqVO.getStudentTeacher()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + + // 删除子表 + deleteStudentContactByStudentId(id); + deleteStudentTeacherByStudentId(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + + // ==================== 子表(学生联系人) ==================== + + @Override + public List getStudentContactListByStudentId(Long studentId) { + return studentContactMapper.selectListByStudentId(studentId); + } + + private void createStudentContactList(Long studentId, List list) { + list.forEach(o -> o.setStudentId(studentId)); + studentContactMapper.insertBatch(list); + } + + private void updateStudentContactList(Long studentId, List list) { + deleteStudentContactByStudentId(studentId); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createStudentContactList(studentId, list); + } + + private void deleteStudentContactByStudentId(Long studentId) { + studentContactMapper.deleteByStudentId(studentId); + } + + // ==================== 子表(学生班主任) ==================== + + @Override + public InfraStudentTeacherDO getStudentTeacherByStudentId(Long studentId) { + return studentTeacherMapper.selectByStudentId(studentId); + } + + private void createStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacherMapper.insert(studentTeacher); + } + + private void updateStudentTeacher(Long studentId, InfraStudentTeacherDO studentTeacher) { + if (studentTeacher == null) { + return; + } + studentTeacher.setStudentId(studentId); + studentTeacher.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 + studentTeacherMapper.insertOrUpdate(studentTeacher); + } + + private void deleteStudentTeacherByStudentId(Long studentId) { + studentTeacherMapper.deleteByStudentId(studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherDO new file mode 100644 index 000000000..c19cf9fab --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherDO @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生班主任 DO + * + * @author 芋道源码 + */ +@TableName("infra_student_teacher") +@KeySequence("infra_student_teacher_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentTeacherDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 学生编号 + */ + private Long studentId; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherMapper new file mode 100644 index 000000000..0521bbaf4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/java/InfraStudentTeacherMapper @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentTeacherDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 学生班主任 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentTeacherMapper extends BaseMapperX { + + default InfraStudentTeacherDO selectByStudentId(Long studentId) { + return selectOne(InfraStudentTeacherDO::getStudentId, studentId); + } + + default int deleteByStudentId(Long studentId) { + return delete(InfraStudentTeacherDO::getStudentId, studentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/sql new file mode 100644 index 000000000..4551d0de6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/ts/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/ts/index new file mode 100644 index 000000000..6afca54c3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/ts/index @@ -0,0 +1,57 @@ +import request from '@/config/axios' + +export interface StudentVO { + id: number + name: string + description: string + birthday: Date + sex: number + enabled: boolean + avatar: string + video: string + memo: string +} + +// 查询学生分页 +export const getStudentPage = async (params) => { + return await request.get({ url: `/infra/student/page`, params }) +} + +// 查询学生详情 +export const getStudent = async (id: number) => { + return await request.get({ url: `/infra/student/get?id=` + id }) +} + +// 新增学生 +export const createStudent = async (data: StudentVO) => { + return await request.post({ url: `/infra/student/create`, data }) +} + +// 修改学生 +export const updateStudent = async (data: StudentVO) => { + return await request.put({ url: `/infra/student/update`, data }) +} + +// 删除学生 +export const deleteStudent = async (id: number) => { + return await request.delete({ url: `/infra/student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportStudent = async (params) => { + return await request.download({ url: `/infra/student/export-excel`, params }) +} + +// ==================== 子表(学生联系人) ==================== + +// 获得学生联系人列表 +export const getStudentContactListByStudentId = async (studentId) => { + return await request.get({ url: `/infra/student/student-contact/list-by-student-id?studentId=` + studentId }) +} + +// ==================== 子表(学生班主任) ==================== + +// 获得学生班主任 +export const getStudentTeacherByStudentId = async (studentId) => { + return await request.get({ url: `/infra/student/student-teacher/get-by-student-id?studentId=` + studentId }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentContactForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentContactForm new file mode 100644 index 000000000..20f129e5b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentContactForm @@ -0,0 +1,174 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentForm new file mode 100644 index 000000000..d77df42d9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentForm @@ -0,0 +1,184 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentTeacherForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentTeacherForm new file mode 100644 index 000000000..6027db882 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/StudentTeacherForm @@ -0,0 +1,122 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/index new file mode 100644 index 000000000..c79755215 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/vue/index @@ -0,0 +1,252 @@ + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/xml/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/xml/InfraStudentMapper new file mode 100644 index 000000000..155aa5c27 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_master_normal/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/assert.json new file mode 100644 index 000000000..5a0eebdeb --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/assert.json @@ -0,0 +1,49 @@ +[ { + "contentPath" : "java/InfraStudentPageReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentPageReqVO.java" +}, { + "contentPath" : "java/InfraStudentRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentRespVO.java" +}, { + "contentPath" : "java/InfraStudentSaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraStudentSaveReqVO.java" +}, { + "contentPath" : "java/InfraStudentController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraStudentController.java" +}, { + "contentPath" : "java/InfraStudentDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraStudentDO.java" +}, { + "contentPath" : "java/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraStudentMapper.java" +}, { + "contentPath" : "xml/InfraStudentMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraStudentMapper.xml" +}, { + "contentPath" : "java/InfraStudentServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImpl.java" +}, { + "contentPath" : "java/InfraStudentService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentService.java" +}, { + "contentPath" : "java/InfraStudentServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraStudentServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue" +}, { + "contentPath" : "vue/StudentForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/StudentForm.vue" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..72162a859 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 学生 TODO 补充编号 ========== +ErrorCode STUDENT_NOT_EXISTS = new ErrorCode(TODO 补充编号, "学生不存在"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentController new file mode 100644 index 000000000..3796982c4 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentController @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraStudentService; + +@Tag(name = "管理后台 - 学生") +@RestController +@RequestMapping("/infra/student") +@Validated +public class InfraStudentController { + + @Resource + private InfraStudentService studentService; + + @PostMapping("/create") + @Operation(summary = "创建学生") + @PreAuthorize("@ss.hasPermission('infra:student:create')") + public CommonResult createStudent(@Valid @RequestBody InfraStudentSaveReqVO createReqVO) { + return success(studentService.createStudent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新学生") + @PreAuthorize("@ss.hasPermission('infra:student:update')") + public CommonResult updateStudent(@Valid @RequestBody InfraStudentSaveReqVO updateReqVO) { + studentService.updateStudent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除学生") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:student:delete')") + public CommonResult deleteStudent(@RequestParam("id") Long id) { + studentService.deleteStudent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得学生") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult getStudent(@RequestParam("id") Long id) { + InfraStudentDO student = studentService.getStudent(id); + return success(BeanUtils.toBean(student, InfraStudentRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得学生分页") + @PreAuthorize("@ss.hasPermission('infra:student:query')") + public CommonResult> getStudentPage(@Valid InfraStudentPageReqVO pageReqVO) { + PageResult pageResult = studentService.getStudentPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, InfraStudentRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出学生 Excel") + @PreAuthorize("@ss.hasPermission('infra:student:export')") + @OperateLog(type = EXPORT) + public void exportStudentExcel(@Valid InfraStudentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = studentService.getStudentPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "学生.xls", "数据", InfraStudentRespVO.class, + BeanUtils.toBean(list, InfraStudentRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentDO new file mode 100644 index 000000000..b0d4bd216 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentDO @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 学生 DO + * + * @author 芋道源码 + */ +@TableName("infra_student") +@KeySequence("infra_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraStudentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 简介 + */ + private String description; + /** + * 出生日期 + */ + private LocalDateTime birthday; + /** + * 性别 + * + * 枚举 {@link TODO system_user_sex 对应的类} + */ + private Integer sex; + /** + * 是否有效 + * + * 枚举 {@link TODO infra_boolean_string 对应的类} + */ + private Boolean enabled; + /** + * 头像 + */ + private String avatar; + /** + * 附件 + */ + private String video; + /** + * 备注 + */ + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentMapper new file mode 100644 index 000000000..34e70a082 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentMapper @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 学生 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraStudentMapper extends BaseMapperX { + + default PageResult selectPage(InfraStudentPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(InfraStudentDO::getName, reqVO.getName()) + .eqIfPresent(InfraStudentDO::getBirthday, reqVO.getBirthday()) + .eqIfPresent(InfraStudentDO::getSex, reqVO.getSex()) + .eqIfPresent(InfraStudentDO::getEnabled, reqVO.getEnabled()) + .betweenIfPresent(InfraStudentDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(InfraStudentDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentPageReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentPageReqVO new file mode 100644 index 000000000..41a373012 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentPageReqVO @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 学生分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfraStudentPageReqVO extends PageParam { + + @Schema(description = "名字", example = "芋头") + private String name; + + @Schema(description = "出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", example = "1") + private Integer sex; + + @Schema(description = "是否有效", example = "true") + private Boolean enabled; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO new file mode 100644 index 000000000..c41a5501f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - 学生 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraStudentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @ExcelProperty("简介") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出生日期") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "性别", converter = DictConvert.class) + @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty(value = "是否有效", converter = DictConvert.class) + @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @ExcelProperty("头像") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @ExcelProperty("附件") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @ExcelProperty("备注") + private String memo; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentSaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentSaveReqVO new file mode 100644 index 000000000..43e7f147d --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentSaveReqVO @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 学生新增/修改 Request VO") +@Data +public class InfraStudentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是介绍") + @NotEmpty(message = "简介不能为空") + private String description; + + @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出生日期不能为空") + private LocalDateTime birthday; + + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "性别不能为空") + private Integer sex; + + @Schema(description = "是否有效", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否有效不能为空") + private Boolean enabled; + + @Schema(description = "头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + @NotEmpty(message = "头像不能为空") + private String avatar; + + @Schema(description = "附件", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.mp4") + @NotEmpty(message = "附件不能为空") + private String video; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是备注") + @NotEmpty(message = "备注不能为空") + private String memo; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentService new file mode 100644 index 000000000..c4a0e1792 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentService @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 学生 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraStudentService { + + /** + * 创建学生 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStudent(@Valid InfraStudentSaveReqVO createReqVO); + + /** + * 更新学生 + * + * @param updateReqVO 更新信息 + */ + void updateStudent(@Valid InfraStudentSaveReqVO updateReqVO); + + /** + * 删除学生 + * + * @param id 编号 + */ + void deleteStudent(Long id); + + /** + * 获得学生 + * + * @param id 编号 + * @return 学生 + */ + InfraStudentDO getStudent(Long id); + + /** + * 获得学生分页 + * + * @param pageReqVO 分页查询 + * @return 学生分页 + */ + PageResult getStudentPage(InfraStudentPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentServiceImpl new file mode 100644 index 000000000..2292a66f3 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentServiceImpl @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 学生 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraStudentServiceImpl implements InfraStudentService { + + @Resource + private InfraStudentMapper studentMapper; + + @Override + public Long createStudent(InfraStudentSaveReqVO createReqVO) { + // 插入 + InfraStudentDO student = BeanUtils.toBean(createReqVO, InfraStudentDO.class); + studentMapper.insert(student); + // 返回 + return student.getId(); + } + + @Override + public void updateStudent(InfraStudentSaveReqVO updateReqVO) { + // 校验存在 + validateStudentExists(updateReqVO.getId()); + // 更新 + InfraStudentDO updateObj = BeanUtils.toBean(updateReqVO, InfraStudentDO.class); + studentMapper.updateById(updateObj); + } + + @Override + public void deleteStudent(Long id) { + // 校验存在 + validateStudentExists(id); + // 删除 + studentMapper.deleteById(id); + } + + private void validateStudentExists(Long id) { + if (studentMapper.selectById(id) == null) { + throw exception(STUDENT_NOT_EXISTS); + } + } + + @Override + public InfraStudentDO getStudent(Long id) { + return studentMapper.selectById(id); + } + + @Override + public PageResult getStudentPage(InfraStudentPageReqVO pageReqVO) { + return studentMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentServiceImplTest new file mode 100644 index 000000000..b5f4bf0ff --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/java/InfraStudentServiceImplTest @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraStudentDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraStudentMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraStudentServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraStudentServiceImpl.class) +public class InfraStudentServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraStudentServiceImpl studentService; + + @Resource + private InfraStudentMapper studentMapper; + + @Test + public void testCreateStudent_success() { + // 准备参数 + InfraStudentSaveReqVO createReqVO = randomPojo(InfraStudentSaveReqVO.class).setId(null); + + // 调用 + Long studentId = studentService.createStudent(createReqVO); + // 断言 + assertNotNull(studentId); + // 校验记录的属性是否正确 + InfraStudentDO student = studentMapper.selectById(studentId); + assertPojoEquals(createReqVO, student, "id"); + } + + @Test + public void testUpdateStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class, o -> { + o.setId(dbStudent.getId()); // 设置更新的 ID + }); + + // 调用 + studentService.updateStudent(updateReqVO); + // 校验是否更新正确 + InfraStudentDO student = studentMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, student); + } + + @Test + public void testUpdateStudent_notExists() { + // 准备参数 + InfraStudentSaveReqVO updateReqVO = randomPojo(InfraStudentSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.updateStudent(updateReqVO), STUDENT_NOT_EXISTS); + } + + @Test + public void testDeleteStudent_success() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class); + studentMapper.insert(dbStudent);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbStudent.getId(); + + // 调用 + studentService.deleteStudent(id); + // 校验数据不存在了 + assertNull(studentMapper.selectById(id)); + } + + @Test + public void testDeleteStudent_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> studentService.deleteStudent(id), STUDENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetStudentPage() { + // mock 数据 + InfraStudentDO dbStudent = randomPojo(InfraStudentDO.class, o -> { // 等会查询到 + o.setName(null); + o.setBirthday(null); + o.setSex(null); + o.setEnabled(null); + o.setCreateTime(null); + }); + studentMapper.insert(dbStudent); + // 测试 name 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setName(null))); + // 测试 birthday 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setBirthday(null))); + // 测试 sex 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setSex(null))); + // 测试 enabled 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setEnabled(null))); + // 测试 createTime 不匹配 + studentMapper.insert(cloneIgnoreId(dbStudent, o -> o.setCreateTime(null))); + // 准备参数 + InfraStudentPageReqVO reqVO = new InfraStudentPageReqVO(); + reqVO.setName(null); + reqVO.setBirthday(null); + reqVO.setSex(null); + reqVO.setEnabled(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = studentService.getStudentPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbStudent, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/sql/h2 new file mode 100644 index 000000000..6c1875f60 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/sql/h2 @@ -0,0 +1,17 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_student" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" varchar NOT NULL, + "birthday" varchar NOT NULL, + "sex" int NOT NULL, + "enabled" bit NOT NULL, + "avatar" varchar NOT NULL, + "video" varchar NOT NULL, + "memo" varchar NOT NULL, + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY ("id") +) COMMENT '学生表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_student"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/sql/sql new file mode 100644 index 000000000..4551d0de6 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '学生管理', '', 2, 0, 888, + 'student', '', 'infra/demo/index', 0, 'InfraStudent' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生查询', 'infra:student:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生创建', 'infra:student:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生更新', 'infra:student:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生删除', 'infra:student:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '学生导出', 'infra:student:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/ts/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/ts/index new file mode 100644 index 000000000..1ac86e52f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/ts/index @@ -0,0 +1,43 @@ +import request from '@/config/axios' + +export interface StudentVO { + id: number + name: string + description: string + birthday: Date + sex: number + enabled: boolean + avatar: string + video: string + memo: string +} + +// 查询学生分页 +export const getStudentPage = async (params) => { + return await request.get({ url: `/infra/student/page`, params }) +} + +// 查询学生详情 +export const getStudent = async (id: number) => { + return await request.get({ url: `/infra/student/get?id=` + id }) +} + +// 新增学生 +export const createStudent = async (data: StudentVO) => { + return await request.post({ url: `/infra/student/create`, data }) +} + +// 修改学生 +export const updateStudent = async (data: StudentVO) => { + return await request.put({ url: `/infra/student/update`, data }) +} + +// 删除学生 +export const deleteStudent = async (id: number) => { + return await request.delete({ url: `/infra/student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportStudent = async (params) => { + return await request.download({ url: `/infra/student/export-excel`, params }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/vue/StudentForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/vue/StudentForm new file mode 100644 index 000000000..2e3fc0387 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/vue/StudentForm @@ -0,0 +1,152 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/vue/index new file mode 100644 index 000000000..c79755215 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/vue/index @@ -0,0 +1,252 @@ + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/xml/InfraStudentMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/xml/InfraStudentMapper new file mode 100644 index 000000000..155aa5c27 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_one/xml/InfraStudentMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/assert.json b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/assert.json new file mode 100644 index 000000000..357df0080 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/assert.json @@ -0,0 +1,49 @@ +[ { + "contentPath" : "java/InfraCategoryListReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategoryListReqVO.java" +}, { + "contentPath" : "java/InfraCategoryRespVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategoryRespVO.java" +}, { + "contentPath" : "java/InfraCategorySaveReqVO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/vo/InfraCategorySaveReqVO.java" +}, { + "contentPath" : "java/InfraCategoryController", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/InfraCategoryController.java" +}, { + "contentPath" : "java/InfraCategoryDO", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/dataobject/demo/InfraCategoryDO.java" +}, { + "contentPath" : "java/InfraCategoryMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/demo/InfraCategoryMapper.java" +}, { + "contentPath" : "xml/InfraCategoryMapper", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/resources/mapper/demo/InfraCategoryMapper.xml" +}, { + "contentPath" : "java/InfraCategoryServiceImpl", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryServiceImpl.java" +}, { + "contentPath" : "java/InfraCategoryService", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryService.java" +}, { + "contentPath" : "java/InfraCategoryServiceImplTest", + "filePath" : "yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/demo/InfraCategoryServiceImplTest.java" +}, { + "contentPath" : "java/ErrorCodeConstants_手动操作", + "filePath" : "yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants_手动操作.java" +}, { + "contentPath" : "sql/sql", + "filePath" : "sql/sql.sql" +}, { + "contentPath" : "sql/h2", + "filePath" : "sql/h2.sql" +}, { + "contentPath" : "vue/index", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/index.vue" +}, { + "contentPath" : "vue/CategoryForm", + "filePath" : "yudao-ui-admin-vue3/src/views/infra/demo/CategoryForm.vue" +}, { + "contentPath" : "ts/index", + "filePath" : "yudao-ui-admin-vue3/src/api/infra/demo/index.ts" +} ] \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/ErrorCodeConstants_手动操作 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/ErrorCodeConstants_手动操作 new file mode 100644 index 000000000..a8626bdda --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/ErrorCodeConstants_手动操作 @@ -0,0 +1,8 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-infra-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 分类 TODO 补充编号 ========== +ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(TODO 补充编号, "分类不存在"); +ErrorCode CATEGORY_EXITS_CHILDREN = new ErrorCode(TODO 补充编号, "存在存在子分类,无法删除"); +ErrorCode CATEGORY_PARENT_NOT_EXITS = new ErrorCode(TODO 补充编号,"父级分类不存在"); +ErrorCode CATEGORY_PARENT_ERROR = new ErrorCode(TODO 补充编号, "不能设置自己为父分类"); +ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(TODO 补充编号, "已经存在该名字的分类"); +ErrorCode CATEGORY_PARENT_IS_CHILD = new ErrorCode(TODO 补充编号, "不能设置自己的子InfraCategory为父InfraCategory"); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryController b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryController new file mode 100644 index 000000000..a7b2f8163 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryController @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo; + +import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import javax.validation.constraints.*; +import javax.validation.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.module.infra.service.demo.InfraCategoryService; + +@Tag(name = "管理后台 - 分类") +@RestController +@RequestMapping("/infra/category") +@Validated +public class InfraCategoryController { + + @Resource + private InfraCategoryService categoryService; + + @PostMapping("/create") + @Operation(summary = "创建分类") + @PreAuthorize("@ss.hasPermission('infra:category:create')") + public CommonResult createCategory(@Valid @RequestBody InfraCategorySaveReqVO createReqVO) { + return success(categoryService.createCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新分类") + @PreAuthorize("@ss.hasPermission('infra:category:update')") + public CommonResult updateCategory(@Valid @RequestBody InfraCategorySaveReqVO updateReqVO) { + categoryService.updateCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('infra:category:delete')") + public CommonResult deleteCategory(@RequestParam("id") Long id) { + categoryService.deleteCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('infra:category:query')") + public CommonResult getCategory(@RequestParam("id") Long id) { + InfraCategoryDO category = categoryService.getCategory(id); + return success(BeanUtils.toBean(category, InfraCategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得分类列表") + @PreAuthorize("@ss.hasPermission('infra:category:query')") + public CommonResult> getCategoryList(@Valid InfraCategoryListReqVO listReqVO) { + List list = categoryService.getCategoryList(listReqVO); + return success(BeanUtils.toBean(list, InfraCategoryRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出分类 Excel") + @PreAuthorize("@ss.hasPermission('infra:category:export')") + @OperateLog(type = EXPORT) + public void exportCategoryExcel(@Valid InfraCategoryListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = categoryService.getCategoryList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "分类.xls", "数据", InfraCategoryRespVO.class, + BeanUtils.toBean(list, InfraCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryDO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryDO new file mode 100644 index 000000000..9bf21c08b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryDO @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.infra.dal.dataobject.demo; + +import lombok.*; +import java.util.*; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 分类 DO + * + * @author 芋道源码 + */ +@TableName("infra_category") +@KeySequence("infra_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfraCategoryDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 名字 + */ + private String name; + /** + * 父编号 + */ + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryListReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryListReqVO new file mode 100644 index 000000000..e5c6f181f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryListReqVO @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - 分类列表 Request VO") +@Data +public class InfraCategoryListReqVO { + + @Schema(description = "名字", example = "芋头") + private String name; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryMapper new file mode 100644 index 000000000..9dadbf1d9 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryMapper @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.infra.dal.mysql.demo; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; + +/** + * 分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface InfraCategoryMapper extends BaseMapperX { + + default List selectList(InfraCategoryListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(InfraCategoryDO::getName, reqVO.getName()) + .orderByDesc(InfraCategoryDO::getId)); + } + + default InfraCategoryDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(InfraCategoryDO::getParentId, parentId, InfraCategoryDO::getName, name); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(InfraCategoryDO::getParentId, parentId); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO new file mode 100644 index 000000000..6325d866c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class InfraCategoryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @ExcelProperty("名字") + private String name; + + @Schema(description = "父编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @ExcelProperty("父编号") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategorySaveReqVO b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategorySaveReqVO new file mode 100644 index 000000000..3c03b977f --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategorySaveReqVO @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; +import java.util.*; + +@Schema(description = "管理后台 - 分类新增/修改 Request VO") +@Data +public class InfraCategorySaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋头") + @NotEmpty(message = "名字不能为空") + private String name; + + @Schema(description = "父编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + @NotNull(message = "父编号不能为空") + private Long parentId; + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryService b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryService new file mode 100644 index 000000000..9d0ae1afa --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryService @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 分类 Service 接口 + * + * @author 芋道源码 + */ +public interface InfraCategoryService { + + /** + * 创建分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCategory(@Valid InfraCategorySaveReqVO createReqVO); + + /** + * 更新分类 + * + * @param updateReqVO 更新信息 + */ + void updateCategory(@Valid InfraCategorySaveReqVO updateReqVO); + + /** + * 删除分类 + * + * @param id 编号 + */ + void deleteCategory(Long id); + + /** + * 获得分类 + * + * @param id 编号 + * @return 分类 + */ + InfraCategoryDO getCategory(Long id); + + /** + * 获得分类列表 + * + * @param listReqVO 查询条件 + * @return 分类列表 + */ + List getCategoryList(InfraCategoryListReqVO listReqVO); + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryServiceImpl b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryServiceImpl new file mode 100644 index 000000000..351568b18 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryServiceImpl @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraCategoryMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; + +/** + * 分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class InfraCategoryServiceImpl implements InfraCategoryService { + + @Resource + private InfraCategoryMapper categoryMapper; + + @Override + public Long createCategory(InfraCategorySaveReqVO createReqVO) { + // 校验父编号的有效性 + validateParentCategory(null, createReqVO.getParentId()); + // 校验名字的唯一性 + validateCategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + InfraCategoryDO category = BeanUtils.toBean(createReqVO, InfraCategoryDO.class); + categoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateCategory(InfraCategorySaveReqVO updateReqVO) { + // 校验存在 + validateCategoryExists(updateReqVO.getId()); + // 校验父编号的有效性 + validateParentCategory(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验名字的唯一性 + validateCategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + InfraCategoryDO updateObj = BeanUtils.toBean(updateReqVO, InfraCategoryDO.class); + categoryMapper.updateById(updateObj); + } + + @Override + public void deleteCategory(Long id) { + // 校验存在 + validateCategoryExists(id); + // 校验是否有子分类 + if (categoryMapper.selectCountByParentId(id) > 0) { + throw exception(CATEGORY_EXITS_CHILDREN); + } + // 删除 + categoryMapper.deleteById(id); + } + + private void validateCategoryExists(Long id) { + if (categoryMapper.selectById(id) == null) { + throw exception(CATEGORY_NOT_EXISTS); + } + } + + private void validateParentCategory(Long id, Long parentId) { + if (parentId == null || CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父分类 + if (Objects.equals(id, parentId)) { + throw exception(CATEGORY_PARENT_ERROR); + } + // 2. 父分类不存在 + CategoryDO parentCategory = categoryMapper.selectById(parentId); + if (parentCategory == null) { + throw exception(CATEGORY_PARENT_NOT_EXITS); + } + // 3. 递归校验父分类,如果父分类是自己的子分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentCategory.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(CATEGORY_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父分类 + if (parentId == null || CategoryDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentCategory = categoryMapper.selectById(parentId); + if (parentCategory == null) { + break; + } + } + } + + private void validateCategoryNameUnique(Long id, Long parentId, String name) { + CategoryDO category = categoryMapper.selectByParentIdAndName(parentId, name); + if (category == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的分类 + if (id == null) { + throw exception(CATEGORY_NAME_DUPLICATE); + } + if (!Objects.equals(category.getId(), id)) { + throw exception(CATEGORY_NAME_DUPLICATE); + } + } + + @Override + public InfraCategoryDO getCategory(Long id) { + return categoryMapper.selectById(id); + } + + @Override + public List getCategoryList(InfraCategoryListReqVO listReqVO) { + return categoryMapper.selectList(listReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryServiceImplTest b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryServiceImplTest new file mode 100644 index 000000000..efb70fd33 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/java/InfraCategoryServiceImplTest @@ -0,0 +1,129 @@ +package cn.iocoder.yudao.module.infra.service.demo; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.infra.controller.admin.demo.vo.*; +import cn.iocoder.yudao.module.infra.dal.dataobject.demo.InfraCategoryDO; +import cn.iocoder.yudao.module.infra.dal.mysql.demo.InfraCategoryMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link InfraCategoryServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(InfraCategoryServiceImpl.class) +public class InfraCategoryServiceImplTest extends BaseDbUnitTest { + + @Resource + private InfraCategoryServiceImpl categoryService; + + @Resource + private InfraCategoryMapper categoryMapper; + + @Test + public void testCreateCategory_success() { + // 准备参数 + InfraCategorySaveReqVO createReqVO = randomPojo(InfraCategorySaveReqVO.class).setId(null); + + // 调用 + Long categoryId = categoryService.createCategory(createReqVO); + // 断言 + assertNotNull(categoryId); + // 校验记录的属性是否正确 + InfraCategoryDO category = categoryMapper.selectById(categoryId); + assertPojoEquals(createReqVO, category, "id"); + } + + @Test + public void testUpdateCategory_success() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + InfraCategorySaveReqVO updateReqVO = randomPojo(InfraCategorySaveReqVO.class, o -> { + o.setId(dbCategory.getId()); // 设置更新的 ID + }); + + // 调用 + categoryService.updateCategory(updateReqVO); + // 校验是否更新正确 + InfraCategoryDO category = categoryMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, category); + } + + @Test + public void testUpdateCategory_notExists() { + // 准备参数 + InfraCategorySaveReqVO updateReqVO = randomPojo(InfraCategorySaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.updateCategory(updateReqVO), CATEGORY_NOT_EXISTS); + } + + @Test + public void testDeleteCategory_success() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class); + categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCategory.getId(); + + // 调用 + categoryService.deleteCategory(id); + // 校验数据不存在了 + assertNull(categoryMapper.selectById(id)); + } + + @Test + public void testDeleteCategory_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCategoryList() { + // mock 数据 + InfraCategoryDO dbCategory = randomPojo(InfraCategoryDO.class, o -> { // 等会查询到 + o.setName(null); + }); + categoryMapper.insert(dbCategory); + // 测试 name 不匹配 + categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null))); + // 准备参数 + InfraCategoryListReqVO reqVO = new InfraCategoryListReqVO(); + reqVO.setName(null); + + // 调用 + List list = categoryService.getCategoryList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCategory, list.get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/sql/h2 b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/sql/h2 new file mode 100644 index 000000000..4141766cf --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/sql/h2 @@ -0,0 +1,10 @@ +-- 将该建表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/create_tables.sql 文件里 +CREATE TABLE IF NOT EXISTS "infra_category" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "description" bigint NOT NULL, + PRIMARY KEY ("id") +) COMMENT '分类表'; + +-- 将该删表 SQL 语句,添加到 yudao-module-infra-biz 模块的 test/resources/sql/clean.sql 文件里 +DELETE FROM "infra_category"; \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/sql/sql b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/sql/sql new file mode 100644 index 000000000..01bf99057 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/sql/sql @@ -0,0 +1,55 @@ +-- 菜单 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status, component_name +) +VALUES ( + '分类管理', '', 2, 0, 888, + 'category', '', 'infra/demo/index', 0, 'InfraCategory' +); + +-- 按钮父菜单ID +-- 暂时只支持 MySQL。如果你是 Oracle、PostgreSQL、SQLServer 的话,需要手动修改 @parentId 的部分的代码 +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类查询', 'infra:category:query', 3, 1, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类创建', 'infra:category:create', 3, 2, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类更新', 'infra:category:update', 3, 3, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类删除', 'infra:category:delete', 3, 4, @parentId, + '', '', '', 0 +); +INSERT INTO system_menu( + name, permission, type, sort, parent_id, + path, icon, component, status +) +VALUES ( + '分类导出', 'infra:category:export', 3, 5, @parentId, + '', '', '', 0 +); \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/ts/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/ts/index new file mode 100644 index 000000000..5f81a63d8 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/ts/index @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface CategoryVO { + id: number + name: string + parentId: number +} + +// 查询分类列表 +export const getCategoryList = async (params) => { + return await request.get({ url: `/infra/category/list`, params }) +} + +// 查询分类详情 +export const getCategory = async (id: number) => { + return await request.get({ url: `/infra/category/get?id=` + id }) +} + +// 新增分类 +export const createCategory = async (data: CategoryVO) => { + return await request.post({ url: `/infra/category/create`, data }) +} + +// 修改分类 +export const updateCategory = async (data: CategoryVO) => { + return await request.put({ url: `/infra/category/update`, data }) +} + +// 删除分类 +export const deleteCategory = async (id: number) => { + return await request.delete({ url: `/infra/category/delete?id=` + id }) +} + +// 导出分类 Excel +export const exportCategory = async (params) => { + return await request.download({ url: `/infra/category/export-excel`, params }) +} \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/vue/CategoryForm b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/vue/CategoryForm new file mode 100644 index 000000000..90143c8d8 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/vue/CategoryForm @@ -0,0 +1,114 @@ + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/vue/index b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/vue/index new file mode 100644 index 000000000..f8283bc70 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/vue/index @@ -0,0 +1,185 @@ + + + \ No newline at end of file diff --git a/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/xml/InfraCategoryMapper b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/xml/InfraCategoryMapper new file mode 100644 index 000000000..025ac8507 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/test/resources/codegen/vue3_tree/xml/InfraCategoryMapper @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-product-biz/pom.xml b/yudao-module-mall/yudao-module-product-biz/pom.xml index b25249152..7506d4e07 100644 --- a/yudao-module-mall/yudao-module-product-biz/pom.xml +++ b/yudao-module-mall/yudao-module-product-biz/pom.xml @@ -108,4 +108,24 @@ + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml index f0c0acfd2..75088bc0a 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-product-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml b/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml index 31e5ae5c9..23eefa0b5 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml +++ b/yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml @@ -28,7 +28,7 @@ spring: mybatis-plus: lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject --- #################### 定时任务相关配置 #################### @@ -47,4 +47,4 @@ mybatis-plus: # 芋道配置项,设置当前项目所有自定义的配置 yudao: info: - base-package: cn.iocoder.yudao + base-package: cn.iocoder.yudao.module.product diff --git a/yudao-module-mall/yudao-module-promotion-biz/pom.xml b/yudao-module-mall/yudao-module-promotion-biz/pom.xml index 0e90502d4..64a66236d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/pom.xml +++ b/yudao-module-mall/yudao-module-promotion-biz/pom.xml @@ -131,4 +131,24 @@ + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml index 604a83cdf..4fdf33e00 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-mall/yudao-module-statistics-biz/pom.xml b/yudao-module-mall/yudao-module-statistics-biz/pom.xml index 52995fa13..d908131f5 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/pom.xml +++ b/yudao-module-mall/yudao-module-statistics-biz/pom.xml @@ -138,4 +138,24 @@ + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml index 1a1b3f887..bbb22b999 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-mall/yudao-module-trade-biz/pom.xml b/yudao-module-mall/yudao-module-trade-biz/pom.xml index 4ec5a4e5d..9ba7de6b5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/pom.xml +++ b/yudao-module-mall/yudao-module-trade-biz/pom.xml @@ -150,4 +150,24 @@ + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml index 780224837..1ad9394e0 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-member/yudao-module-member-biz/pom.xml b/yudao-module-member/yudao-module-member-biz/pom.xml index 22942d6ea..b7f9a1c4d 100644 --- a/yudao-module-member/yudao-module-member-biz/pom.xml +++ b/yudao-module-member/yudao-module-member-biz/pom.xml @@ -127,4 +127,24 @@ + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java index 0eaa0763d..96cafaa2b 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java @@ -53,7 +53,8 @@ public class AppAuthController { @PermitAll @Operation(summary = "登出系统") public CommonResult logout(HttpServletRequest request) { - String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); + String token = SecurityFrameworkUtils.obtainAuthorization(request, + securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); if (StrUtil.isNotBlank(token)) { authService.logout(token); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java index 11dcdf957..b2cc06280 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java @@ -23,4 +23,7 @@ public class AppAuthWeixinMiniAppLoginReqVO { @NotEmpty(message = "登录 code 不能为空") private String loginCode; + @Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62") + @NotEmpty(message = "state 不能为空") + private String state; } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java index 3170ddec1..fe0a3a16c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -131,7 +131,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { // 绑定社交用户 String openid = socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), - SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), "")).getCheckedData(); + SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), reqVO.getState())).getCheckedData(); // 创建 Token 令牌,记录登录日志 return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL, openid); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml b/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml index d73214ed8..9a5bc0937 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml +++ b/yudao-module-member/yudao-module-member-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-mp/yudao-module-mp-biz/pom.xml b/yudao-module-mp/yudao-module-mp-biz/pom.xml index ff1d72262..27b7621bc 100644 --- a/yudao-module-mp/yudao-module-mp-biz/pom.xml +++ b/yudao-module-mp/yudao-module-mp-biz/pom.xml @@ -46,10 +46,6 @@ cn.iocoder.cloud yudao-spring-boot-starter-biz-operatelog - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-weixin - cn.iocoder.cloud yudao-spring-boot-starter-biz-tenant @@ -114,6 +110,31 @@ yudao-spring-boot-starter-excel + + + com.github.binarywang + wx-java-mp-spring-boot-starter + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml b/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml index 32cf51b23..d66716b3b 100644 --- a/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml +++ b/yudao-module-mp/yudao-module-mp-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-pay/yudao-module-pay-biz/pom.xml b/yudao-module-pay/yudao-module-pay-biz/pom.xml index aca7735de..35ad4874a 100644 --- a/yudao-module-pay/yudao-module-pay-biz/pom.xml +++ b/yudao-module-pay/yudao-module-pay-biz/pom.xml @@ -120,4 +120,24 @@ + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml b/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml index 32aaf34f8..599e71d12 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/test-integration/resources/application-integration-test.yaml b/yudao-module-pay/yudao-module-pay-biz/src/test-integration/resources/application-integration-test.yaml index c8e34e476..3d6e2379c 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/test-integration/resources/application-integration-test.yaml +++ b/yudao-module-pay/yudao-module-pay-biz/src/test-integration/resources/application-integration-test.yaml @@ -60,7 +60,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) mapper-locations: classpath*:mapper/*.xml - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject --- #################### 定时任务相关配置 #################### @@ -87,7 +87,7 @@ resilience4j: yudao: info: version: 1.0.0 - base-package: cn.iocoder.yudao.module + base-package: cn.iocoder.yudao.module.pay pay: pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify diff --git a/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml b/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml index 54ddd674f..1a17926a1 100644 --- a/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml +++ b/yudao-module-report/yudao-module-report-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 diff --git a/yudao-module-report/yudao-module-report-biz/src/test/resources/application-unit-test.yaml b/yudao-module-report/yudao-module-report-biz/src/test/resources/application-unit-test.yaml index 93e037aab..52c749605 100644 --- a/yudao-module-report/yudao-module-report-biz/src/test/resources/application-unit-test.yaml +++ b/yudao-module-report/yudao-module-report-biz/src/test/resources/application-unit-test.yaml @@ -28,7 +28,7 @@ spring: mybatis-plus: lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject global-config: db-config: id-type: AUTO # H2 主键递增 @@ -50,4 +50,4 @@ mybatis-plus: # 芋道配置项,设置当前项目所有自定义的配置 yudao: info: - base-package: cn.iocoder.yudao + base-package: cn.iocoder.yudao.module.report diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index 7b9632e54..ef5c3a624 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -82,6 +82,10 @@ public interface ErrorCodeConstants { // ========== 短信模板 1-002-012-000 ========== ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_012_000, "短信模板不存在"); ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_002_012_001, "已经存在编码为【{}】的短信模板"); + ErrorCode SMS_TEMPLATE_API_ERROR = new ErrorCode(1_002_012_002, "短信 API 模板调用失败,原因是:{}"); + ErrorCode SMS_TEMPLATE_API_AUDIT_CHECKING = new ErrorCode(1_002_012_003, "短信 API 模版无法使用,原因:审批中"); + ErrorCode SMS_TEMPLATE_API_AUDIT_FAIL = new ErrorCode(1_002_012_004, "短信 API 模版无法使用,原因:审批不通过,{}"); + ErrorCode SMS_TEMPLATE_API_NOT_FOUND = new ErrorCode(1_002_012_005, "短信 API 模版无法使用,原因:模版不存在"); // ========== 短信发送 1-002-013-000 ========== ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1_002_013_000, "手机号不存在"); @@ -104,6 +108,7 @@ public interface ErrorCodeConstants { ErrorCode TENANT_EXPIRE = new ErrorCode(1_002_015_002, "名字为【{}】的租户已过期"); ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1_002_015_003, "系统租户不能进行修改、删除等操作!"); ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1_002_015_004, "名字为【{}】的租户已存在"); + ErrorCode TENANT_WEBSITE_DUPLICATE = new ErrorCode(1_002_015_005, "域名为【{}】的租户已存在"); // ========== 租户套餐 1-002-016-000 ========== ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在"); diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java index 7146b98ef..6b06b06d6 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/DataScopeEnum.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.module.system.enums.permission; +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; + /** * 数据范围枚举类 * @@ -12,7 +15,7 @@ import lombok.Getter; */ @Getter @AllArgsConstructor -public enum DataScopeEnum { +public enum DataScopeEnum implements IntArrayValuable { ALL(1), // 全部数据权限 @@ -27,4 +30,11 @@ public enum DataScopeEnum { */ private final Integer scope; + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DataScopeEnum::getScope).toArray(); + + @Override + public int[] array() { + return ARRAYS; + } + } diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index a5370a1f4..d1cd79904 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -62,10 +62,6 @@ cn.iocoder.cloud yudao-spring-boot-starter-biz-data-permission - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-social - cn.iocoder.cloud yudao-spring-boot-starter-biz-tenant @@ -78,10 +74,6 @@ cn.iocoder.cloud yudao-spring-boot-starter-biz-ip - - cn.iocoder.cloud - yudao-spring-boot-starter-biz-weixin - @@ -165,7 +157,23 @@ yudao-spring-boot-starter-monitor + + + com.xingyuv + spring-boot-starter-justauth + + + + com.github.binarywang + wx-java-mp-spring-boot-starter + + + com.github.binarywang + wx-java-miniapp-spring-boot-starter + + + ${project.artifactId} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index 00270da82..9eb46ee6a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.system.api.dept; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; import org.springframework.validation.annotation.Validated; @@ -24,13 +24,13 @@ public class DeptApiImpl implements DeptApi { @Override public CommonResult getDept(Long id) { DeptDO dept = deptService.getDept(id); - return success(DeptConvert.INSTANCE.convert03(dept)); + return success(BeanUtils.toBean(dept, DeptRespDTO.class)); } @Override public CommonResult> getDeptList(Collection ids) { List depts = deptService.getDeptList(ids); - return success(DeptConvert.INSTANCE.convertList03(depts)); + return success(BeanUtils.toBean(depts, DeptRespDTO.class)); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java index bc93fe8c0..5a3f745a1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dict/DictDataApiImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.system.api.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; -import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.service.dict.DictDataService; import org.springframework.validation.annotation.Validated; @@ -29,13 +29,13 @@ public class DictDataApiImpl implements DictDataApi { @Override public CommonResult getDictData(String dictType, String value) { DictDataDO dictData = dictDataService.getDictData(dictType, value); - return success(DictDataConvert.INSTANCE.convert02(dictData)); + return success(BeanUtils.toBean(dictData, DictDataRespDTO.class)); } @Override public CommonResult parseDictData(String dictType, String label) { DictDataDO dictData = dictDataService.parseDictData(dictType, label); - return success(DictDataConvert.INSTANCE.convert02(dictData)); + return success(BeanUtils.toBean(dictData, DictDataRespDTO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/oauth2/OAuth2TokenApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/oauth2/OAuth2TokenApiImpl.java index 2e4702eea..a199bb920 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/oauth2/OAuth2TokenApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/oauth2/OAuth2TokenApiImpl.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.system.api.oauth2; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO; import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO; import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; -import cn.iocoder.yudao.module.system.convert.auth.OAuth2TokenConvert; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; import io.swagger.v3.oas.annotations.Operation; @@ -27,24 +27,25 @@ public class OAuth2TokenApiImpl implements OAuth2TokenApi { public CommonResult createAccessToken(OAuth2AccessTokenCreateReqDTO reqDTO) { OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken( reqDTO.getUserId(), reqDTO.getUserType(), reqDTO.getClientId(), reqDTO.getScopes()); - return success(OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO)); + return success(BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class)); } @Override public CommonResult checkAccessToken(String accessToken) { - return success(OAuth2TokenConvert.INSTANCE.convert(oauth2TokenService.checkAccessToken(accessToken))); + OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.checkAccessToken(accessToken); + return success(BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenCheckRespDTO.class)); } @Override public CommonResult removeAccessToken(String accessToken) { OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.removeAccessToken(accessToken); - return success(OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO)); + return success(BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class)); } @Override public CommonResult refreshAccessToken(String refreshToken, String clientId) { OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, clientId); - return success(OAuth2TokenConvert.INSTANCE.convert2(accessTokenDO)); + return success(BeanUtils.toBean(accessTokenDO, OAuth2AccessTokenRespDTO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java index 6cad9dc6a..0f41dd025 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.system.api.social; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; -import cn.iocoder.yudao.module.system.convert.social.SocialClientConvert; import cn.iocoder.yudao.module.system.service.social.SocialClientService; import me.chanjar.weixin.common.bean.WxJsapiSignature; import org.springframework.validation.annotation.Validated; @@ -34,13 +34,13 @@ public class SocialClientApiImpl implements SocialClientApi { @Override public CommonResult createWxMpJsapiSignature(Integer userType, String url) { WxJsapiSignature signature = socialClientService.createWxMpJsapiSignature(userType, url); - return success(SocialClientConvert.INSTANCE.convert(signature)); + return success(BeanUtils.toBean(signature, SocialWxJsapiSignatureRespDTO.class)); } @Override public CommonResult getWxMaPhoneNumberInfo(Integer userType, String phoneCode) { WxMaPhoneNumberInfo info = socialClientService.getWxMaPhoneNumberInfo(userType, phoneCode); - return success(SocialClientConvert.INSTANCE.convert(info)); + return success(BeanUtils.toBean(info, SocialWxPhoneNumberInfoRespDTO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index 3e1f45483..111dd4999 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.system.api.user; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import cn.iocoder.yudao.module.system.convert.user.UserConvert; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import org.springframework.validation.annotation.Validated; @@ -25,25 +25,25 @@ public class AdminUserApiImpl implements AdminUserApi { @Override public CommonResult getUser(Long id) { AdminUserDO user = userService.getUser(id); - return success(UserConvert.INSTANCE.convert4(user)); + return success(BeanUtils.toBean(user, AdminUserRespDTO.class)); } @Override public CommonResult> getUserList(Collection ids) { List users = userService.getUserList(ids); - return success(UserConvert.INSTANCE.convertList4(users)); + return success(BeanUtils.toBean(users, AdminUserRespDTO.class)); } @Override public CommonResult> getUserListByDeptIds(Collection deptIds) { List users = userService.getUserListByDeptIds(deptIds); - return success(UserConvert.INSTANCE.convertList4(users)); + return success(BeanUtils.toBean(users, AdminUserRespDTO.class)); } @Override public CommonResult> getUserListByPostIds(Collection postIds) { List users = userService.getUserListByPostIds(postIds); - return success(UserConvert.INSTANCE.convertList4(users)); + return success(BeanUtils.toBean(users, AdminUserRespDTO.class)); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index c2eae8d38..061539494 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.security.config.SecurityProperties; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; @@ -38,7 +39,6 @@ import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.obtainAuthorization; @Tag(name = "管理后台 - 认证") @RestController @@ -76,7 +76,8 @@ public class AuthController { @Operation(summary = "登出系统") @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 public CommonResult logout(HttpServletRequest request) { - String token = obtainAuthorization(request, securityProperties.getTokenHeader()); + String token = SecurityFrameworkUtils.obtainAuthorization(request, + securityProperties.getTokenHeader(), securityProperties.getTokenParameter()); if (StrUtil.isNotBlank(token)) { authService.logout(token, LoginLogTypeEnum.LOGOUT_SELF.getType()); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java index 029958e8c..25c5e88ee 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java @@ -17,11 +17,6 @@ import javax.annotation.Resource; import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletRequest; -/** - * 验证码 - * - * @author 芋道源码 - */ @Tag(name = "管理后台 - 验证码") @RestController("adminCaptchaController") @RequestMapping("/system/captcha") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java index 906ab646a..86cdeed1d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/DeptController.java @@ -2,20 +2,22 @@ package cn.iocoder.yudao.module.system.controller.admin.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.*; -import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; -import java.util.Comparator; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -32,16 +34,16 @@ public class DeptController { @PostMapping("create") @Operation(summary = "创建部门") @PreAuthorize("@ss.hasPermission('system:dept:create')") - public CommonResult createDept(@Valid @RequestBody DeptCreateReqVO reqVO) { - Long deptId = deptService.createDept(reqVO); + public CommonResult createDept(@Valid @RequestBody DeptSaveReqVO createReqVO) { + Long deptId = deptService.createDept(createReqVO); return success(deptId); } @PutMapping("update") @Operation(summary = "更新部门") @PreAuthorize("@ss.hasPermission('system:dept:update')") - public CommonResult updateDept(@Valid @RequestBody DeptUpdateReqVO reqVO) { - deptService.updateDept(reqVO); + public CommonResult updateDept(@Valid @RequestBody DeptSaveReqVO updateReqVO) { + deptService.updateDept(updateReqVO); return success(true); } @@ -59,20 +61,15 @@ public class DeptController { @PreAuthorize("@ss.hasPermission('system:dept:query')") public CommonResult> getDeptList(DeptListReqVO reqVO) { List list = deptService.getDeptList(reqVO); - list.sort(Comparator.comparing(DeptDO::getSort)); - return success(DeptConvert.INSTANCE.convertList(list)); + return success(BeanUtils.toBean(list, DeptRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping(value = {"/list-all-simple", "/simple-list"}) @Operation(summary = "获取部门精简信息列表", description = "只包含被开启的部门,主要用于前端的下拉选项") public CommonResult> getSimpleDeptList() { - // 获得部门列表,只要开启状态的 - DeptListReqVO reqVO = new DeptListReqVO(); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - List list = deptService.getDeptList(reqVO); - // 排序后,返回给前端 - list.sort(Comparator.comparing(DeptDO::getSort)); - return success(DeptConvert.INSTANCE.convertList02(list)); + List list = deptService.getDeptList( + new DeptListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(BeanUtils.toBean(list, DeptSimpleRespVO.class)); } @GetMapping("/get") @@ -80,7 +77,8 @@ public class DeptController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:dept:query')") public CommonResult getDept(@RequestParam("id") Long id) { - return success(DeptConvert.INSTANCE.convert(deptService.getDept(id))); + DeptDO dept = deptService.getDept(id); + return success(BeanUtils.toBean(dept, DeptRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java index 70e2d8639..175e4b242 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/PostController.java @@ -2,16 +2,20 @@ package cn.iocoder.yudao.module.system.controller.admin.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.*; -import cn.iocoder.yudao.module.system.convert.dept.PostConvert; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.service.dept.PostService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -39,16 +43,16 @@ public class PostController { @PostMapping("/create") @Operation(summary = "创建岗位") @PreAuthorize("@ss.hasPermission('system:post:create')") - public CommonResult createPost(@Valid @RequestBody PostCreateReqVO reqVO) { - Long postId = postService.createPost(reqVO); + public CommonResult createPost(@Valid @RequestBody PostSaveReqVO createReqVO) { + Long postId = postService.createPost(createReqVO); return success(postId); } @PutMapping("/update") @Operation(summary = "修改岗位") @PreAuthorize("@ss.hasPermission('system:post:update')") - public CommonResult updatePost(@Valid @RequestBody PostUpdateReqVO reqVO) { - postService.updatePost(reqVO); + public CommonResult updatePost(@Valid @RequestBody PostSaveReqVO updateReqVO) { + postService.updatePost(updateReqVO); return success(true); } @@ -65,35 +69,38 @@ public class PostController { @Parameter(name = "id", description = "岗位编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:post:query')") public CommonResult getPost(@RequestParam("id") Long id) { - return success(PostConvert.INSTANCE.convert(postService.getPost(id))); + PostDO post = postService.getPost(id); + return success(BeanUtils.toBean(post, PostRespVO.class)); } - @GetMapping("/list-all-simple") - @Operation(summary = "获取岗位精简信息列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") + @GetMapping(value = {"/list-all-simple", "simple-list"}) + @Operation(summary = "获取岗位全列表", description = "只包含被开启的岗位,主要用于前端的下拉选项") public CommonResult> getSimplePostList() { // 获得岗位列表,只要开启状态的 List list = postService.getPostList(null, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); // 排序后,返回给前端 list.sort(Comparator.comparing(PostDO::getSort)); - return success(PostConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, PostSimpleRespVO.class)); } @GetMapping("/page") @Operation(summary = "获得岗位分页列表") @PreAuthorize("@ss.hasPermission('system:post:query')") - public CommonResult> getPostPage(@Validated PostPageReqVO reqVO) { - return success(PostConvert.INSTANCE.convertPage(postService.getPostPage(reqVO))); + public CommonResult> getPostPage(@Validated PostPageReqVO pageReqVO) { + PageResult pageResult = postService.getPostPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, PostRespVO.class)); } @GetMapping("/export") @Operation(summary = "岗位管理") @PreAuthorize("@ss.hasPermission('system:post:export')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Validated PostExportReqVO reqVO) throws IOException { - List posts = postService.getPostList(reqVO); - List data = PostConvert.INSTANCE.convertList03(posts); + public void export(HttpServletResponse response, @Validated PostPageReqVO reqVO) throws IOException { + reqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = postService.getPostPage(reqVO).getList(); // 输出 - ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostExcelVO.class, data); + ExcelUtils.write(response, "岗位数据.xls", "岗位列表", PostRespVO.class, + BeanUtils.toBean(list, PostRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptCreateReqVO.java deleted file mode 100644 index 5cf650c52..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptCreateReqVO.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 部门创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class DeptCreateReqVO extends DeptBaseVO { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java index d8d6a229b..777cb75de 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptRespVO.java @@ -2,19 +2,35 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import java.time.LocalDateTime; @Schema(description = "管理后台 - 部门信息 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -public class DeptRespVO extends DeptBaseVO { +public class DeptRespVO { - @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @Schema(description = "部门编号", example = "1024") private Long id; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + private String name; + + @Schema(description = "父部门 ID", example = "1024") + private Long parentId; + + @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer sort; + + @Schema(description = "负责人的用户编号", example = "2048") + private Long leaderUserId; + + @Schema(description = "联系电话", example = "15601691000") + private String phone; + + @Schema(description = "邮箱", example = "yudao@iocoder.cn") + private String email; + + @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer status; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java similarity index 65% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java index 5d3a4b6d7..fb9f29847 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptSaveReqVO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -8,19 +10,19 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 部门 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 部门创建/修改 Request VO") @Data -public class DeptBaseVO { +public class DeptSaveReqVO { - @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @Schema(description = "部门编号", example = "1024") + private Long id; + + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") @NotBlank(message = "部门名称不能为空") - @Size(max = 30, message = "部门名称长度不能超过30个字符") + @Size(max = 30, message = "部门名称长度不能超过 30 个字符") private String name; - @Schema(description = "父菜单 ID", example = "1024") + @Schema(description = "父部门 ID", example = "1024") private Long parentId; @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @@ -36,12 +38,12 @@ public class DeptBaseVO { @Schema(description = "邮箱", example = "yudao@iocoder.cn") @Email(message = "邮箱格式不正确") - @Size(max = 50, message = "邮箱长度不能超过50个字符") + @Size(max = 50, message = "邮箱长度不能超过 50 个字符") private String email; @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "状态不能为空") -// @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") + @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptUpdateReqVO.java deleted file mode 100644 index b63f79d85..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/dept/DeptUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 部门更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class DeptUpdateReqVO extends DeptBaseVO { - - @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "部门编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostCreateReqVO.java deleted file mode 100644 index b2e52e174..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostCreateReqVO.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - 岗位创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class PostCreateReqVO extends PostBaseVO { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExcelVO.java deleted file mode 100644 index 0053a7895..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExcelVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -/** - * 岗位 Excel 导出响应 VO - */ -@Data -public class PostExcelVO { - - @ExcelProperty("岗位序号") - private Long id; - - @ExcelProperty("岗位编码") - private String code; - - @ExcelProperty("岗位名称") - private String name; - - @ExcelProperty("岗位排序") - private Integer sort; - - @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private String status; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java deleted file mode 100644 index 837da3587..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostExportReqVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - 岗位导出 Request VO,参数和 PostExcelVO 是一致的") -@Data -public class PostExportReqVO { - - @Schema(description = "岗位编码,模糊匹配", example = "yudao") - private String code; - - @Schema(description = "岗位名称,模糊匹配", example = "芋道") - private String name; - - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java deleted file mode 100644 index 949680441..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostListReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - 岗位列表 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class PostListReqVO extends PostBaseVO { - - @Schema(description = "岗位名称,模糊匹配", example = "芋道") - private String name; - - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java index 5cc994123..78f306edb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostPageReqVO.java @@ -19,4 +19,4 @@ public class PostPageReqVO extends PageParam { @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") private Integer status; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java index db39fff88..a037a132a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java @@ -1,20 +1,45 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import java.time.LocalDateTime; @Schema(description = "管理后台 - 岗位信息 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -public class PostRespVO extends PostBaseVO { +@ExcelIgnoreUnannotated +public class PostRespVO { @Schema(description = "岗位序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("岗位序号") private Long id; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") + @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆") + @ExcelProperty("岗位名称") + private String name; + + @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + @ExcelProperty("岗位编码") + private String code; + + @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("岗位排序") + private Integer sort; + + @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "快乐的备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java similarity index 64% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java index 6127564f1..b8d3c24cd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSaveReqVO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -7,16 +9,16 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 岗位 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 岗位创建/修改 Request VO") @Data -public class PostBaseVO { +public class PostSaveReqVO { - @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") + @Schema(description = "岗位编号", example = "1024") + private Long id; + + @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆") @NotBlank(message = "岗位名称不能为空") - @Size(max = 50, message = "岗位名称长度不能超过50个字符") + @Size(max = 50, message = "岗位名称长度不能超过 50 个字符") private String name; @Schema(description = "岗位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") @@ -28,10 +30,11 @@ public class PostBaseVO { @NotNull(message = "显示顺序不能为空") private Integer sort; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @InEnum(CommonStatusEnum.class) private Integer status; @Schema(description = "备注", example = "快乐的备注") private String remark; -} +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java index a4698df16..72852a18e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java @@ -1,20 +1,19 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; -@Schema(description = "管理后台 - 岗位精简信息 Response VO") +@Schema(description = "管理后台 - 岗位信息的精简 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor public class PostSimpleRespVO { - @Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @Schema(description = "岗位序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("岗位序号") private Long id; - @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小土豆") + @ExcelProperty("岗位名称") private String name; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java deleted file mode 100644 index c17685a71..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 岗位更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class PostUpdateReqVO extends PostBaseVO { - - @Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "岗位编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java index 13c6f4855..8dc38a644 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictDataController.java @@ -1,16 +1,21 @@ package cn.iocoder.yudao.module.system.controller.admin.dict; -import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.*; -import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSimpleRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.service.dict.DictDataService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -36,16 +41,16 @@ public class DictDataController { @PostMapping("/create") @Operation(summary = "新增字典数据") @PreAuthorize("@ss.hasPermission('system:dict:create')") - public CommonResult createDictData(@Valid @RequestBody DictDataCreateReqVO reqVO) { - Long dictDataId = dictDataService.createDictData(reqVO); + public CommonResult createDictData(@Valid @RequestBody DictDataSaveReqVO createReqVO) { + Long dictDataId = dictDataService.createDictData(createReqVO); return success(dictDataId); } @PutMapping("/update") @Operation(summary = "修改字典数据") @PreAuthorize("@ss.hasPermission('system:dict:update')") - public CommonResult updateDictData(@Valid @RequestBody DictDataUpdateReqVO reqVO) { - dictDataService.updateDictData(reqVO); + public CommonResult updateDictData(@Valid @RequestBody DictDataSaveReqVO updateReqVO) { + dictDataService.updateDictData(updateReqVO); return success(true); } @@ -58,19 +63,21 @@ public class DictDataController { return success(true); } - @GetMapping("/list-all-simple") + @GetMapping(value = {"/list-all-simple", "simple-list"}) @Operation(summary = "获得全部字典数据列表", description = "一般用于管理后台缓存字典数据在本地") // 无需添加权限认证,因为前端全局都需要 public CommonResult> getSimpleDictDataList() { - List list = dictDataService.getDictDataList(); - return success(DictDataConvert.INSTANCE.convertList(list)); + List list = dictDataService.getDictDataList( + CommonStatusEnum.ENABLE.getStatus(), null); + return success(BeanUtils.toBean(list, DictDataSimpleRespVO.class)); } @GetMapping("/page") @Operation(summary = "/获得字典类型的分页列表") @PreAuthorize("@ss.hasPermission('system:dict:query')") - public CommonResult> getDictTypePage(@Valid DictDataPageReqVO reqVO) { - return success(DictDataConvert.INSTANCE.convertPage(dictDataService.getDictDataPage(reqVO))); + public CommonResult> getDictTypePage(@Valid DictDataPageReqVO pageReqVO) { + PageResult pageResult = dictDataService.getDictDataPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, DictDataRespVO.class)); } @GetMapping(value = "/get") @@ -78,18 +85,20 @@ public class DictDataController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:dict:query')") public CommonResult getDictData(@RequestParam("id") Long id) { - return success(DictDataConvert.INSTANCE.convert(dictDataService.getDictData(id))); + DictDataDO dictData = dictDataService.getDictData(id); + return success(BeanUtils.toBean(dictData, DictDataRespVO.class)); } @GetMapping("/export") @Operation(summary = "导出字典数据") @PreAuthorize("@ss.hasPermission('system:dict:export')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Valid DictDataExportReqVO reqVO) throws IOException { - List list = dictDataService.getDictDataList(reqVO); - List data = DictDataConvert.INSTANCE.convertList02(list); + public void export(HttpServletResponse response, @Valid DictDataPageReqVO exportReqVO) throws IOException { + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = dictDataService.getDictDataPage(exportReqVO).getList(); // 输出 - ExcelUtils.write(response, "字典数据.xls", "数据列表", DictDataExcelVO.class, data); + ExcelUtils.write(response, "字典数据.xls", "数据", DictDataRespVO.class, + BeanUtils.toBean(list, DictDataRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java index 6fcdcdd9c..99b251f8b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/DictTypeController.java @@ -1,16 +1,20 @@ package cn.iocoder.yudao.module.system.controller.admin.dict; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.*; -import cn.iocoder.yudao.module.system.convert.dict.DictTypeConvert; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import cn.iocoder.yudao.module.system.service.dict.DictTypeService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -36,16 +40,16 @@ public class DictTypeController { @PostMapping("/create") @Operation(summary = "创建字典类型") @PreAuthorize("@ss.hasPermission('system:dict:create')") - public CommonResult createDictType(@Valid @RequestBody DictTypeCreateReqVO reqVO) { - Long dictTypeId = dictTypeService.createDictType(reqVO); + public CommonResult createDictType(@Valid @RequestBody DictTypeSaveReqVO createReqVO) { + Long dictTypeId = dictTypeService.createDictType(createReqVO); return success(dictTypeId); } @PutMapping("/update") @Operation(summary = "修改字典类型") @PreAuthorize("@ss.hasPermission('system:dict:update')") - public CommonResult updateDictType(@Valid @RequestBody DictTypeUpdateReqVO reqVO) { - dictTypeService.updateDictType(reqVO); + public CommonResult updateDictType(@Valid @RequestBody DictTypeSaveReqVO updateReqVO) { + dictTypeService.updateDictType(updateReqVO); return success(true); } @@ -58,11 +62,12 @@ public class DictTypeController { return success(true); } - @Operation(summary = "/获得字典类型的分页列表") @GetMapping("/page") + @Operation(summary = "获得字典类型的分页列表") @PreAuthorize("@ss.hasPermission('system:dict:query')") - public CommonResult> pageDictTypes(@Valid DictTypePageReqVO reqVO) { - return success(DictTypeConvert.INSTANCE.convertPage(dictTypeService.getDictTypePage(reqVO))); + public CommonResult> pageDictTypes(@Valid DictTypePageReqVO pageReqVO) { + PageResult pageResult = dictTypeService.getDictTypePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, DictTypeRespVO.class)); } @Operation(summary = "/查询字典类型详细") @@ -70,26 +75,28 @@ public class DictTypeController { @GetMapping(value = "/get") @PreAuthorize("@ss.hasPermission('system:dict:query')") public CommonResult getDictType(@RequestParam("id") Long id) { - return success(DictTypeConvert.INSTANCE.convert(dictTypeService.getDictType(id))); + DictTypeDO dictType = dictTypeService.getDictType(id); + return success(BeanUtils.toBean(dictType, DictTypeRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping(value = {"/list-all-simple", "simple-list"}) @Operation(summary = "获得全部字典类型列表", description = "包括开启 + 禁用的字典类型,主要用于前端的下拉选项") // 无需添加权限认证,因为前端全局都需要 public CommonResult> getSimpleDictTypeList() { List list = dictTypeService.getDictTypeList(); - return success(DictTypeConvert.INSTANCE.convertList(list)); + return success(BeanUtils.toBean(list, DictTypeSimpleRespVO.class)); } @Operation(summary = "导出数据类型") @GetMapping("/export") @PreAuthorize("@ss.hasPermission('system:dict:query')") @OperateLog(type = EXPORT) - public void export(HttpServletResponse response, @Valid DictTypeExportReqVO reqVO) throws IOException { - List list = dictTypeService.getDictTypeList(reqVO); - List data = DictTypeConvert.INSTANCE.convertList02(list); - // 输出 - ExcelUtils.write(response, "字典类型.xls", "类型列表", DictTypeExcelVO.class, data); + public void export(HttpServletResponse response, @Valid DictTypePageReqVO exportReqVO) throws IOException { + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = dictTypeService.getDictTypePage(exportReqVO).getList(); + // 导出 + ExcelUtils.write(response, "字典类型.xls", "数据", DictTypeRespVO.class, + BeanUtils.toBean(list, DictTypeRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataCreateReqVO.java deleted file mode 100644 index 6f225eba4..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataCreateReqVO.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - 字典数据创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class DictDataCreateReqVO extends DictDataBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExcelVO.java deleted file mode 100644 index 6dcb9bb50..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExcelVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -/** - * 字典数据 Excel 导出响应 VO - */ -@Data -public class DictDataExcelVO { - - @ExcelProperty("字典编码") - private Long id; - - @ExcelProperty("字典排序") - private Integer sort; - - @ExcelProperty("字典标签") - private String label; - - @ExcelProperty("字典键值") - private String value; - - @ExcelProperty("字典类型") - private String dictType; - - @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private Integer status; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java deleted file mode 100644 index 0d7fc748a..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataExportReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.Size; - -@Schema(description = "管理后台 - 字典类型导出 Request VO") -@Data -public class DictDataExportReqVO { - - @Schema(description = "字典标签", example = "芋道") - @Size(max = 100, message = "字典标签长度不能超过100个字符") - private String label; - - @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex") - @Size(max = 100, message = "字典类型类型长度不能超过100个字符") - private String dictType; - - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java index 73ddb781f..d9bd14af8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataPageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -21,6 +23,7 @@ public class DictDataPageReqVO extends PageParam { private String dictType; @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") + @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java index d9786c903..e0b940a58 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java @@ -1,23 +1,54 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Schema(description = "管理后台 - 字典数据信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class DictDataRespVO extends DictDataBaseVO { +@ExcelIgnoreUnannotated +public class DictDataRespVO { @Schema(description = "字典数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("字典编码") private Long id; + @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("字典排序") + private Integer sort; + + @Schema(description = "字典标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @ExcelProperty("字典标签") + private String label; + + @Schema(description = "字典值", requiredMode = Schema.RequiredMode.REQUIRED, example = "iocoder") + @ExcelProperty("字典键值") + private String value; + + @Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex") + @ExcelProperty("字典类型") + private String dictType; + + @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default") + private String colorType; + + @Schema(description = "css 样式", example = "btn-visible") + private String cssClass; + + @Schema(description = "备注", example = "我是一个角色") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSaveReqVO.java similarity index 86% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSaveReqVO.java index 0bb821b6e..4f35087bc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataSaveReqVO.java @@ -9,12 +9,12 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 字典数据 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 字典数据创建/修改 Request VO") @Data -public class DictDataBaseVO { +public class DictDataSaveReqVO { + + @Schema(description = "字典数据编号", example = "1024") + private Long id; @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "显示顺序不能为空") @@ -37,11 +37,12 @@ public class DictDataBaseVO { @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "状态不能为空") -// @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") + @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") private Integer status; @Schema(description = "颜色类型,default、primary、success、info、warning、danger", example = "default") private String colorType; + @Schema(description = "css 样式", example = "btn-visible") private String cssClass; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataUpdateReqVO.java deleted file mode 100644 index 226029f81..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 字典数据更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class DictDataUpdateReqVO extends DictDataBaseVO { - - @Schema(description = "字典数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "字典数据编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeCreateReqVO.java deleted file mode 100644 index 59e9ecc78..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeCreateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -@Schema(description = "管理后台 - 字典类型创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class DictTypeCreateReqVO extends DictTypeBaseVO { - - @Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex") - @NotNull(message = "字典类型不能为空") - @Size(max = 100, message = "字典类型类型长度不能超过100个字符") - private String type; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExcelVO.java deleted file mode 100644 index b7db46d0e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExcelVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -/** - * 字典类型 Excel 导出响应 VO - */ -@Data -public class DictTypeExcelVO { - - @ExcelProperty("字典主键") - private Long id; - - @ExcelProperty("字典名称") - private String name; - - @ExcelProperty("字典类型") - private String type; - - @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private Integer status; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java deleted file mode 100644 index fb15914c2..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeExportReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 字典类型分页列表 Request VO") -@Data -public class DictTypeExportReqVO { - - @Schema(description = "字典类型名称,模糊匹配", example = "芋道") - private String name; - - @Schema(description = "字典类型,模糊匹配", example = "sys_common_sex") - private String type; - - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java index aa7372195..80fde2e9c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypePageReqVO.java @@ -30,4 +30,4 @@ public class DictTypePageReqVO extends PageParam { @Schema(description = "创建时间") private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java index 0dcba7007..6ddd47bcd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java @@ -1,26 +1,40 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Schema(description = "管理后台 - 字典类型信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class DictTypeRespVO extends DictTypeBaseVO { +@ExcelIgnoreUnannotated +public class DictTypeRespVO { @Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("字典主键") private Long id; + @Schema(description = "字典名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "性别") + @ExcelProperty("字典名称") + private String name; + @Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex") + @ExcelProperty("字典类型") private String type; + @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "快乐的备注") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSaveReqVO.java similarity index 64% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSaveReqVO.java index 996a32364..c506c08f6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSaveReqVO.java @@ -7,18 +7,23 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 字典类型 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 字典类型创建/修改 Request VO") @Data -public class DictTypeBaseVO { +public class DictTypeSaveReqVO { + + @Schema(description = "字典类型编号", example = "1024") + private Long id; @Schema(description = "字典名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "性别") @NotBlank(message = "字典名称不能为空") @Size(max = 100, message = "字典类型名称长度不能超过100个字符") private String name; + @Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sys_common_sex") + @NotNull(message = "字典类型不能为空") + @Size(max = 100, message = "字典类型类型长度不能超过 100 个字符") + private String type; + @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "状态不能为空") private Integer status; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java index 2d8133b75..f3e717dae 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeSimpleRespVO.java @@ -1,14 +1,10 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; @Schema(description = "管理后台 - 字典类型精简信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor public class DictTypeSimpleRespVO { @Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeUpdateReqVO.java deleted file mode 100644 index 9209317ba..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 字典类型更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class DictTypeUpdateReqVO extends DictTypeBaseVO { - - @Schema(description = "字典类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "字典类型编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java index e72631a9c..09d8ee86c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/ErrorCodeController.java @@ -1,11 +1,14 @@ package cn.iocoder.yudao.module.system.controller.admin.errorcode; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.*; -import cn.iocoder.yudao.module.system.convert.errorcode.ErrorCodeConvert; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeRespVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; import cn.iocoder.yudao.module.system.service.errorcode.ErrorCodeService; import io.swagger.v3.oas.annotations.Operation; @@ -36,14 +39,14 @@ public class ErrorCodeController { @PostMapping("/create") @Operation(summary = "创建错误码") @PreAuthorize("@ss.hasPermission('system:error-code:create')") - public CommonResult createErrorCode(@Valid @RequestBody ErrorCodeCreateReqVO createReqVO) { + public CommonResult createErrorCode(@Valid @RequestBody ErrorCodeSaveReqVO createReqVO) { return success(errorCodeService.createErrorCode(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新错误码") @PreAuthorize("@ss.hasPermission('system:error-code:update')") - public CommonResult updateErrorCode(@Valid @RequestBody ErrorCodeUpdateReqVO updateReqVO) { + public CommonResult updateErrorCode(@Valid @RequestBody ErrorCodeSaveReqVO updateReqVO) { errorCodeService.updateErrorCode(updateReqVO); return success(true); } @@ -63,7 +66,7 @@ public class ErrorCodeController { @PreAuthorize("@ss.hasPermission('system:error-code:query')") public CommonResult getErrorCode(@RequestParam("id") Long id) { ErrorCodeDO errorCode = errorCodeService.getErrorCode(id); - return success(ErrorCodeConvert.INSTANCE.convert(errorCode)); + return success(BeanUtils.toBean(errorCode, ErrorCodeRespVO.class)); } @GetMapping("/page") @@ -71,19 +74,20 @@ public class ErrorCodeController { @PreAuthorize("@ss.hasPermission('system:error-code:query')") public CommonResult> getErrorCodePage(@Valid ErrorCodePageReqVO pageVO) { PageResult pageResult = errorCodeService.getErrorCodePage(pageVO); - return success(ErrorCodeConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, ErrorCodeRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出错误码 Excel") @PreAuthorize("@ss.hasPermission('system:error-code:export')") @OperateLog(type = EXPORT) - public void exportErrorCodeExcel(@Valid ErrorCodeExportReqVO exportReqVO, + public void exportErrorCodeExcel(@Valid ErrorCodePageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = errorCodeService.getErrorCodeList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = errorCodeService.getErrorCodePage(exportReqVO).getList(); // 导出 Excel - List datas = ErrorCodeConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "错误码.xls", "数据", ErrorCodeExcelVO.class, datas); + ExcelUtils.write(response, "错误码.xls", "数据", ErrorCodeRespVO.class, + BeanUtils.toBean(list, ErrorCodeRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeCreateReqVO.java deleted file mode 100644 index 7d5720a38..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeCreateReqVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; - - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 错误码创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ErrorCodeCreateReqVO extends ErrorCodeBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExcelVO.java deleted file mode 100644 index 8af519d25..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExcelVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 错误码 Excel VO - * - * @author 芋道源码 - */ -@Data -public class ErrorCodeExcelVO { - - @ExcelProperty("错误码编号") - private Long id; - - @ExcelProperty(value = "错误码类型", converter = DictConvert.class) - @DictFormat("inf_error_code_type") // TODO 芋艿:得思考下杂解决枚举值 - private Integer type; - - @ExcelProperty("应用名") - private String applicationName; - - @ExcelProperty("错误码编码") - private Integer code; - - @ExcelProperty("错误码错误提示") - private String message; - - @ExcelProperty("备注") - private String memo; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java deleted file mode 100644 index 2506a184b..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeExportReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 错误码 Excel 导出 Request VO,参数和 InfErrorCodePageReqVO 是一致的") -@Data -public class ErrorCodeExportReqVO { - - @Schema(description = "错误码类型", example = "1") - private Integer type; - - @Schema(description = "应用名", example = "dashboard") - private String applicationName; - - @Schema(description = "错误码编码", example = "1234") - private Integer code; - - @Schema(description = "错误码错误提示", example = "帅气") - private String message; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java index 46bad4678..ba565d94c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodePageReqVO.java @@ -33,4 +33,4 @@ public class ErrorCodePageReqVO extends PageParam { @Schema(description = "创建时间") private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java index bd8e35fef..31f72bf93 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeRespVO.java @@ -1,25 +1,47 @@ package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; @Schema(description = "管理后台 - 错误码 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ErrorCodeRespVO extends ErrorCodeBaseVO { +@ExcelIgnoreUnannotated +public class ErrorCodeRespVO { @Schema(description = "错误码编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("错误码编号") private Long id; @Schema(description = "错误码类型,参见 ErrorCodeTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "错误码类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.ERROR_CODE_TYPE) private Integer type; + @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard") + @ExcelProperty("应用名") + private String applicationName; + + @Schema(description = "错误码编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234") + @ExcelProperty("错误码编码") + private Integer code; + + @Schema(description = "错误码错误提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "帅气") + @ExcelProperty("错误码错误提示") + private String message; + + @Schema(description = "备注", example = "哈哈哈") + @ExcelProperty("备注") + private String memo; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeSaveReqVO.java similarity index 80% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeSaveReqVO.java index 3e222a070..d8b6b2125 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeSaveReqVO.java @@ -5,12 +5,12 @@ import lombok.Data; import javax.validation.constraints.NotNull; -/** -* 错误码 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ +@Schema(description = "管理后台 - 错误码创建/修改 Request VO") @Data -public class ErrorCodeBaseVO { +public class ErrorCodeSaveReqVO { + + @Schema(description = "错误码编号", example = "1024") + private Long id; @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "dashboard") @NotNull(message = "应用名不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeUpdateReqVO.java deleted file mode 100644 index 5b17591f0..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/errorcode/vo/ErrorCodeUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.errorcode.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 错误码更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ErrorCodeUpdateReqVO extends ErrorCodeBaseVO { - - @Schema(description = "错误码编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "错误码编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java index f5262697a..70d586d88 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/LoginLogController.java @@ -1,18 +1,17 @@ package cn.iocoder.yudao.module.system.controller.admin.logger; -import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogRespVO; -import cn.iocoder.yudao.module.system.convert.logger.LoginLogConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.module.system.service.logger.LoginLogService; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -25,6 +24,7 @@ import javax.validation.Valid; import java.io.IOException; import java.util.List; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 登录日志") @@ -39,21 +39,21 @@ public class LoginLogController { @GetMapping("/page") @Operation(summary = "获得登录日志分页列表") @PreAuthorize("@ss.hasPermission('system:login-log:query')") - public CommonResult> getLoginLogPage(@Valid LoginLogPageReqVO reqVO) { - PageResult page = loginLogService.getLoginLogPage(reqVO); - return CommonResult.success(LoginLogConvert.INSTANCE.convertPage(page)); + public CommonResult> getLoginLogPage(@Valid LoginLogPageReqVO pageReqVO) { + PageResult pageResult = loginLogService.getLoginLogPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, LoginLogRespVO.class)); } @GetMapping("/export") @Operation(summary = "导出登录日志 Excel") @PreAuthorize("@ss.hasPermission('system:login-log:export')") @OperateLog(type = EXPORT) - public void exportLoginLog(HttpServletResponse response, @Valid LoginLogExportReqVO reqVO) throws IOException { - List list = loginLogService.getLoginLogList(reqVO); - // 拼接数据 - List data = LoginLogConvert.INSTANCE.convertList(list); + public void exportLoginLog(HttpServletResponse response, @Valid LoginLogPageReqVO exportReqVO) throws IOException { + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = loginLogService.getLoginLogPage(exportReqVO).getList(); // 输出 - ExcelUtils.write(response, "登录日志.xls", "数据列表", LoginLogExcelVO.class, data); + ExcelUtils.write(response, "登录日志.xls", "数据列表", LoginLogRespVO.class, + BeanUtils.toBean(list, LoginLogRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java index fc035f471..277aa0a75 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java @@ -1,22 +1,19 @@ package cn.iocoder.yudao.module.system.controller.admin.logger; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -27,12 +24,11 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 操作日志") @@ -49,37 +45,27 @@ public class OperateLogController { @GetMapping("/page") @Operation(summary = "查看操作日志分页列表") @PreAuthorize("@ss.hasPermission('system:operate-log:query')") - public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO reqVO) { - PageResult pageResult = operateLogService.getOperateLogPage(reqVO); - + public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) { + PageResult pageResult = operateLogService.getOperateLogPage(pageReqVO); // 获得拼接需要的数据 - Collection userIds = CollectionUtils.convertList(pageResult.getList(), OperateLogDO::getUserId); - Map userMap = userService.getUserMap(userIds); - // 拼接数据 - List list = new ArrayList<>(pageResult.getList().size()); - pageResult.getList().forEach(operateLog -> { - OperateLogRespVO respVO = OperateLogConvert.INSTANCE.convert(operateLog); - list.add(respVO); - // 拼接用户信息 - MapUtils.findAndThen(userMap, operateLog.getUserId(), user -> respVO.setUserNickname(user.getNickname())); - }); - return success(new PageResult<>(list, pageResult.getTotal())); + Map userMap = userService.getUserMap( + convertList(pageResult.getList(), OperateLogDO::getUserId)); + return success(new PageResult<>(OperateLogConvert.INSTANCE.convertList(pageResult.getList(), userMap), + pageResult.getTotal())); } @Operation(summary = "导出操作日志") @GetMapping("/export") @PreAuthorize("@ss.hasPermission('system:operate-log:export')") @OperateLog(type = EXPORT) - public void exportOperateLog(HttpServletResponse response, @Valid OperateLogExportReqVO reqVO) throws IOException { - List list = operateLogService.getOperateLogList(reqVO); - - // 获得拼接需要的数据 - Collection userIds = CollectionUtils.convertList(list, OperateLogDO::getUserId); - Map userMap = userService.getUserMap(userIds); - // 拼接数据 - List excelDataList = OperateLogConvert.INSTANCE.convertList(list, userMap); + public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException { + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = operateLogService.getOperateLogPage(exportReqVO).getList(); // 输出 - ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogExcelVO.class, excelDataList); + Map userMap = userService.getUserMap( + convertList(list, OperateLogDO::getUserId)); + ExcelUtils.write(response, "操作日志.xls", "数据列表", OperateLogRespVO.class, + OperateLogConvert.INSTANCE.convertList(list, userMap)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java deleted file mode 100644 index 0a8736a80..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogBaseVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -/** - * 登录日志 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class LoginLogBaseVO { - - @Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "日志类型不能为空") - private Integer logType; - - @Schema(description = "链路追踪编号", example = "89aca178-a370-411c-ae02-3f0d672be4ab") - @NotEmpty(message = "链路追踪编号不能为空") - private String traceId; - - @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") - @NotBlank(message = "用户账号不能为空") - @Size(max = 30, message = "用户账号长度不能超过30个字符") - private String username; - - @Schema(description = "登录结果,参见 LoginResultEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "登录结果不能为空") - private Integer result; - - @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - @Schema(description = "浏览器 UserAgent", example = "Mozilla/5.0") - private String userAgent; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExcelVO.java deleted file mode 100644 index 897fe4497..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExcelVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 登录日志 Excel 导出响应 VO - */ -@Data -public class LoginLogExcelVO { - - @ExcelProperty("日志主键") - private Long id; - - @ExcelProperty("用户账号") - private String username; - - @ExcelProperty(value = "日志类型", converter = DictConvert.class) - @DictFormat(DictTypeConstants.LOGIN_TYPE) - private Integer logType; - - @ExcelProperty(value = "登录结果", converter = DictConvert.class) - @DictFormat(DictTypeConstants.LOGIN_RESULT) - private Integer result; - - @ExcelProperty("登录 IP") - private String userIp; - - @ExcelProperty("浏览器 UA") - private String userAgent; - - @ExcelProperty("登录时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java deleted file mode 100644 index d957771e0..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogExportReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 登录日志分页列表 Request VO") -@Data -public class LoginLogExportReqVO { - - @Schema(description = "用户 IP,模拟匹配", example = "127.0.0.1") - private String userIp; - - @Schema(description = "用户账号,模拟匹配", example = "芋道") - private String username; - - @Schema(description = "操作状态", example = "true") - private Boolean status; - - @Schema(description = "登录时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java index 0d69e7d3c..7b9cd165e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java @@ -1,30 +1,57 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @Schema(description = "管理后台 - 登录日志 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class LoginLogRespVO extends LoginLogBaseVO { +@ExcelIgnoreUnannotated +public class LoginLogRespVO { @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("日志主键") private Long id; + @Schema(description = "日志类型,参见 LoginLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "日志类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.LOGIN_TYPE) + private Integer logType; + @Schema(description = "用户编号", example = "666") private Long userId; @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "用户类型不能为空") private Integer userType; + @Schema(description = "链路追踪编号", example = "89aca178-a370-411c-ae02-3f0d672be4ab") + private String traceId; + + @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + @ExcelProperty("用户账号") + private String username; + + @Schema(description = "登录结果,参见 LoginResultEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "登录结果", converter = DictConvert.class) + @DictFormat(DictTypeConstants.LOGIN_RESULT) + private Integer result; + + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") + @ExcelProperty("登录 IP") + private String userIp; + + @Schema(description = "浏览器 UserAgent", example = "Mozilla/5.0") + @ExcelProperty("浏览器 UA") + private String userAgent; + @Schema(description = "登录时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("登录时间") private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java deleted file mode 100644 index c07cc8e1f..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogBaseVO.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.Map; - -/** - * 操作日志 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class OperateLogBaseVO { - - @Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "89aca178-a370-411c-ae02-3f0d672be4ab") - @NotEmpty(message = "链路追踪编号不能为空") - private String traceId; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单") - @NotEmpty(message = "操作模块不能为空") - private String module; - - @Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单") - @NotEmpty(message = "操作名") - private String name; - - @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "操作分类不能为空") - private Integer type; - - @Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") - private String content; - - @Schema(description = "拓展字段", example = "{'orderId': 1}") - private Map exts; - - @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") - @NotEmpty(message = "请求方法名不能为空") - private String requestMethod; - - @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy") - @NotEmpty(message = "请求地址不能为空") - private String requestUrl; - - @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") - @NotEmpty(message = "用户 IP 不能为空") - private String userIp; - - @Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0") - @NotEmpty(message = "浏览器 UserAgent 不能为空") - private String userAgent; - - @Schema(description = "Java 方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "cn.iocoder.yudao.adminserver.UserController.save(...)") - @NotEmpty(message = "Java 方法名不能为空") - private String javaMethod; - - @Schema(description = "Java 方法的参数") - private String javaMethodArgs; - - @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "开始时间不能为空") - private LocalDateTime startTime; - - @Schema(description = "执行时长,单位:毫秒", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "执行时长不能为空") - private Integer duration; - - @Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "结果码不能为空") - private Integer resultCode; - - @Schema(description = "结果提示") - private String resultMsg; - - @Schema(description = "结果数据") - private String resultData; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExcelVO.java deleted file mode 100644 index 8285a9bf5..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExcelVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 操作日志 Excel 导出响应 VO - */ -@Data -public class OperateLogExcelVO { - - @ExcelProperty("日志编号") - private Long id; - - @ExcelProperty("操作模块") - private String module; - - @ExcelProperty("操作名") - private String name; - - @ExcelProperty(value = "操作类型", converter = DictConvert.class) - @DictFormat(DictTypeConstants.OPERATE_TYPE) - private String type; - - @ExcelProperty("操作人") - private String userNickname; - - @ExcelProperty(value = "操作结果") // 成功 or 失败 - private String successStr; - - @ExcelProperty("操作日志") - private LocalDateTime startTime; - - @ExcelProperty("执行时长") - private Integer duration; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java deleted file mode 100644 index b25953027..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogExportReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 操作日志分页列表 Request VO") -@Data -public class OperateLogExportReqVO { - - @Schema(description = "操作模块,模拟匹配", example = "订单") - private String module; - - @Schema(description = "用户昵称,模拟匹配", example = "芋道") - private String userNickname; - - @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", example = "1") - private Integer type; - - @Schema(description = "操作状态", example = "true") - private Boolean success; - - @Schema(description = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] startTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java index 5ed6ae948..3de8d669e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java @@ -1,20 +1,90 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; + +import javax.validation.constraints.NotEmpty; +import java.time.LocalDateTime; +import java.util.Map; @Schema(description = "管理后台 - 操作日志 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class OperateLogRespVO extends OperateLogBaseVO { +@ExcelIgnoreUnannotated +public class OperateLogRespVO { @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("日志编号") private Long id; + @Schema(description = "链路追踪编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "89aca178-a370-411c-ae02-3f0d672be4ab") + private String traceId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long userId; + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("操作人") private String userNickname; + @Schema(description = "操作模块", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单") + @ExcelProperty("操作模块") + private String module; + + @Schema(description = "操作名", requiredMode = Schema.RequiredMode.REQUIRED, example = "创建订单") + @ExcelProperty("操作名") + private String name; + + @Schema(description = "操作分类,参见 OperateLogTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "操作类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.OPERATE_TYPE) + private Integer type; + + @Schema(description = "操作明细", example = "修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。") + private String content; + + @Schema(description = "拓展字段", example = "{'orderId': 1}") + private Map exts; + + @Schema(description = "请求方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "GET") + @NotEmpty(message = "请求方法名不能为空") + private String requestMethod; + + @Schema(description = "请求地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "/xxx/yyy") + private String requestUrl; + + @Schema(description = "用户 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "127.0.0.1") + private String userIp; + + @Schema(description = "浏览器 UserAgent", requiredMode = Schema.RequiredMode.REQUIRED, example = "Mozilla/5.0") + private String userAgent; + + @Schema(description = "Java 方法名", requiredMode = Schema.RequiredMode.REQUIRED, example = "cn.iocoder.yudao.adminserver.UserController.save(...)") + private String javaMethod; + + @Schema(description = "Java 方法的参数") + private String javaMethodArgs; + + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("操作日志") + private LocalDateTime startTime; + + @Schema(description = "执行时长,单位:毫秒", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("执行时长") + private Integer duration; + + @Schema(description = "结果码", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty(value = "结果码") + private Integer resultCode; + + @Schema(description = "结果提示") + private String resultMsg; + + @Schema(description = "结果数据") + private String resultData; + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailAccountController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailAccountController.java index dfffb5d0e..e01b29bb5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailAccountController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailAccountController.java @@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.system.controller.admin.mail; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.*; -import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountRespVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import cn.iocoder.yudao.module.system.service.mail.MailAccountService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -30,14 +33,14 @@ public class MailAccountController { @PostMapping("/create") @Operation(summary = "创建邮箱账号") @PreAuthorize("@ss.hasPermission('system:mail-account:create')") - public CommonResult createMailAccount(@Valid @RequestBody MailAccountCreateReqVO createReqVO) { + public CommonResult createMailAccount(@Valid @RequestBody MailAccountSaveReqVO createReqVO) { return success(mailAccountService.createMailAccount(createReqVO)); } @PutMapping("/update") @Operation(summary = "修改邮箱账号") @PreAuthorize("@ss.hasPermission('system:mail-account:update')") - public CommonResult updateMailAccount(@Valid @RequestBody MailAccountUpdateReqVO updateReqVO) { + public CommonResult updateMailAccount(@Valid @RequestBody MailAccountSaveReqVO updateReqVO) { mailAccountService.updateMailAccount(updateReqVO); return success(true); } @@ -56,23 +59,23 @@ public class MailAccountController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:mail-account:get')") public CommonResult getMailAccount(@RequestParam("id") Long id) { - MailAccountDO mailAccountDO = mailAccountService.getMailAccount(id); - return success(MailAccountConvert.INSTANCE.convert(mailAccountDO)); + MailAccountDO account = mailAccountService.getMailAccount(id); + return success(BeanUtils.toBean(account, MailAccountRespVO.class)); } @GetMapping("/page") @Operation(summary = "获得邮箱账号分页") @PreAuthorize("@ss.hasPermission('system:mail-account:query')") - public CommonResult> getMailAccountPage(@Valid MailAccountPageReqVO pageReqVO) { + public CommonResult> getMailAccountPage(@Valid MailAccountPageReqVO pageReqVO) { PageResult pageResult = mailAccountService.getMailAccountPage(pageReqVO); - return success(MailAccountConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, MailAccountRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping({"/list-all-simple", "simple-list"}) @Operation(summary = "获得邮箱账号精简列表") public CommonResult> getSimpleMailAccountList() { List list = mailAccountService.getMailAccountList(); - return success(MailAccountConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, MailAccountSimpleRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailLogController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailLogController.java index fd9afed85..c2669ec52 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailLogController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailLogController.java @@ -1,16 +1,15 @@ package cn.iocoder.yudao.module.system.controller.admin.mail; - import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogRespVO; -import cn.iocoder.yudao.module.system.convert.mail.MailLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; import cn.iocoder.yudao.module.system.service.mail.MailLogService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,7 +21,6 @@ import javax.validation.Valid; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - @Tag(name = "管理后台 - 邮件日志") @RestController @RequestMapping("/system/mail-log") @@ -36,7 +34,7 @@ public class MailLogController { @PreAuthorize("@ss.hasPermission('system:mail-log:query')") public CommonResult> getMailLogPage(@Valid MailLogPageReqVO pageVO) { PageResult pageResult = mailLogService.getMailLogPage(pageVO); - return success(MailLogConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, MailLogRespVO.class)); } @GetMapping("/get") @@ -44,8 +42,8 @@ public class MailLogController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:mail-log:query')") public CommonResult getMailTemplate(@RequestParam("id") Long id) { - MailLogDO mailLogDO = mailLogService.getMailLog(id); - return success(MailLogConvert.INSTANCE.convert(mailLogDO)); + MailLogDO log = mailLogService.getMailLog(id); + return success(BeanUtils.toBean(log, MailLogRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java index aadcd830a..3a171ee62 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/MailTemplateController.java @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.system.controller.admin.mail; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.*; -import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; import cn.iocoder.yudao.module.system.service.mail.MailSendService; import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -33,14 +33,14 @@ public class MailTemplateController { @PostMapping("/create") @Operation(summary = "创建邮件模版") @PreAuthorize("@ss.hasPermission('system:mail-template:create')") - public CommonResult createMailTemplate(@Valid @RequestBody MailTemplateCreateReqVO createReqVO){ + public CommonResult createMailTemplate(@Valid @RequestBody MailTemplateSaveReqVO createReqVO){ return success(mailTempleService.createMailTemplate(createReqVO)); } @PutMapping("/update") @Operation(summary = "修改邮件模版") @PreAuthorize("@ss.hasPermission('system:mail-template:update')") - public CommonResult updateMailTemplate(@Valid @RequestBody MailTemplateUpdateReqVO updateReqVO){ + public CommonResult updateMailTemplate(@Valid @RequestBody MailTemplateSaveReqVO updateReqVO){ mailTempleService.updateMailTemplate(updateReqVO); return success(true); } @@ -59,8 +59,8 @@ public class MailTemplateController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:mail-template:get')") public CommonResult getMailTemplate(@RequestParam("id") Long id) { - MailTemplateDO mailTemplateDO = mailTempleService.getMailTemplate(id); - return success(MailTemplateConvert.INSTANCE.convert(mailTemplateDO)); + MailTemplateDO template = mailTempleService.getMailTemplate(id); + return success(BeanUtils.toBean(template, MailTemplateRespVO.class)); } @GetMapping("/page") @@ -68,14 +68,14 @@ public class MailTemplateController { @PreAuthorize("@ss.hasPermission('system:mail-template:query')") public CommonResult> getMailTemplatePage(@Valid MailTemplatePageReqVO pageReqVO) { PageResult pageResult = mailTempleService.getMailTemplatePage(pageReqVO); - return success(MailTemplateConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, MailTemplateRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping({"/list-all-simple", "simple-list"}) @Operation(summary = "获得邮件模版精简列表") public CommonResult> getSimpleTemplateList() { List list = mailTempleService.getMailTemplateList(); - return success(MailTemplateConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, MailTemplateSimpleRespVO.class)); } @PostMapping("/send-mail") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountCreateReqVO.java deleted file mode 100644 index 6776ad9f7..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 邮箱账号创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailAccountCreateReqVO extends MailAccountBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java index dcc42f408..c1dc376df 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountRespVO.java @@ -2,22 +2,34 @@ package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @Schema(description = "管理后台 - 邮箱账号 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailAccountRespVO extends MailAccountBaseVO { +public class MailAccountRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") private Long id; + @Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma@123.com") + private String mail; + + @Schema(description = "用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + private String username; + + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + private String password; + + @Schema(description = "SMTP 服务器域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "www.iocoder.cn") + private String host; + + @Schema(description = "SMTP 服务器端口", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") + private Integer port; + + @Schema(description = "是否开启 ssl", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean sslEnable; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountSaveReqVO.java similarity index 87% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountSaveReqVO.java index 799342e58..83a7647eb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountSaveReqVO.java @@ -6,12 +6,12 @@ import lombok.Data; import javax.validation.constraints.Email; import javax.validation.constraints.NotNull; -/** - * 邮箱账号 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 邮箱账号创建/修改 Request VO") @Data -public class MailAccountBaseVO { +public class MailAccountSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; @Schema(description = "邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma@123.com") @NotNull(message = "邮箱不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountUpdateReqVO.java deleted file mode 100644 index e961cc70a..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 邮箱账号修改 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailAccountUpdateReqVO extends MailAccountBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java deleted file mode 100755 index 7ba58b70f..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogBaseVO.java +++ /dev/null @@ -1,75 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** - * 邮件日志 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class MailLogBaseVO { - - @Schema(description = "用户编号", example = "30883") - private Long userId; - - @Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2") - private Byte userType; - - @Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "76854@qq.com") - @NotNull(message = "接收邮箱地址不能为空") - private String toMail; - - @Schema(description = "邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18107") - @NotNull(message = "邮箱账号编号不能为空") - private Long accountId; - - @Schema(description = "发送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "85757@qq.com") - @NotNull(message = "发送邮箱地址不能为空") - private String fromMail; - - @Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5678") - @NotNull(message = "模板编号不能为空") - private Long templateId; - - @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") - @NotNull(message = "模板编码不能为空") - private String templateCode; - - @Schema(description = "模版发送人名称", example = "李四") - private String templateNickname; - - @Schema(description = "邮件标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试标题") - @NotNull(message = "邮件标题不能为空") - private String templateTitle; - - @Schema(description = "邮件内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试内容") - @NotNull(message = "邮件内容不能为空") - private String templateContent; - - @Schema(description = "邮件参数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "邮件参数不能为空") - private Map templateParams; - - @Schema(description = "发送状态,参见 MailSendStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "发送状态不能为空") - private Byte sendStatus; - - @Schema(description = "发送时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime sendTime; - - @Schema(description = "发送返回的消息 ID", example = "28568") - private String sendMessageId; - - @Schema(description = "发送异常") - private String sendException; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java index de553e9a2..fed1d9233 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java @@ -2,20 +2,62 @@ package cn.iocoder.yudao.module.system.controller.admin.mail.vo.log; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; +import java.util.Map; @Schema(description = "管理后台 - 邮件日志 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailLogRespVO extends MailLogBaseVO { +public class MailLogRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31020") private Long id; + @Schema(description = "用户编号", example = "30883") + private Long userId; + + @Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2") + private Byte userType; + + @Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "76854@qq.com") + private String toMail; + + @Schema(description = "邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18107") + private Long accountId; + + @Schema(description = "发送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "85757@qq.com") + private String fromMail; + + @Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5678") + private Long templateId; + + @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") + private String templateCode; + + @Schema(description = "模版发送人名称", example = "李四") + private String templateNickname; + + @Schema(description = "邮件标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试标题") + private String templateTitle; + + @Schema(description = "邮件内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试内容") + private String templateContent; + + @Schema(description = "邮件参数", requiredMode = Schema.RequiredMode.REQUIRED) + private Map templateParams; + + @Schema(description = "发送状态,参见 MailSendStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Byte sendStatus; + + @Schema(description = "发送时间") + private LocalDateTime sendTime; + + @Schema(description = "发送返回的消息 ID", example = "28568") + private String sendMessageId; + + @Schema(description = "发送异常") + private String sendException; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateCreateReqVO.java deleted file mode 100644 index b8b47e3b2..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 邮件模版创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailTemplateCreateReqVO extends MailTemplateBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateRespVO.java index c003b0059..58a9b61a6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateRespVO.java @@ -2,24 +2,44 @@ package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; import java.util.List; @Schema(description = "管理后台 - 邮件末班 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailTemplateRespVO extends MailTemplateBaseVO { +public class MailTemplateRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试名字") + private String name; + + @Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "test") + private String code; + + @Schema(description = "发送的邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long accountId; + + @Schema(description = "发送人名称", example = "芋头") + private String nickname; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "注册成功") + private String title; + + @Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,注册成功啦") + private String content; + @Schema(description = "参数数组", example = "name,code") private List params; + @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "备注", example = "奥特曼") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateSaveReqVO.java similarity index 88% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateSaveReqVO.java index eae1640aa..de316973c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateSaveReqVO.java @@ -6,12 +6,12 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -/** - * 邮件模版 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 邮件模版创建/修改 Request VO") @Data -public class MailTemplateBaseVO { +public class MailTemplateSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; @Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试名字") @NotNull(message = "名称不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateUpdateReqVO.java deleted file mode 100644 index bc99db508..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 邮件模版修改 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class MailTemplateUpdateReqVO extends MailTemplateBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java index 0e1957785..138f2d9ae 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/NoticeController.java @@ -1,16 +1,19 @@ package cn.iocoder.yudao.module.system.controller.admin.notice; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeRespVO; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; import cn.iocoder.yudao.module.system.service.notice.NoticeService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -29,19 +32,22 @@ public class NoticeController { @Resource private NoticeService noticeService; + @Resource + private WebSocketSenderApi webSocketSenderApi; + @PostMapping("/create") @Operation(summary = "创建通知公告") @PreAuthorize("@ss.hasPermission('system:notice:create')") - public CommonResult createNotice(@Valid @RequestBody NoticeCreateReqVO reqVO) { - Long noticeId = noticeService.createNotice(reqVO); + public CommonResult createNotice(@Valid @RequestBody NoticeSaveReqVO createReqVO) { + Long noticeId = noticeService.createNotice(createReqVO); return success(noticeId); } @PutMapping("/update") @Operation(summary = "修改通知公告") @PreAuthorize("@ss.hasPermission('system:notice:update')") - public CommonResult updateNotice(@Valid @RequestBody NoticeUpdateReqVO reqVO) { - noticeService.updateNotice(reqVO); + public CommonResult updateNotice(@Valid @RequestBody NoticeSaveReqVO updateReqVO) { + noticeService.updateNotice(updateReqVO); return success(true); } @@ -57,8 +63,9 @@ public class NoticeController { @GetMapping("/page") @Operation(summary = "获取通知公告列表") @PreAuthorize("@ss.hasPermission('system:notice:query')") - public CommonResult> getNoticePage(@Validated NoticePageReqVO reqVO) { - return success(NoticeConvert.INSTANCE.convertPage(noticeService.getNoticePage(reqVO))); + public CommonResult> getNoticePage(@Validated NoticePageReqVO pageReqVO) { + PageResult pageResult = noticeService.getNoticePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, NoticeRespVO.class)); } @GetMapping("/get") @@ -66,7 +73,20 @@ public class NoticeController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:notice:query')") public CommonResult getNotice(@RequestParam("id") Long id) { - return success(NoticeConvert.INSTANCE.convert(noticeService.getNotice(id))); + NoticeDO notice = noticeService.getNotice(id); + return success(BeanUtils.toBean(notice, NoticeRespVO.class)); + } + + @PostMapping("/push") + @Operation(summary = "推送通知公告", description = "只发送给 websocket 连接在线的用户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:notice:update')") + public CommonResult push(@RequestParam("id") Long id) { + NoticeDO notice = noticeService.getNotice(id); + Assert.notNull(notice, "公告不能为空"); + // 通过 websocket 推送给在线的用户 + webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), "notice-push", notice); + return success(true); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeCreateReqVO.java deleted file mode 100644 index 211f4f0cf..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeCreateReqVO.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.notice.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - 通知公告创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class NoticeCreateReqVO extends NoticeBaseVO { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java index 621c1d301..543f5881e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeRespVO.java @@ -2,18 +2,28 @@ package cn.iocoder.yudao.module.system.controller.admin.notice.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import java.time.LocalDateTime; @Schema(description = "管理后台 - 通知公告信息 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -public class NoticeRespVO extends NoticeBaseVO { +public class NoticeRespVO { @Schema(description = "通知公告序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "公告标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") + private String title; + + @Schema(description = "公告类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") + private Integer type; + + @Schema(description = "公告内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "半生编码") + private String content; + + @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java similarity index 77% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java index efac4df73..4d7e6c872 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java @@ -7,12 +7,13 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 通知公告 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 通知公告创建/修改 Request VO") @Data -public class NoticeBaseVO { +public class NoticeSaveReqVO { + + @Schema(description = "岗位公告编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "岗位公告编号不能为空") + private Long id; @Schema(description = "公告标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") @NotBlank(message = "公告标题不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeUpdateReqVO.java deleted file mode 100644 index 695bd2863..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.notice.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 岗位公告更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class NoticeUpdateReqVO extends NoticeBaseVO { - - @Schema(description = "岗位公告编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "岗位公告编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java index edeef281b..93394ddbb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyMessageController.java @@ -3,15 +3,15 @@ package cn.iocoder.yudao.module.system.controller.admin.notify; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessageMyPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO; -import cn.iocoder.yudao.module.system.convert.notify.NotifyMessageConvert; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO; import cn.iocoder.yudao.module.system.service.notify.NotifyMessageService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -39,8 +39,8 @@ public class NotifyMessageController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:notify-message:query')") public CommonResult getNotifyMessage(@RequestParam("id") Long id) { - NotifyMessageDO notifyMessage = notifyMessageService.getNotifyMessage(id); - return success(NotifyMessageConvert.INSTANCE.convert(notifyMessage)); + NotifyMessageDO message = notifyMessageService.getNotifyMessage(id); + return success(BeanUtils.toBean(message, NotifyMessageRespVO.class)); } @GetMapping("/page") @@ -48,7 +48,7 @@ public class NotifyMessageController { @PreAuthorize("@ss.hasPermission('system:notify-message:query')") public CommonResult> getNotifyMessagePage(@Valid NotifyMessagePageReqVO pageVO) { PageResult pageResult = notifyMessageService.getNotifyMessagePage(pageVO); - return success(NotifyMessageConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, NotifyMessageRespVO.class)); } // ========== 查看自己的站内信 ========== @@ -58,7 +58,7 @@ public class NotifyMessageController { public CommonResult> getMyMyNotifyMessagePage(@Valid NotifyMessageMyPageReqVO pageVO) { PageResult pageResult = notifyMessageService.getMyMyNotifyMessagePage(pageVO, getLoginUserId(), UserTypeEnum.ADMIN.getValue()); - return success(NotifyMessageConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, NotifyMessageRespVO.class)); } @PutMapping("/update-read") @@ -83,13 +83,14 @@ public class NotifyMessageController { @RequestParam(name = "size", defaultValue = "10") Integer size) { List list = notifyMessageService.getUnreadNotifyMessageList( getLoginUserId(), UserTypeEnum.ADMIN.getValue(), size); - return success(NotifyMessageConvert.INSTANCE.convertList(list)); + return success(BeanUtils.toBean(list, NotifyMessageRespVO.class)); } @GetMapping("/get-unread-count") @Operation(summary = "获得当前用户的未读站内信数量") public CommonResult getUnreadNotifyMessageCount() { - return success(notifyMessageService.getUnreadNotifyMessageCount(getLoginUserId(), UserTypeEnum.ADMIN.getValue())); + return success(notifyMessageService.getUnreadNotifyMessageCount( + getLoginUserId(), UserTypeEnum.ADMIN.getValue())); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java index 4a4e2ae33..dc99d3778 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/NotifyTemplateController.java @@ -3,8 +3,11 @@ package cn.iocoder.yudao.module.system.controller.admin.notify; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.*; -import cn.iocoder.yudao.module.system.convert.notify.NotifyTemplateConvert; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSendReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; import cn.iocoder.yudao.module.system.service.notify.NotifySendService; import cn.iocoder.yudao.module.system.service.notify.NotifyTemplateService; @@ -35,14 +38,14 @@ public class NotifyTemplateController { @PostMapping("/create") @Operation(summary = "创建站内信模版") @PreAuthorize("@ss.hasPermission('system:notify-template:create')") - public CommonResult createNotifyTemplate(@Valid @RequestBody NotifyTemplateCreateReqVO createReqVO) { + public CommonResult createNotifyTemplate(@Valid @RequestBody NotifyTemplateSaveReqVO createReqVO) { return success(notifyTemplateService.createNotifyTemplate(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新站内信模版") @PreAuthorize("@ss.hasPermission('system:notify-template:update')") - public CommonResult updateNotifyTemplate(@Valid @RequestBody NotifyTemplateUpdateReqVO updateReqVO) { + public CommonResult updateNotifyTemplate(@Valid @RequestBody NotifyTemplateSaveReqVO updateReqVO) { notifyTemplateService.updateNotifyTemplate(updateReqVO); return success(true); } @@ -61,8 +64,8 @@ public class NotifyTemplateController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:notify-template:query')") public CommonResult getNotifyTemplate(@RequestParam("id") Long id) { - NotifyTemplateDO notifyTemplate = notifyTemplateService.getNotifyTemplate(id); - return success(NotifyTemplateConvert.INSTANCE.convert(notifyTemplate)); + NotifyTemplateDO template = notifyTemplateService.getNotifyTemplate(id); + return success(BeanUtils.toBean(template, NotifyTemplateRespVO.class)); } @GetMapping("/page") @@ -70,7 +73,7 @@ public class NotifyTemplateController { @PreAuthorize("@ss.hasPermission('system:notify-template:query')") public CommonResult> getNotifyTemplatePage(@Valid NotifyTemplatePageReqVO pageVO) { PageResult pageResult = notifyTemplateService.getNotifyTemplatePage(pageVO); - return success(NotifyTemplateConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, NotifyTemplateRespVO.class)); } @PostMapping("/send-notify") @@ -85,5 +88,4 @@ public class NotifyTemplateController { sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams())); } } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java deleted file mode 100644 index 95fa77cc5..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageBaseVO.java +++ /dev/null @@ -1,60 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.notify.vo.message; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.Map; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** - * 站内信消息 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class NotifyMessageBaseVO { - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25025") - @NotNull(message = "用户编号不能为空") - private Long userId; - - @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "用户类型不能为空") - private Byte userType; - - @Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13013") - @NotNull(message = "模版编号不能为空") - private Long templateId; - - @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") - @NotNull(message = "模板编码不能为空") - private String templateCode; - - @Schema(description = "模版发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") - @NotNull(message = "模版发送人名称不能为空") - private String templateNickname; - - @Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试内容") - @NotNull(message = "模版内容不能为空") - private String templateContent; - - @Schema(description = "模版类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "模版类型不能为空") - private Integer templateType; - - @Schema(description = "模版参数", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "模版参数不能为空") - private Map templateParams; - - @Schema(description = "是否已读", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - @NotNull(message = "是否已读不能为空") - private Boolean readStatus; - - @Schema(description = "阅读时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime readTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java index 9da05e151..774ed2a34 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/message/NotifyMessageRespVO.java @@ -2,20 +2,47 @@ package cn.iocoder.yudao.module.system.controller.admin.notify.vo.message; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; +import java.util.Map; @Schema(description = "管理后台 - 站内信 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class NotifyMessageRespVO extends NotifyMessageBaseVO { +public class NotifyMessageRespVO { @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25025") + private Long userId; + + @Schema(description = "用户类型,参见 UserTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Byte userType; + + @Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13013") + private Long templateId; + + @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") + private String templateCode; + + @Schema(description = "模版发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String templateNickname; + + @Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试内容") + private String templateContent; + + @Schema(description = "模版类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer templateType; + + @Schema(description = "模版参数", requiredMode = Schema.RequiredMode.REQUIRED) + private Map templateParams; + + @Schema(description = "是否已读", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean readStatus; + + @Schema(description = "阅读时间") + private LocalDateTime readTime; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateCreateReqVO.java deleted file mode 100644 index eb080a7bf..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateCreateReqVO.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.notify.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -@Schema(description = "管理后台 - 站内信模版创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class NotifyTemplateCreateReqVO extends NotifyTemplateBaseVO { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateRespVO.java index 275b6a827..8d362b800 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateRespVO.java @@ -2,24 +2,41 @@ package cn.iocoder.yudao.module.system.controller.admin.notify.vo.template; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; import java.util.List; @Schema(description = "管理后台 - 站内信模版 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class NotifyTemplateRespVO extends NotifyTemplateBaseVO { +public class NotifyTemplateRespVO { @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版") + private String name; + + @Schema(description = "模版编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SEND_TEST") + private String code; + + @Schema(description = "模版类型,对应 system_notify_template_type 字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer type; + + @Schema(description = "发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆") + private String nickname; + + @Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是模版内容") + private String content; + @Schema(description = "参数数组", example = "name,code") private List params; + @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "备注", example = "我是备注") + private String remark; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java similarity index 88% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java index 72b995ad1..dc4a4cbce 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java @@ -8,12 +8,12 @@ import lombok.Data; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -/** - * 站内信模版 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 站内信模版创建/修改 Request VO") @Data -public class NotifyTemplateBaseVO { +public class NotifyTemplateSaveReqVO { + + @Schema(description = "ID", example = "1024") + private Long id; @Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版") @NotEmpty(message = "模版名称不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSendReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSendReqVO.java index 6a47e8ba9..43b5691b6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSendReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateSendReqVO.java @@ -25,4 +25,5 @@ public class NotifyTemplateSendReqVO { @Schema(description = "模板参数") private Map templateParams; + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateUpdateReqVO.java deleted file mode 100644 index f9e87589d..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notify/vo/template/NotifyTemplateUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.notify.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 站内信模版更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class NotifyTemplateUpdateReqVO extends NotifyTemplateBaseVO { - - @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "ID 不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2ClientController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2ClientController.java index 39a498edc..7aa9bb97a 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2ClientController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2ClientController.java @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.system.controller.admin.oauth2; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientRespVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.auth.OAuth2ClientConvert; +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -33,14 +32,14 @@ public class OAuth2ClientController { @PostMapping("/create") @Operation(summary = "创建 OAuth2 客户端") @PreAuthorize("@ss.hasPermission('system:oauth2-client:create')") - public CommonResult createOAuth2Client(@Valid @RequestBody OAuth2ClientCreateReqVO createReqVO) { + public CommonResult createOAuth2Client(@Valid @RequestBody OAuth2ClientSaveReqVO createReqVO) { return success(oAuth2ClientService.createOAuth2Client(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新 OAuth2 客户端") @PreAuthorize("@ss.hasPermission('system:oauth2-client:update')") - public CommonResult updateOAuth2Client(@Valid @RequestBody OAuth2ClientUpdateReqVO updateReqVO) { + public CommonResult updateOAuth2Client(@Valid @RequestBody OAuth2ClientSaveReqVO updateReqVO) { oAuth2ClientService.updateOAuth2Client(updateReqVO); return success(true); } @@ -59,16 +58,16 @@ public class OAuth2ClientController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:oauth2-client:query')") public CommonResult getOAuth2Client(@RequestParam("id") Long id) { - OAuth2ClientDO oAuth2Client = oAuth2ClientService.getOAuth2Client(id); - return success(OAuth2ClientConvert.INSTANCE.convert(oAuth2Client)); + OAuth2ClientDO client = oAuth2ClientService.getOAuth2Client(id); + return success(BeanUtils.toBean(client, OAuth2ClientRespVO.class)); } @GetMapping("/page") - @Operation(summary = "获得OAuth2 客户端分页") + @Operation(summary = "获得 OAuth2 客户端分页") @PreAuthorize("@ss.hasPermission('system:oauth2-client:query')") public CommonResult> getOAuth2ClientPage(@Valid OAuth2ClientPageReqVO pageVO) { PageResult pageResult = oAuth2ClientService.getOAuth2ClientPage(pageVO); - return success(OAuth2ClientConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, OAuth2ClientRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java index 2ff359235..caa032455 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java @@ -22,10 +22,10 @@ import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService; import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService; import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils; -import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2TokenController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2TokenController.java index d1e0364dc..62827b1b9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2TokenController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2TokenController.java @@ -2,16 +2,16 @@ package cn.iocoder.yudao.module.system.controller.admin.oauth2; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenRespVO; -import cn.iocoder.yudao.module.system.convert.auth.OAuth2TokenConvert; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; import cn.iocoder.yudao.module.system.service.auth.AdminAuthService; import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -35,7 +35,7 @@ public class OAuth2TokenController { @PreAuthorize("@ss.hasPermission('system:oauth2-token:page')") public CommonResult> getAccessTokenPage(@Valid OAuth2AccessTokenPageReqVO reqVO) { PageResult pageResult = oauth2TokenService.getAccessTokenPage(reqVO); - return success(OAuth2TokenConvert.INSTANCE.convert(pageResult)); + return success(BeanUtils.toBean(pageResult, OAuth2AccessTokenRespVO.class)); } @DeleteMapping("/delete") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2UserController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2UserController.java index b56d71484..7236299aa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2UserController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2UserController.java @@ -2,17 +2,18 @@ package cn.iocoder.yudao.module.system.controller.admin.oauth2; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2UserConvert; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.dept.PostService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; @@ -53,16 +54,16 @@ public class OAuth2UserController { public CommonResult getUserInfo() { // 获得用户基本信息 AdminUserDO user = userService.getUser(getLoginUserId()); - OAuth2UserInfoRespVO resp = OAuth2UserConvert.INSTANCE.convert(user); + OAuth2UserInfoRespVO resp = BeanUtils.toBean(user, OAuth2UserInfoRespVO.class); // 获得部门信息 if (user.getDeptId() != null) { DeptDO dept = deptService.getDept(user.getDeptId()); - resp.setDept(OAuth2UserConvert.INSTANCE.convert(dept)); + resp.setDept(BeanUtils.toBean(dept, OAuth2UserInfoRespVO.Dept.class)); } // 获得岗位信息 if (CollUtil.isNotEmpty(user.getPostIds())) { List posts = postService.getPostList(user.getPostIds()); - resp.setPosts(OAuth2UserConvert.INSTANCE.convertList(posts)); + resp.setPosts(BeanUtils.toBean(posts, OAuth2UserInfoRespVO.Post.class)); } return success(resp); } @@ -73,7 +74,7 @@ public class OAuth2UserController { public CommonResult updateUserInfo(@Valid @RequestBody OAuth2UserUpdateReqVO reqVO) { // 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。 // 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做 - userService.updateUserProfile(getLoginUserId(), OAuth2UserConvert.INSTANCE.convert(reqVO)); + userService.updateUserProfile(getLoginUserId(), BeanUtils.toBean(reqVO, UserProfileUpdateReqVO.class)); return success(true); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientCreateReqVO.java deleted file mode 100755 index 033ab9a7e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientCreateReqVO.java +++ /dev/null @@ -1,12 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -@Schema(description = "管理后台 - OAuth2 客户端创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class OAuth2ClientCreateReqVO extends OAuth2ClientBaseVO { - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java index f10f15aa4..2c7c00d32 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientPageReqVO.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; @Schema(description = "管理后台 - OAuth2 客户端分页 Request VO") @Data diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientRespVO.java index 7a106fd97..acd26c7b0 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientRespVO.java @@ -2,20 +2,62 @@ package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - OAuth2 客户端 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class OAuth2ClientRespVO extends OAuth2ClientBaseVO { +public class OAuth2ClientRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou") + private String clientId; + + @Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "fan") + private String secret; + + @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆") + private String name; + + @Schema(description = "应用图标", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") + private String logo; + + @Schema(description = "应用描述", example = "我是一个应用") + private String description; + + @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "访问令牌的有效期", requiredMode = Schema.RequiredMode.REQUIRED, example = "8640") + private Integer accessTokenValiditySeconds; + + @Schema(description = "刷新令牌的有效期", requiredMode = Schema.RequiredMode.REQUIRED, example = "8640000") + private Integer refreshTokenValiditySeconds; + + @Schema(description = "可重定向的 URI 地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn") + private List redirectUris; + + @Schema(description = "授权类型,参见 OAuth2GrantTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "password") + private List authorizedGrantTypes; + + @Schema(description = "授权范围", example = "user_info") + private List scopes; + + @Schema(description = "自动通过的授权范围", example = "user_info") + private List autoApproveScopes; + + @Schema(description = "权限", example = "system:user:query") + private List authorities; + + @Schema(description = "资源", example = "1024") + private List resourceIds; + + @Schema(description = "附加信息", example = "{yunai: true}") + private String additionalInformation; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientSaveReqVO.java similarity index 91% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientSaveReqVO.java index d9f661d5e..fb8f39b0a 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientSaveReqVO.java @@ -11,12 +11,12 @@ import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; -/** -* OAuth2 客户端 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ +@Schema(description = "管理后台 - OAuth2 客户端创建/修改 Request VO") @Data -public class OAuth2ClientBaseVO { +public class OAuth2ClientSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "tudou") @NotNull(message = "客户端编号不能为空") @@ -52,8 +52,7 @@ public class OAuth2ClientBaseVO { @Schema(description = "可重定向的 URI 地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn") @NotNull(message = "可重定向的 URI 地址不能为空") - private List<@NotEmpty(message = "重定向的 URI 不能为空") - @URL(message = "重定向的 URI 格式不正确") String> redirectUris; + private List<@NotEmpty(message = "重定向的 URI 不能为空") @URL(message = "重定向的 URI 格式不正确") String> redirectUris; @Schema(description = "授权类型,参见 OAuth2GrantTypeEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "password") @NotNull(message = "授权类型不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientUpdateReqVO.java deleted file mode 100755 index 8f7d9a095..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/client/OAuth2ClientUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - OAuth2 客户端更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class OAuth2ClientUpdateReqVO extends OAuth2ClientBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java index 4b007ff72..46a14254c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java @@ -2,13 +2,16 @@ package cn.iocoder.yudao.module.system.controller.admin.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.*; -import cn.iocoder.yudao.module.system.convert.permission.MenuConvert; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.service.permission.MenuService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -32,16 +35,16 @@ public class MenuController { @PostMapping("/create") @Operation(summary = "创建菜单") @PreAuthorize("@ss.hasPermission('system:menu:create')") - public CommonResult createMenu(@Valid @RequestBody MenuCreateReqVO reqVO) { - Long menuId = menuService.createMenu(reqVO); + public CommonResult createMenu(@Valid @RequestBody MenuSaveVO createReqVO) { + Long menuId = menuService.createMenu(createReqVO); return success(menuId); } @PutMapping("/update") @Operation(summary = "修改菜单") @PreAuthorize("@ss.hasPermission('system:menu:update')") - public CommonResult updateMenu(@Valid @RequestBody MenuUpdateReqVO reqVO) { - menuService.updateMenu(reqVO); + public CommonResult updateMenu(@Valid @RequestBody MenuSaveVO updateReqVO) { + menuService.updateMenu(updateReqVO); return success(true); } @@ -60,20 +63,17 @@ public class MenuController { public CommonResult> getMenuList(MenuListReqVO reqVO) { List list = menuService.getMenuList(reqVO); list.sort(Comparator.comparing(MenuDO::getSort)); - return success(MenuConvert.INSTANCE.convertList(list)); + return success(BeanUtils.toBean(list, MenuRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping({"/list-all-simple", "simple-list"}) @Operation(summary = "获取菜单精简信息列表", description = "只包含被开启的菜单,用于【角色分配菜单】功能的选项。" + "在多租户的场景下,会只返回租户所在套餐有的菜单") public CommonResult> getSimpleMenuList() { - // 获得菜单列表,只要开启状态的 - MenuListReqVO reqVO = new MenuListReqVO(); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - List list = menuService.getMenuListByTenant(reqVO); - // 排序后,返回给前端 + List list = menuService.getMenuListByTenant( + new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); list.sort(Comparator.comparing(MenuDO::getSort)); - return success(MenuConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, MenuSimpleRespVO.class)); } @GetMapping("/get") @@ -81,7 +81,7 @@ public class MenuController { @PreAuthorize("@ss.hasPermission('system:menu:query')") public CommonResult getMenu(Long id) { MenuDO menu = menuService.getMenu(id); - return success(MenuConvert.INSTANCE.convert(menu)); + return success(BeanUtils.toBean(menu, MenuRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java index 91f5d4266..e808b90eb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/PermissionController.java @@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission. import cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission.PermissionAssignUserRoleReqVO; import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.tenant.TenantService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java index 2df1e74b0..14437a6fc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java @@ -2,16 +2,17 @@ package cn.iocoder.yudao.module.system.controller.admin.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*; -import cn.iocoder.yudao.module.system.convert.permission.RoleConvert; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.service.permission.RoleService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -39,15 +40,15 @@ public class RoleController { @PostMapping("/create") @Operation(summary = "创建角色") @PreAuthorize("@ss.hasPermission('system:role:create')") - public CommonResult createRole(@Valid @RequestBody RoleCreateReqVO reqVO) { - return success(roleService.createRole(reqVO, null)); + public CommonResult createRole(@Valid @RequestBody RoleSaveReqVO createReqVO) { + return success(roleService.createRole(createReqVO, null)); } @PutMapping("/update") @Operation(summary = "修改角色") @PreAuthorize("@ss.hasPermission('system:role:update')") - public CommonResult updateRole(@Valid @RequestBody RoleUpdateReqVO reqVO) { - roleService.updateRole(reqVO); + public CommonResult updateRole(@Valid @RequestBody RoleSaveReqVO updateReqVO) { + roleService.updateRole(updateReqVO); return success(true); } @@ -73,34 +74,35 @@ public class RoleController { @PreAuthorize("@ss.hasPermission('system:role:query')") public CommonResult getRole(@RequestParam("id") Long id) { RoleDO role = roleService.getRole(id); - return success(RoleConvert.INSTANCE.convert(role)); + return success(BeanUtils.toBean(role, RoleRespVO.class)); } @GetMapping("/page") @Operation(summary = "获得角色分页") @PreAuthorize("@ss.hasPermission('system:role:query')") - public CommonResult> getRolePage(RolePageReqVO reqVO) { - return success(roleService.getRolePage(reqVO)); + public CommonResult> getRolePage(RolePageReqVO pageReqVO) { + PageResult pageResult = roleService.getRolePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, RoleRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping({"/list-all-simple", "/simple-list"}) @Operation(summary = "获取角色精简信息列表", description = "只包含被开启的角色,主要用于前端的下拉选项") public CommonResult> getSimpleRoleList() { - // 获得角色列表,只要开启状态的 List list = roleService.getRoleListByStatus(singleton(CommonStatusEnum.ENABLE.getStatus())); - // 排序后,返回给前端 list.sort(Comparator.comparing(RoleDO::getSort)); - return success(RoleConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, RoleSimpleRespVO.class)); } - @GetMapping("/export") + @GetMapping("/export-excel") + @Operation(summary = "导出角色 Excel") @OperateLog(type = EXPORT) @PreAuthorize("@ss.hasPermission('system:role:export')") - public void export(HttpServletResponse response, @Validated RoleExportReqVO reqVO) throws IOException { - List list = roleService.getRoleList(reqVO); - List data = RoleConvert.INSTANCE.convertList03(list); + public void export(HttpServletResponse response, @Validated RolePageReqVO exportReqVO) throws IOException { + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = roleService.getRolePage(exportReqVO).getList(); // 输出 - ExcelUtils.write(response, "角色数据.xls", "角色列表", RoleExcelVO.class, data); + ExcelUtils.write(response, "角色数据.xls", "数据", RoleRespVO.class, + BeanUtils.toBean(list, RoleRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuCreateReqVO.java deleted file mode 100644 index 56721b7fe..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuCreateReqVO.java +++ /dev/null @@ -1,10 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -@Schema(description = "管理后台 - 菜单创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class MenuCreateReqVO extends MenuBaseVO { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java index d50be7579..b3b7f2d07 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java @@ -13,4 +13,4 @@ public class MenuListReqVO { @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") private Integer status; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java index 6cd9bd174..ccd443405 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java @@ -1,26 +1,68 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import java.time.LocalDateTime; @Schema(description = "管理后台 - 菜单信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class MenuRespVO extends MenuBaseVO { +public class MenuRespVO { @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @NotBlank(message = "菜单名称不能为空") + @Size(max = 50, message = "菜单名称长度不能超过50个字符") + private String name; + + @Schema(description = "权限标识,仅菜单类型为按钮时,才需要传递", example = "sys:menu:add") + @Size(max = 100) + private String permission; + + @Schema(description = "类型,参见 MenuTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "菜单类型不能为空") + private Integer type; + + @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "显示顺序不能为空") + private Integer sort; + + @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "父菜单 ID 不能为空") + private Long parentId; + + @Schema(description = "路由地址,仅菜单类型为菜单或者目录时,才需要传", example = "post") + @Size(max = 200, message = "路由地址不能超过200个字符") + private String path; + + @Schema(description = "菜单图标,仅菜单类型为菜单或者目录时,才需要传", example = "/menu/list") + private String icon; + + @Schema(description = "组件路径,仅菜单类型为菜单时,才需要传", example = "system/post/index") + @Size(max = 200, message = "组件路径不能超过255个字符") + private String component; + + @Schema(description = "组件名", example = "SystemUser") + private String componentName; + + @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") private Integer status; + @Schema(description = "是否可见", example = "false") + private Boolean visible; + + @Schema(description = "是否缓存", example = "false") + private Boolean keepAlive; + + @Schema(description = "是否总是显示", example = "false") + private Boolean alwaysShow; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java similarity index 92% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java index 29e6c36ea..8b91af1b8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSaveVO.java @@ -7,12 +7,12 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 菜单 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 菜单创建/修改 Request VO") @Data -public class MenuBaseVO { +public class MenuSaveVO { + + @Schema(description = "菜单编号", example = "1024") + private Long id; @Schema(description = "菜单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") @NotBlank(message = "菜单名称不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java index c3fc859bf..bb94601db 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuSimpleRespVO.java @@ -1,14 +1,10 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; @Schema(description = "管理后台 - 菜单精简信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor public class MenuSimpleRespVO { @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuUpdateReqVO.java deleted file mode 100644 index 3d96434de..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 菜单更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class MenuUpdateReqVO extends MenuBaseVO { - - @Schema(description = "菜单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "菜单编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java index 2957898e8..f70426d31 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/permission/PermissionAssignRoleDataScopeReqVO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.permission; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -17,7 +19,7 @@ public class PermissionAssignRoleDataScopeReqVO { @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "数据范围不能为空") -// TODO 这里要多一个枚举校验 + @InEnum(value = DataScopeEnum.class, message = "数据范围必须是 {value}") private Integer dataScope; @Schema(description = "部门编号列表,只有范围类型为 DEPT_CUSTOM 时,该字段才需要", example = "1,3,5") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleCreateReqVO.java deleted file mode 100644 index ac4cd8a3e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleCreateReqVO.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; - - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - 角色创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class RoleCreateReqVO extends RoleBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExcelVO.java deleted file mode 100644 index d22cf9bf2..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExcelVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -/** - * 角色 Excel 导出响应 VO - */ -@Data -public class RoleExcelVO { - - @ExcelProperty("角色序号") - private Long id; - - @ExcelProperty("角色名称") - private String name; - - @ExcelProperty("角色标志") - private String code; - - @ExcelProperty("角色排序") - private Integer sort; - - @ExcelProperty("数据范围") - private Integer dataScope; - - @ExcelProperty(value = "角色状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private String status; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java deleted file mode 100644 index ae719c04b..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleExportReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 角色分页 Request VO") -@Data -public class RoleExportReqVO { - - @Schema(description = "角色名称,模糊匹配", example = "芋道") - private String name; - - @Schema(description = "角色标识,模糊匹配", example = "yudao") - private String code; - - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - - @Schema(description = "开始时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java index 7eeb1493c..2e15ee4f7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java @@ -1,36 +1,56 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import javax.validation.constraints.NotBlank; import java.time.LocalDateTime; import java.util.Set; @Schema(description = "管理后台 - 角色信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class RoleRespVO extends RoleBaseVO { +@ExcelIgnoreUnannotated +public class RoleRespVO { @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("角色序号") private Long id; - @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer dataScope; + @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "管理员") + @ExcelProperty("角色名称") + private String name; - @Schema(description = "数据范围(指定部门数组)", example = "1") - private Set dataScopeDeptIds; + @NotBlank(message = "角色标志不能为空") + @ExcelProperty("角色标志") + private String code; + + @Schema(description = "显示顺序不能为空", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("角色排序") + private Integer sort; @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "角色状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; @Schema(description = "角色类型,参见 RoleTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer type; + @Schema(description = "备注", example = "我是一个角色") + private String remark; + + @Schema(description = "数据范围,参见 DataScopeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("数据范围") + private Integer dataScope; + + @Schema(description = "数据范围(指定部门数组)", example = "1") + private Set dataScopeDeptIds; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java similarity index 84% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java index f03ac05e1..5a59b5f4c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSaveReqVO.java @@ -7,12 +7,12 @@ import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -/** - * 角色 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 角色创建 Request VO") @Data -public class RoleBaseVO { +public class RoleSaveReqVO { + + @Schema(description = "角色编号", example = "1") + private Long id; @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "管理员") @NotBlank(message = "角色名称不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java index bd177148e..c9e174dd2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleSimpleRespVO.java @@ -1,14 +1,10 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; @Schema(description = "管理后台 - 角色精简信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor public class RoleSimpleRespVO { @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateReqVO.java deleted file mode 100644 index 713989c19..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 角色更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class RoleUpdateReqVO extends RoleBaseVO { - - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "角色编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/SensitiveWordController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/SensitiveWordController.java index ab0a129df..f2231d897 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/SensitiveWordController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/SensitiveWordController.java @@ -1,16 +1,19 @@ package cn.iocoder.yudao.module.system.controller.admin.sensitiveword; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.*; -import cn.iocoder.yudao.module.system.convert.sensitiveword.SensitiveWordConvert; +import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordRespVO; +import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; import cn.iocoder.yudao.module.system.service.sensitiveword.SensitiveWordService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -37,14 +40,14 @@ public class SensitiveWordController { @PostMapping("/create") @Operation(summary = "创建敏感词") @PreAuthorize("@ss.hasPermission('system:sensitive-word:create')") - public CommonResult createSensitiveWord(@Valid @RequestBody SensitiveWordCreateReqVO createReqVO) { + public CommonResult createSensitiveWord(@Valid @RequestBody SensitiveWordSaveVO createReqVO) { return success(sensitiveWordService.createSensitiveWord(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新敏感词") @PreAuthorize("@ss.hasPermission('system:sensitive-word:update')") - public CommonResult updateSensitiveWord(@Valid @RequestBody SensitiveWordUpdateReqVO updateReqVO) { + public CommonResult updateSensitiveWord(@Valid @RequestBody SensitiveWordSaveVO updateReqVO) { sensitiveWordService.updateSensitiveWord(updateReqVO); return success(true); } @@ -64,7 +67,7 @@ public class SensitiveWordController { @PreAuthorize("@ss.hasPermission('system:sensitive-word:query')") public CommonResult getSensitiveWord(@RequestParam("id") Long id) { SensitiveWordDO sensitiveWord = sensitiveWordService.getSensitiveWord(id); - return success(SensitiveWordConvert.INSTANCE.convert(sensitiveWord)); + return success(BeanUtils.toBean(sensitiveWord, SensitiveWordRespVO.class)); } @GetMapping("/page") @@ -72,19 +75,20 @@ public class SensitiveWordController { @PreAuthorize("@ss.hasPermission('system:sensitive-word:query')") public CommonResult> getSensitiveWordPage(@Valid SensitiveWordPageReqVO pageVO) { PageResult pageResult = sensitiveWordService.getSensitiveWordPage(pageVO); - return success(SensitiveWordConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, SensitiveWordRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出敏感词 Excel") @PreAuthorize("@ss.hasPermission('system:sensitive-word:export')") @OperateLog(type = EXPORT) - public void exportSensitiveWordExcel(@Valid SensitiveWordExportReqVO exportReqVO, + public void exportSensitiveWordExcel(@Valid SensitiveWordPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = sensitiveWordService.getSensitiveWordList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = sensitiveWordService.getSensitiveWordPage(exportReqVO).getList(); // 导出 Excel - List datas = SensitiveWordConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "敏感词.xls", "数据", SensitiveWordExcelVO.class, datas); + ExcelUtils.write(response, "敏感词.xls", "数据", SensitiveWordRespVO.class, + BeanUtils.toBean(list, SensitiveWordRespVO.class)); } @GetMapping("/get-tags") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordCreateReqVO.java deleted file mode 100644 index 2e2e89df5..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 敏感词创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SensitiveWordCreateReqVO extends SensitiveWordBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExcelVO.java deleted file mode 100644 index 29409cbe3..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExcelVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 敏感词 Excel VO - * - * @author 永不言败 - */ -@Data -public class SensitiveWordExcelVO { - - @ExcelProperty("编号") - private Long id; - - @ExcelProperty("敏感词") - private String name; - - @ExcelProperty(value = "标签", converter = JsonConvert.class) - private List tags; - - @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private Integer status; - - @ExcelProperty("描述") - private String description; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java deleted file mode 100644 index d84af0132..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordExportReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 敏感词 Excel 导出 Request VO,参数和 SensitiveWordPageReqVO 是一致的") -@Data -public class SensitiveWordExportReqVO { - - @Schema(description = "敏感词", example = "敏感词") - private String name; - - @Schema(description = "标签", example = "短信,评论") - private String tag; - - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java index 33659cc66..642773a55 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordPageReqVO.java @@ -30,4 +30,4 @@ public class SensitiveWordPageReqVO extends PageParam { @Schema(description = "创建时间") private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordRespVO.java index 750d733cf..250a044a7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordRespVO.java @@ -1,22 +1,43 @@ package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - 敏感词 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SensitiveWordRespVO extends SensitiveWordBaseVO { +public class SensitiveWordRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("编号") private Long id; + @Schema(description = "敏感词", requiredMode = Schema.RequiredMode.REQUIRED, example = "敏感词") + @ExcelProperty("敏感词") + private String name; + + @Schema(description = "标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "短信,评论") + @ExcelProperty(value = "标签", converter = JsonConvert.class) + private List tags; + + @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "描述", example = "污言秽语") + @ExcelProperty("描述") + private String description; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordSaveVO.java similarity index 80% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordSaveVO.java index b2ae46d17..c7b2fbd89 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordSaveVO.java @@ -6,12 +6,12 @@ import lombok.Data; import javax.validation.constraints.NotNull; import java.util.List; -/** - * 敏感词 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 敏感词创建/修改 Request VO") @Data -public class SensitiveWordBaseVO { +public class SensitiveWordSaveVO { + + @Schema(description = "编号", example = "1") + private Long id; @Schema(description = "敏感词", requiredMode = Schema.RequiredMode.REQUIRED, example = "敏感词") @NotNull(message = "敏感词不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordUpdateReqVO.java deleted file mode 100644 index 7c8100383..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sensitiveword/vo/SensitiveWordUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 敏感词更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SensitiveWordUpdateReqVO extends SensitiveWordBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java index b6512a601..79ff7b80d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsChannelController.java @@ -1,14 +1,17 @@ package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.*; -import cn.iocoder.yudao.module.system.convert.sms.SmsChannelConvert; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; -import cn.iocoder.yudao.module.system.service.sms.SmsChannelService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelRespVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSimpleRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.module.system.service.sms.SmsChannelService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -30,14 +33,14 @@ public class SmsChannelController { @PostMapping("/create") @Operation(summary = "创建短信渠道") @PreAuthorize("@ss.hasPermission('system:sms-channel:create')") - public CommonResult createSmsChannel(@Valid @RequestBody SmsChannelCreateReqVO createReqVO) { + public CommonResult createSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO createReqVO) { return success(smsChannelService.createSmsChannel(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新短信渠道") @PreAuthorize("@ss.hasPermission('system:sms-channel:update')") - public CommonResult updateSmsChannel(@Valid @RequestBody SmsChannelUpdateReqVO updateReqVO) { + public CommonResult updateSmsChannel(@Valid @RequestBody SmsChannelSaveReqVO updateReqVO) { smsChannelService.updateSmsChannel(updateReqVO); return success(true); } @@ -56,8 +59,8 @@ public class SmsChannelController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:sms-channel:query')") public CommonResult getSmsChannel(@RequestParam("id") Long id) { - SmsChannelDO smsChannel = smsChannelService.getSmsChannel(id); - return success(SmsChannelConvert.INSTANCE.convert(smsChannel)); + SmsChannelDO channel = smsChannelService.getSmsChannel(id); + return success(BeanUtils.toBean(channel, SmsChannelRespVO.class)); } @GetMapping("/page") @@ -65,16 +68,15 @@ public class SmsChannelController { @PreAuthorize("@ss.hasPermission('system:sms-channel:query')") public CommonResult> getSmsChannelPage(@Valid SmsChannelPageReqVO pageVO) { PageResult pageResult = smsChannelService.getSmsChannelPage(pageVO); - return success(SmsChannelConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, SmsChannelRespVO.class)); } - @GetMapping("/list-all-simple") + @GetMapping({"/list-all-simple", "/simple-list"}) @Operation(summary = "获得短信渠道精简列表", description = "包含被禁用的短信渠道") public CommonResult> getSimpleSmsChannelList() { List list = smsChannelService.getSmsChannelList(); - // 排序后,返回给前端 list.sort(Comparator.comparing(SmsChannelDO::getId)); - return success(SmsChannelConvert.INSTANCE.convertList03(list)); + return success(BeanUtils.toBean(list, SmsChannelSimpleRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java index 27b957bd6..fda06b8de 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsLogController.java @@ -1,18 +1,17 @@ package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO; -import cn.iocoder.yudao.module.system.convert.sms.SmsLogConvert; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; -import cn.iocoder.yudao.module.system.service.sms.SmsLogService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import io.swagger.v3.oas.annotations.tags.Tag; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; +import cn.iocoder.yudao.module.system.service.sms.SmsLogService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -40,21 +39,22 @@ public class SmsLogController { @GetMapping("/page") @Operation(summary = "获得短信日志分页") @PreAuthorize("@ss.hasPermission('system:sms-log:query')") - public CommonResult> getSmsLogPage(@Valid SmsLogPageReqVO pageVO) { - PageResult pageResult = smsLogService.getSmsLogPage(pageVO); - return success(SmsLogConvert.INSTANCE.convertPage(pageResult)); + public CommonResult> getSmsLogPage(@Valid SmsLogPageReqVO pageReqVO) { + PageResult pageResult = smsLogService.getSmsLogPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, SmsLogRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出短信日志 Excel") @PreAuthorize("@ss.hasPermission('system:sms-log:export')") @OperateLog(type = EXPORT) - public void exportSmsLogExcel(@Valid SmsLogExportReqVO exportReqVO, + public void exportSmsLogExcel(@Valid SmsLogPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = smsLogService.getSmsLogList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = smsLogService.getSmsLogPage(exportReqVO).getList(); // 导出 Excel - List datas = SmsLogConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "短信日志.xls", "数据", SmsLogExcelVO.class, datas); + ExcelUtils.write(response, "短信日志.xls", "数据", SmsLogRespVO.class, + BeanUtils.toBean(list, SmsLogRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java index 173d8f643..571717741 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsTemplateController.java @@ -1,17 +1,21 @@ package cn.iocoder.yudao.module.system.controller.admin.sms; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.*; -import cn.iocoder.yudao.module.system.convert.sms.SmsTemplateConvert; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; -import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService; -import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.service.sms.SmsSendService; +import cn.iocoder.yudao.module.system.service.sms.SmsTemplateService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -37,14 +41,14 @@ public class SmsTemplateController { @PostMapping("/create") @Operation(summary = "创建短信模板") @PreAuthorize("@ss.hasPermission('system:sms-template:create')") - public CommonResult createSmsTemplate(@Valid @RequestBody SmsTemplateCreateReqVO createReqVO) { + public CommonResult createSmsTemplate(@Valid @RequestBody SmsTemplateSaveReqVO createReqVO) { return success(smsTemplateService.createSmsTemplate(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新短信模板") @PreAuthorize("@ss.hasPermission('system:sms-template:update')") - public CommonResult updateSmsTemplate(@Valid @RequestBody SmsTemplateUpdateReqVO updateReqVO) { + public CommonResult updateSmsTemplate(@Valid @RequestBody SmsTemplateSaveReqVO updateReqVO) { smsTemplateService.updateSmsTemplate(updateReqVO); return success(true); } @@ -63,8 +67,8 @@ public class SmsTemplateController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:sms-template:query')") public CommonResult getSmsTemplate(@RequestParam("id") Long id) { - SmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplate(id); - return success(SmsTemplateConvert.INSTANCE.convert(smsTemplate)); + SmsTemplateDO template = smsTemplateService.getSmsTemplate(id); + return success(BeanUtils.toBean(template, SmsTemplateRespVO.class)); } @GetMapping("/page") @@ -72,19 +76,20 @@ public class SmsTemplateController { @PreAuthorize("@ss.hasPermission('system:sms-template:query')") public CommonResult> getSmsTemplatePage(@Valid SmsTemplatePageReqVO pageVO) { PageResult pageResult = smsTemplateService.getSmsTemplatePage(pageVO); - return success(SmsTemplateConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, SmsTemplateRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出短信模板 Excel") @PreAuthorize("@ss.hasPermission('system:sms-template:export')") @OperateLog(type = EXPORT) - public void exportSmsTemplateExcel(@Valid SmsTemplateExportReqVO exportReqVO, + public void exportSmsTemplateExcel(@Valid SmsTemplatePageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = smsTemplateService.getSmsTemplateList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = smsTemplateService.getSmsTemplatePage(exportReqVO).getList(); // 导出 Excel - List datas = SmsTemplateConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "短信模板.xls", "数据", SmsTemplateExcelVO.class, datas); + ExcelUtils.write(response, "短信模板.xls", "数据", SmsTemplateRespVO.class, + BeanUtils.toBean(list, SmsTemplateRespVO.class)); } @PostMapping("/send-sms") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java deleted file mode 100644 index 7e052de57..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelCreateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 短信渠道创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsChannelCreateReqVO extends SmsChannelBaseVO { - - @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN") - @NotNull(message = "渠道编码不能为空") - private String code; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java index 040f5bc24..70b709e2c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelRespVO.java @@ -2,23 +2,43 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; +import org.hibernate.validator.constraints.URL; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; @Schema(description = "管理后台 - 短信渠道 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsChannelRespVO extends SmsChannelBaseVO { +public class SmsChannelRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + @NotNull(message = "短信签名不能为空") + private String signature; + @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN") private String code; + @Schema(description = "启用状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "启用状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "好吃!") + private String remark; + + @Schema(description = "短信 API 的账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + @NotNull(message = "短信 API 的账号不能为空") + private String apiKey; + + @Schema(description = "短信 API 的密钥", example = "yuanma") + private String apiSecret; + + @Schema(description = "短信发送回调 URL", example = "https://www.iocoder.cn") + @URL(message = "回调 URL 格式不正确") + private String callbackUrl; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSaveReqVO.java similarity index 74% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSaveReqVO.java index 7d0cee8b1..47cde1ee2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSaveReqVO.java @@ -6,17 +6,21 @@ import org.hibernate.validator.constraints.URL; import javax.validation.constraints.NotNull; -/** -* 短信渠道 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ +@Schema(description = "管理后台 - 短信渠道创建/修改 Request VO") @Data -public class SmsChannelBaseVO { +public class SmsChannelSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; @Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") @NotNull(message = "短信签名不能为空") private String signature; + @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN") + @NotNull(message = "渠道编码不能为空") + private String code; + @Schema(description = "启用状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "启用状态不能为空") private Integer status; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java index 560a39e91..350297ce3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelSimpleRespVO.java @@ -3,18 +3,14 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import javax.validation.constraints.NotNull; - @Schema(description = "管理后台 - 短信渠道精简 Response VO") @Data public class SmsChannelSimpleRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") private Long id; @Schema(description = "短信签名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") - @NotNull(message = "短信签名不能为空") private String signature; @Schema(description = "渠道编码,参见 SmsChannelEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "YUN_PIAN") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelUpdateReqVO.java deleted file mode 100644 index 594854705..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/channel/SmsChannelUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 短信渠道更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsChannelUpdateReqVO extends SmsChannelBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java deleted file mode 100644 index f84da74ac..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExcelVO.java +++ /dev/null @@ -1,100 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.Map; - -/** - * 短信日志 Excel VO - * - * @author 芋道源码 - */ -@Data -public class SmsLogExcelVO { - - @ExcelProperty("编号") - private Long id; - - @ExcelProperty("短信渠道编号") - private Long channelId; - - @ExcelProperty("短信渠道编码") - private String channelCode; - - @ExcelProperty("模板编号") - private Long templateId; - - @ExcelProperty("模板编码") - private String templateCode; - - @ExcelProperty(value = "短信类型", converter = DictConvert.class) - @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE) - private Integer templateType; - - @ExcelProperty("短信内容") - private String templateContent; - - @ExcelProperty(value = "短信参数", converter = JsonConvert.class) - private Map templateParams; - - @ExcelProperty("短信 API 的模板编号") - private String apiTemplateId; - - @ExcelProperty("手机号") - private String mobile; - - @ExcelProperty("用户编号") - private Long userId; - - @ExcelProperty(value = "用户类型", converter = DictConvert.class) - @DictFormat(DictTypeConstants.USER_TYPE) - private Integer userType; - - @ExcelProperty(value = "发送状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.SMS_SEND_STATUS) - private Integer sendStatus; - - @ExcelProperty("发送时间") - private LocalDateTime sendTime; - - @ExcelProperty("发送结果的编码") - private Integer sendCode; - - @ExcelProperty("发送结果的提示") - private String sendMsg; - - @ExcelProperty("短信 API 发送结果的编码") - private String apiSendCode; - - @ExcelProperty("短信 API 发送失败的提示") - private String apiSendMsg; - - @ExcelProperty("短信 API 发送返回的唯一请求 ID") - private String apiRequestId; - - @ExcelProperty("短信 API 发送返回的序号") - private String apiSerialNo; - - @ExcelProperty(value = "接收状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.SMS_RECEIVE_STATUS) - private Integer receiveStatus; - - @ExcelProperty("接收时间") - private LocalDateTime receiveTime; - - @ExcelProperty("API 接收结果的编码") - private String apiReceiveCode; - - @ExcelProperty("API 接收结果的说明") - private String apiReceiveMsg; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java deleted file mode 100644 index 79f1e7d27..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogExportReqVO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 短信日志 Excel 导出 Request VO,参数和 SmsLogPageReqVO 是一致的") -@Data -public class SmsLogExportReqVO { - - @Schema(description = "短信渠道编号", example = "10") - private Long channelId; - - @Schema(description = "模板编号", example = "20") - private Long templateId; - - @Schema(description = "手机号", example = "15601691300") - private String mobile; - - @Schema(description = "发送状态", example = "1") - private Integer sendStatus; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "开始发送时间") - private LocalDateTime[] sendTime; - - @Schema(description = "接收状态", example = "0") - private Integer receiveStatus; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "开始接收时间") - private LocalDateTime[] receiveTime; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java index 6f31e6d04..77409ed91 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java @@ -1,5 +1,11 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.log; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -8,81 +14,103 @@ import java.util.Map; @Schema(description = "管理后台 - 短信日志 Response VO") @Data +@ExcelIgnoreUnannotated public class SmsLogRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") private Long id; @Schema(description = "短信渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("短信渠道编号") private Long channelId; @Schema(description = "短信渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ALIYUN") + @ExcelProperty("短信渠道编码") private String channelCode; @Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + @ExcelProperty("模板编号") private Long templateId; @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test-01") + @ExcelProperty("模板编码") private String templateCode; @Schema(description = "短信类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "短信类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE) private Integer templateType; @Schema(description = "短信内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你的验证码是 1024") + @ExcelProperty("短信内容") private String templateContent; @Schema(description = "短信参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "name,code") + @ExcelProperty(value = "短信参数", converter = JsonConvert.class) private Map templateParams; @Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SMS_207945135") + @ExcelProperty("短信 API 的模板编号") private String apiTemplateId; @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") + @ExcelProperty("手机号") private String mobile; @Schema(description = "用户编号", example = "10") + @ExcelProperty("用户编号") private Long userId; @Schema(description = "用户类型", example = "1") + @ExcelProperty(value = "用户类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.USER_TYPE) private Integer userType; @Schema(description = "发送状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "发送状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.SMS_SEND_STATUS) private Integer sendStatus; @Schema(description = "发送时间") + @ExcelProperty("发送时间") private LocalDateTime sendTime; - @Schema(description = "发送结果的编码", example = "0") - private Integer sendCode; - - @Schema(description = "发送结果的提示", example = "成功") - private String sendMsg; - @Schema(description = "短信 API 发送结果的编码", example = "SUCCESS") + @ExcelProperty("短信 API 发送结果的编码") private String apiSendCode; @Schema(description = "短信 API 发送失败的提示", example = "成功") + @ExcelProperty("短信 API 发送失败的提示") private String apiSendMsg; @Schema(description = "短信 API 发送返回的唯一请求 ID", example = "3837C6D3-B96F-428C-BBB2-86135D4B5B99") + @ExcelProperty("短信 API 发送返回的唯一请求 ID") private String apiRequestId; @Schema(description = "短信 API 发送返回的序号", example = "62923244790") + @ExcelProperty("短信 API 发送返回的序号") private String apiSerialNo; @Schema(description = "接收状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "接收状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.SMS_RECEIVE_STATUS) private Integer receiveStatus; @Schema(description = "接收时间") + @ExcelProperty("接收时间") private LocalDateTime receiveTime; @Schema(description = "API 接收结果的编码", example = "DELIVRD") + @ExcelProperty("API 接收结果的编码") private String apiReceiveCode; @Schema(description = "API 接收结果的说明", example = "用户接收成功") + @ExcelProperty("API 接收结果的说明") private String apiReceiveMsg; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateCreateReqVO.java deleted file mode 100644 index 069ebb127..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 短信模板创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsTemplateCreateReqVO extends SmsTemplateBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExcelVO.java deleted file mode 100644 index f4f34bd1d..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExcelVO.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 短信模板 Excel VO - * - * @author 芋道源码 - */ -@Data -public class SmsTemplateExcelVO { - - @ExcelProperty("编号") - private Long id; - - @ExcelProperty(value = "短信签名", converter = DictConvert.class) - @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE) - private Integer type; - - @ExcelProperty(value = "开启状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private Integer status; - - @ExcelProperty("模板编码") - private String code; - - @ExcelProperty("模板名称") - private String name; - - @ExcelProperty("模板内容") - private String content; - - @ExcelProperty("备注") - private String remark; - - @ExcelProperty("短信 API 的模板编号") - private String apiTemplateId; - - @ExcelProperty("短信渠道编号") - private Long channelId; - - @ExcelProperty(value = "短信渠道编码", converter = DictConvert.class) - @DictFormat(DictTypeConstants.SMS_CHANNEL_CODE) - private String channelCode; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java deleted file mode 100644 index 0395b365e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateExportReqVO.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 短信模板 Excel 导出 Request VO,参数和 SmsTemplatePageReqVO 是一致的") -@Data -public class SmsTemplateExportReqVO { - - @Schema(description = "短信签名", example = "1") - private Integer type; - - @Schema(description = "开启状态", example = "1") - private Integer status; - - @Schema(description = "模板编码,模糊匹配", example = "test_01") - private String code; - - @Schema(description = "模板内容,模糊匹配", example = "你好,{name}。你长的太{like}啦!") - private String content; - - @Schema(description = "短信 API 的模板编号,模糊匹配", example = "4383920") - private String apiTemplateId; - - @Schema(description = "短信渠道编号", example = "10") - private Long channelId; - - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @Schema(description = "创建时间") - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java index bfe3964d9..acf99e380 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplatePageReqVO.java @@ -39,4 +39,4 @@ public class SmsTemplatePageReqVO extends PageParam { @Schema(description = "创建时间") private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java index 3139d20dc..6b8aecaaa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java @@ -1,29 +1,69 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; import java.util.List; @Schema(description = "管理后台 - 短信模板 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsTemplateRespVO extends SmsTemplateBaseVO { +@ExcelIgnoreUnannotated +public class SmsTemplateRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") private Long id; - @Schema(description = "短信渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ALIYUN") - private String channelCode; + @Schema(description = "短信类型,参见 SmsTemplateTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "短信签名", converter = DictConvert.class) + @DictFormat(DictTypeConstants.SMS_TEMPLATE_TYPE) + private Integer type; + + @Schema(description = "开启状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") + @ExcelProperty("模板编码") + private String code; + + @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + @ExcelProperty("模板名称") + private String name; + + @Schema(description = "模板内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,{name}。你长的太{like}啦!") + @ExcelProperty("模板内容") + private String content; @Schema(description = "参数数组", example = "name,code") private List params; + @Schema(description = "备注", example = "哈哈哈") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4383920") + @ExcelProperty("短信 API 的模板编号") + private String apiTemplateId; + + @Schema(description = "短信渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("短信渠道编号") + private Long channelId; + + @Schema(description = "短信渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ALIYUN") + @ExcelProperty(value = "短信渠道编码", converter = DictConvert.class) + @DictFormat(DictTypeConstants.SMS_CHANNEL_CODE) + private String channelCode; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java similarity index 89% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java index 6fc337a60..7199bf39c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java @@ -5,12 +5,12 @@ import lombok.Data; import javax.validation.constraints.NotNull; -/** -* 短信模板 Base VO,提供给添加、修改、详细的子 VO 使用 -* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 -*/ +@Schema(description = "管理后台 - 短信模板创建/修改 Request VO") @Data -public class SmsTemplateBaseVO { +public class SmsTemplateSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; @Schema(description = "短信类型,参见 SmsTemplateTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "短信类型不能为空") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateUpdateReqVO.java deleted file mode 100644 index d347f6950..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 短信模板更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SmsTemplateUpdateReqVO extends SmsTemplateBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialClientController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialClientController.java index 893523630..c9b5f4da7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialClientController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialClientController.java @@ -2,11 +2,10 @@ package cn.iocoder.yudao.module.system.controller.admin.socail; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientRespVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.social.SocialClientConvert; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.service.social.SocialClientService; import io.swagger.v3.oas.annotations.Operation; @@ -33,14 +32,14 @@ public class SocialClientController { @PostMapping("/create") @Operation(summary = "创建社交客户端") @PreAuthorize("@ss.hasPermission('system:social-client:create')") - public CommonResult createSocialClient(@Valid @RequestBody SocialClientCreateReqVO createReqVO) { + public CommonResult createSocialClient(@Valid @RequestBody SocialClientSaveReqVO createReqVO) { return success(socialClientService.createSocialClient(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新社交客户端") @PreAuthorize("@ss.hasPermission('system:social-client:update')") - public CommonResult updateSocialClient(@Valid @RequestBody SocialClientUpdateReqVO updateReqVO) { + public CommonResult updateSocialClient(@Valid @RequestBody SocialClientSaveReqVO updateReqVO) { socialClientService.updateSocialClient(updateReqVO); return success(true); } @@ -59,8 +58,8 @@ public class SocialClientController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('system:social-client:query')") public CommonResult getSocialClient(@RequestParam("id") Long id) { - SocialClientDO socialClient = socialClientService.getSocialClient(id); - return success(SocialClientConvert.INSTANCE.convert(socialClient)); + SocialClientDO client = socialClientService.getSocialClient(id); + return success(BeanUtils.toBean(client, SocialClientRespVO.class)); } @GetMapping("/page") @@ -68,7 +67,7 @@ public class SocialClientController { @PreAuthorize("@ss.hasPermission('system:social-client:query')") public CommonResult> getSocialClientPage(@Valid SocialClientPageReqVO pageVO) { PageResult pageResult = socialClientService.getSocialClientPage(pageVO); - return success(SocialClientConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, SocialClientRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java index 08b45147e..6fdf9da0b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java @@ -3,10 +3,11 @@ package cn.iocoder.yudao.module.system.controller.admin.socail; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserBindReqVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserUnbindReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserRespVO; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserUnbindReqVO; import cn.iocoder.yudao.module.system.convert.social.SocialUserConvert; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.service.social.SocialUserService; @@ -35,7 +36,8 @@ public class SocialUserController { @PostMapping("/bind") @Operation(summary = "社交绑定,使用 code 授权码") public CommonResult socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) { - socialUserService.bindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO)); + socialUserService.bindSocialUser(SocialUserConvert.INSTANCE.convert( + getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO)); return CommonResult.success(true); } @@ -54,7 +56,7 @@ public class SocialUserController { @PreAuthorize("@ss.hasPermission('system:social-user:query')") public CommonResult getSocialUser(@RequestParam("id") Long id) { SocialUserDO socialUser = socialUserService.getSocialUser(id); - return success(SocialUserConvert.INSTANCE.convert(socialUser)); + return success(BeanUtils.toBean(socialUser, SocialUserRespVO.class)); } @GetMapping("/page") @@ -62,7 +64,7 @@ public class SocialUserController { @PreAuthorize("@ss.hasPermission('system:social-user:query')") public CommonResult> getSocialUserPage(@Valid SocialUserPageReqVO pageVO) { PageResult pageResult = socialUserService.getSocialUserPage(pageVO); - return success(SocialUserConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, SocialUserRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientCreateReqVO.java deleted file mode 100644 index 8bd98c41d..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.socail.vo.client; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 社交客户端创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SocialClientCreateReqVO extends SocialClientBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java index 4512a67b5..900f363d1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientRespVO.java @@ -2,20 +2,37 @@ package cn.iocoder.yudao.module.system.controller.admin.socail.vo.client; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; @Schema(description = "管理后台 - 社交客户端 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SocialClientRespVO extends SocialClientBaseVO { +public class SocialClientRespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27162") private Long id; + @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao商城") + private String name; + + @Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "31") + private Integer socialType; + + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer userType; + + @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "wwd411c69a39ad2e54") + private String clientId; + + @Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "peter") + private String clientSecret; + + @Schema(description = "授权方的网页应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000045") + private String agentId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientSaveReqVO.java similarity index 80% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientSaveReqVO.java index 86d980ee0..be89153e8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientSaveReqVO.java @@ -13,12 +13,12 @@ import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; import java.util.Objects; -/** - * 社交客户端 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 社交客户端创建/修改 Request VO") @Data -public class SocialClientBaseVO { +public class SocialClientSaveReqVO { + + @Schema(description = "编号", example = "27162") + private Long id; @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao商城") @NotNull(message = "应用名不能为空") @@ -38,7 +38,7 @@ public class SocialClientBaseVO { @NotNull(message = "客户端编号不能为空") private String clientId; - @Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw") + @Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "peter") @NotNull(message = "客户端密钥不能为空") private String clientSecret; @@ -50,16 +50,12 @@ public class SocialClientBaseVO { @InEnum(CommonStatusEnum.class) private Integer status; - @SuppressWarnings("RedundantIfStatement") @AssertTrue(message = "agentId 不能为空") @JsonIgnore public boolean isAgentIdValid() { // 如果是企业微信,必须填写 agentId 属性 - if (Objects.equals(socialType, SocialTypeEnum.WECHAT_ENTERPRISE.getType()) - && StrUtil.isEmpty(agentId)) { - return false; - } - return true; + return !Objects.equals(socialType, SocialTypeEnum.WECHAT_ENTERPRISE.getType()) + || !StrUtil.isEmpty(agentId); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientUpdateReqVO.java deleted file mode 100644 index 963bf4b09..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/client/SocialClientUpdateReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.socail.vo.client; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 社交客户端更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SocialClientUpdateReqVO extends SocialClientBaseVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27162") - @NotNull(message = "编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBaseVO.java deleted file mode 100644 index e763d0570..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBaseVO.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.socail.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/** - * 社交用户 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ -@Data -public class SocialUserBaseVO { - - @Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") - @NotNull(message = "社交平台的类型不能为空") - private Integer type; - - @Schema(description = "社交 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - @NotNull(message = "社交 openid不能为空") - private String openid; - - @Schema(description = "社交 token", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private String token; - - @Schema(description = "原始 Token 数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - private String rawTokenInfo; - - @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") - @NotNull(message = "用户昵称不能为空") - private String nickname; - - @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") - private String avatar; - - @Schema(description = "原始用户数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - private String rawUserInfo; - - @Schema(description = "最后一次的认证 code", requiredMode = Schema.RequiredMode.REQUIRED, example = "666666") - private String code; - - @Schema(description = "最后一次的认证 state", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - private String state; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java similarity index 99% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java index 47a7681e2..1ece236d1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserBindReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserBindReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.controller.admin.socail.vo; +package cn.iocoder.yudao.module.system.controller.admin.socail.vo.user; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java index fdffa0872..fd377037d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserRespVO.java @@ -2,20 +2,43 @@ package cn.iocoder.yudao.module.system.controller.admin.socail.vo.user; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; @Schema(description = "管理后台 - 社交用户 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class SocialUserRespVO extends SocialUserBaseVO { +public class SocialUserRespVO { @Schema(description = "主键(自增策略)", requiredMode = Schema.RequiredMode.REQUIRED, example = "14569") private Long id; + @Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") + private Integer type; + + @Schema(description = "社交 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private String openid; + + @Schema(description = "社交 token", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private String token; + + @Schema(description = "原始 Token 数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private String rawTokenInfo; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String nickname; + + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") + private String avatar; + + @Schema(description = "原始用户数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private String rawUserInfo; + + @Schema(description = "最后一次的认证 code", requiredMode = Schema.RequiredMode.REQUIRED, example = "666666") + private String code; + + @Schema(description = "最后一次的认证 state", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + private String state; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserUnbindReqVO.java similarity index 99% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserUnbindReqVO.java index 10f6244cd..10f07fcdc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/SocialUserUnbindReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/vo/user/SocialUserUnbindReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.controller.admin.socail.vo; +package cn.iocoder.yudao.module.system.controller.admin.socail.vo.user; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java index 0020c9280..ea815313e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java @@ -1,16 +1,20 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.*; -import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.service.tenant.TenantService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -37,21 +41,30 @@ public class TenantController { @Operation(summary = "使用租户名,获得租户编号", description = "登录界面,根据用户的租户名,获得租户编号") @Parameter(name = "name", description = "租户名", required = true, example = "1024") public CommonResult getTenantIdByName(@RequestParam("name") String name) { - TenantDO tenantDO = tenantService.getTenantByName(name); - return success(tenantDO != null ? tenantDO.getId() : null); + TenantDO tenant = tenantService.getTenantByName(name); + return success(tenant != null ? tenant.getId() : null); + } + + @GetMapping("/get-by-website") + @PermitAll + @Operation(summary = "使用域名,获得租户信息", description = "登录界面,根据用户的域名,获得租户信息") + @Parameter(name = "website", description = "域名", required = true, example = "www.iocoder.cn") + public CommonResult getTenantByWebsite(@RequestParam("website") String website) { + TenantDO tenant = tenantService.getTenantByWebsite(website); + return success(BeanUtils.toBean(tenant, TenantSimpleRespVO.class)); } @PostMapping("/create") @Operation(summary = "创建租户") @PreAuthorize("@ss.hasPermission('system:tenant:create')") - public CommonResult createTenant(@Valid @RequestBody TenantCreateReqVO createReqVO) { + public CommonResult createTenant(@Valid @RequestBody TenantSaveReqVO createReqVO) { return success(tenantService.createTenant(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新租户") @PreAuthorize("@ss.hasPermission('system:tenant:update')") - public CommonResult updateTenant(@Valid @RequestBody TenantUpdateReqVO updateReqVO) { + public CommonResult updateTenant(@Valid @RequestBody TenantSaveReqVO updateReqVO) { tenantService.updateTenant(updateReqVO); return success(true); } @@ -71,7 +84,7 @@ public class TenantController { @PreAuthorize("@ss.hasPermission('system:tenant:query')") public CommonResult getTenant(@RequestParam("id") Long id) { TenantDO tenant = tenantService.getTenant(id); - return success(TenantConvert.INSTANCE.convert(tenant)); + return success(BeanUtils.toBean(tenant, TenantRespVO.class)); } @GetMapping("/page") @@ -79,20 +92,20 @@ public class TenantController { @PreAuthorize("@ss.hasPermission('system:tenant:query')") public CommonResult> getTenantPage(@Valid TenantPageReqVO pageVO) { PageResult pageResult = tenantService.getTenantPage(pageVO); - return success(TenantConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出租户 Excel") @PreAuthorize("@ss.hasPermission('system:tenant:export')") @OperateLog(type = EXPORT) - public void exportTenantExcel(@Valid TenantExportReqVO exportReqVO, + public void exportTenantExcel(@Valid TenantPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - List list = tenantService.getTenantList(exportReqVO); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = tenantService.getTenantPage(exportReqVO).getList(); // 导出 Excel - List datas = TenantConvert.INSTANCE.convertList02(list); - ExcelUtils.write(response, "租户.xls", "数据", TenantExcelVO.class, datas); + ExcelUtils.write(response, "租户.xls", "数据", TenantRespVO.class, + BeanUtils.toBean(list, TenantRespVO.class)); } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java index ec4782388..148494987 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java @@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.*; -import cn.iocoder.yudao.module.system.convert.tenant.TenantPackageConvert; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageRespVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; import cn.iocoder.yudao.module.system.service.tenant.TenantPackageService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -32,14 +35,14 @@ public class TenantPackageController { @PostMapping("/create") @Operation(summary = "创建租户套餐") @PreAuthorize("@ss.hasPermission('system:tenant-package:create')") - public CommonResult createTenantPackage(@Valid @RequestBody TenantPackageCreateReqVO createReqVO) { + public CommonResult createTenantPackage(@Valid @RequestBody TenantPackageSaveReqVO createReqVO) { return success(tenantPackageService.createTenantPackage(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新租户套餐") @PreAuthorize("@ss.hasPermission('system:tenant-package:update')") - public CommonResult updateTenantPackage(@Valid @RequestBody TenantPackageUpdateReqVO updateReqVO) { + public CommonResult updateTenantPackage(@Valid @RequestBody TenantPackageSaveReqVO updateReqVO) { tenantPackageService.updateTenantPackage(updateReqVO); return success(true); } @@ -59,7 +62,7 @@ public class TenantPackageController { @PreAuthorize("@ss.hasPermission('system:tenant-package:query')") public CommonResult getTenantPackage(@RequestParam("id") Long id) { TenantPackageDO tenantPackage = tenantPackageService.getTenantPackage(id); - return success(TenantPackageConvert.INSTANCE.convert(tenantPackage)); + return success(BeanUtils.toBean(tenantPackage, TenantPackageRespVO.class)); } @GetMapping("/page") @@ -67,15 +70,14 @@ public class TenantPackageController { @PreAuthorize("@ss.hasPermission('system:tenant-package:query')") public CommonResult> getTenantPackagePage(@Valid TenantPackagePageReqVO pageVO) { PageResult pageResult = tenantPackageService.getTenantPackagePage(pageVO); - return success(TenantPackageConvert.INSTANCE.convertPage(pageResult)); + return success(BeanUtils.toBean(pageResult, TenantPackageRespVO.class)); } - @GetMapping("/get-simple-list") + @GetMapping({"/get-simple-list", "simple-list"}) @Operation(summary = "获取租户套餐精简信息列表", description = "只包含被开启的租户套餐,主要用于前端的下拉选项") public CommonResult> getTenantPackageList() { - // 获得角色列表,只要开启状态的 List list = tenantPackageService.getTenantPackageListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(TenantPackageConvert.INSTANCE.convertList02(list)); + return success(BeanUtils.toBean(list, TenantPackageSimpleRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageCreateReqVO.java deleted file mode 100755 index 255971447..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageCreateReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -@Schema(description = "管理后台 - 租户套餐创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TenantPackageCreateReqVO extends TenantPackageBaseVO { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackagePageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackagePageReqVO.java index 2ee55b3a1..525a5da73 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackagePageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackagePageReqVO.java @@ -29,5 +29,4 @@ public class TenantPackagePageReqVO extends PageParam { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @Schema(description = "创建时间") private LocalDateTime[] createTime; - -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageRespVO.java index 29b985df6..16ffd817a 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageRespVO.java @@ -2,20 +2,29 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; +import java.util.Set; @Schema(description = "管理后台 - 租户套餐 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TenantPackageRespVO extends TenantPackageBaseVO { +public class TenantPackageRespVO { @Schema(description = "套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long id; + @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "VIP") + private String name; + + @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "备注", example = "好") + private String remark; + + @Schema(description = "关联的菜单编号", requiredMode = Schema.RequiredMode.REQUIRED) + private Set menuIds; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSaveReqVO.java similarity index 62% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSaveReqVO.java index fdf316a9b..3faed3a3d 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSaveReqVO.java @@ -1,24 +1,28 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.Set; -/** - * 租户套餐 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 租户套餐创建/修改 Request VO") @Data -public class TenantPackageBaseVO { +public class TenantPackageSaveReqVO { + + @Schema(description = "套餐编号", example = "1024") + private Long id; @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "VIP") - @NotNull(message = "套餐名不能为空") + @NotEmpty(message = "套餐名不能为空") private String name; @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "状态不能为空") + @InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}") private Integer status; @Schema(description = "备注", example = "好") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageUpdateReqVO.java deleted file mode 100755 index 0d7e74c25..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageUpdateReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import javax.validation.constraints.*; - -@Schema(description = "管理后台 - 租户套餐更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TenantPackageUpdateReqVO extends TenantPackageBaseVO { - - @Schema(description = "套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "套餐编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantCreateReqVO.java deleted file mode 100755 index b45ac59ba..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantCreateReqVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; - -@Schema(description = "管理后台 - 租户创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TenantCreateReqVO extends TenantBaseVO { - - @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") - @NotBlank(message = "用户账号不能为空") - @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") - @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") - private String username; - - @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") - private String password; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExcelVO.java deleted file mode 100755 index 91b78d2a1..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExcelVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - - -/** - * 租户 Excel VO - * - * @author 芋道源码 - */ -@Data -public class TenantExcelVO { - - @ExcelProperty("租户编号") - private Long id; - - @ExcelProperty("租户名") - private String name; - - @ExcelProperty("联系人") - private String contactName; - - @ExcelProperty("联系手机") - private String contactMobile; - - @ExcelProperty(value = "状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private Integer status; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java deleted file mode 100755 index c5c5a0660..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantExportReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 租户 Excel 导出 Request VO,参数和 TenantPageReqVO 是一致的") -@Data -public class TenantExportReqVO { - - @Schema(description = "租户名", example = "芋道") - private String name; - - @Schema(description = "联系人", example = "芋艿") - private String contactName; - - @Schema(description = "联系手机", example = "15601691300") - private String contactMobile; - - @Schema(description = "租户状态(0正常 1停用)", example = "1") - private Integer status; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java index d7aec7614..512a4a761 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantPageReqVO.java @@ -33,4 +33,4 @@ public class TenantPageReqVO extends PageParam { @Schema(description = "创建时间") private LocalDateTime[] createTime; -} \ No newline at end of file +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index b2e5724cf..5a444b521 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -1,22 +1,55 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; import java.time.LocalDateTime; @Schema(description = "管理后台 - 租户 Response VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TenantRespVO extends TenantBaseVO { +@ExcelIgnoreUnannotated +public class TenantRespVO { @Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("租户编号") private Long id; + @Schema(description = "租户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @ExcelProperty("租户名") + private String name; + + @Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("联系人") + private String contactName; + + @Schema(description = "联系手机", example = "15601691300") + @ExcelProperty("联系手机") + private String contactMobile; + + @Schema(description = "租户状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "绑定域名", example = "https://www.iocoder.cn") + private String website; + + @Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long packageId; + + @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime expireTime; + + @Schema(description = "账号数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Integer accountCount; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java old mode 100755 new mode 100644 similarity index 50% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java index a54784c68..117d365ff --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java @@ -1,17 +1,23 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.Data; +import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.*; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import java.time.LocalDateTime; -/** - * 租户 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 租户创建/修改 Request VO") @Data -public class TenantBaseVO { +public class TenantSaveReqVO { + + @Schema(description = "租户编号", example = "1024") + private Long id; @Schema(description = "租户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") @NotNull(message = "租户名不能为空") @@ -29,7 +35,7 @@ public class TenantBaseVO { private Integer status; @Schema(description = "绑定域名", example = "https://www.iocoder.cn") - private String domain; + private String website; @Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotNull(message = "租户套餐编号不能为空") @@ -43,4 +49,22 @@ public class TenantBaseVO { @NotNull(message = "账号数量不能为空") private Integer accountCount; + // ========== 仅【创建】时,需要传递的字段 ========== + + @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") + @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") + private String username; + + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + private String password; + + @AssertTrue(message = "用户账号、密码不能为空") + @JsonIgnore + public boolean isUsernameValid() { + return id != null // 修改时,不需要传递 + || (ObjectUtil.isAllNotEmpty(username, password)); // 新增时,必须都传递 username、password + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSimpleRespVO.java new file mode 100755 index 000000000..49752278d --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSimpleRespVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 租户精简 Response VO") +@Data +public class TenantSimpleRespVO { + + @Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "租户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + private String name; + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantUpdateReqVO.java deleted file mode 100755 index 6555bcec0..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantUpdateReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import javax.validation.constraints.*; - -@Schema(description = "管理后台 - 租户更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class TenantUpdateReqVO extends TenantBaseVO { - - @Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "租户编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java index 549982e3c..358affb3e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java @@ -1,23 +1,23 @@ package cn.iocoder.yudao.module.system.controller.admin.user; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; import cn.iocoder.yudao.module.system.convert.user.UserConvert; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import cn.iocoder.yudao.module.system.enums.common.SexEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; -import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -27,11 +27,12 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; -import java.util.*; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - 用户") @@ -48,7 +49,7 @@ public class UserController { @PostMapping("/create") @Operation(summary = "新增用户") @PreAuthorize("@ss.hasPermission('system:user:create')") - public CommonResult createUser(@Valid @RequestBody UserCreateReqVO reqVO) { + public CommonResult createUser(@Valid @RequestBody UserSaveReqVO reqVO) { Long id = userService.createUser(reqVO); return success(id); } @@ -56,7 +57,7 @@ public class UserController { @PutMapping("update") @Operation(summary = "修改用户") @PreAuthorize("@ss.hasPermission('system:user:update')") - public CommonResult updateUser(@Valid @RequestBody UserUpdateReqVO reqVO) { + public CommonResult updateUser(@Valid @RequestBody UserSaveReqVO reqVO) { userService.updateUser(reqVO); return success(true); } @@ -89,33 +90,27 @@ public class UserController { @GetMapping("/page") @Operation(summary = "获得用户分页列表") @PreAuthorize("@ss.hasPermission('system:user:list')") - public CommonResult> getUserPage(@Valid UserPageReqVO reqVO) { + public CommonResult> getUserPage(@Valid UserPageReqVO pageReqVO) { // 获得用户分页列表 - PageResult pageResult = userService.getUserPage(reqVO); + PageResult pageResult = userService.getUserPage(pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { - return success(new PageResult<>(pageResult.getTotal())); // 返回空 + return success(new PageResult<>(pageResult.getTotal())); } - - // 获得拼接需要的数据 - Collection deptIds = convertList(pageResult.getList(), AdminUserDO::getDeptId); - Map deptMap = deptService.getDeptMap(deptIds); - // 拼接结果返回 - List userList = new ArrayList<>(pageResult.getList().size()); - pageResult.getList().forEach(user -> { - UserPageItemRespVO respVO = UserConvert.INSTANCE.convert(user); - respVO.setDept(UserConvert.INSTANCE.convert(deptMap.get(user.getDeptId()))); - userList.add(respVO); - }); - return success(new PageResult<>(userList, pageResult.getTotal())); + // 拼接数据 + Map deptMap = deptService.getDeptMap( + convertList(pageResult.getList(), AdminUserDO::getDeptId)); + return success(new PageResult<>(UserConvert.INSTANCE.convertList(pageResult.getList(), deptMap), + pageResult.getTotal())); } - @GetMapping("/list-all-simple") + @GetMapping({"/list-all-simple", "/simple-list"}) @Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项") public CommonResult> getSimpleUserList() { - // 获用户列表,只要开启状态的 List list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus()); - // 排序后,返回给前端 - return success(UserConvert.INSTANCE.convertList04(list)); + // 拼接数据 + Map deptMap = deptService.getDeptMap( + convertList(list, AdminUserDO::getDeptId)); + return success(UserConvert.INSTANCE.convertSimpleList(list, deptMap)); } @GetMapping("/get") @@ -124,41 +119,24 @@ public class UserController { @PreAuthorize("@ss.hasPermission('system:user:query')") public CommonResult getUser(@RequestParam("id") Long id) { AdminUserDO user = userService.getUser(id); - // 获得部门数据 + // 拼接数据 DeptDO dept = deptService.getDept(user.getDeptId()); - return success(UserConvert.INSTANCE.convert(user).setDept(UserConvert.INSTANCE.convert(dept))); + return success(UserConvert.INSTANCE.convert(user, dept)); } @GetMapping("/export") @Operation(summary = "导出用户") @PreAuthorize("@ss.hasPermission('system:user:export')") @OperateLog(type = EXPORT) - public void exportUserList(@Validated UserExportReqVO reqVO, + public void exportUserList(@Validated UserPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - // 获得用户列表 - List users = userService.getUserList(reqVO); - - // 获得拼接需要的数据 - Collection deptIds = convertList(users, AdminUserDO::getDeptId); - Map deptMap = deptService.getDeptMap(deptIds); - Map deptLeaderUserMap = userService.getUserMap( - convertSet(deptMap.values(), DeptDO::getLeaderUserId)); - // 拼接数据 - List excelUsers = new ArrayList<>(users.size()); - users.forEach(user -> { - UserExcelVO excelVO = UserConvert.INSTANCE.convert02(user); - // 设置部门 - MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> { - excelVO.setDeptName(dept.getName()); - // 设置部门负责人的名字 - MapUtils.findAndThen(deptLeaderUserMap, dept.getLeaderUserId(), - deptLeaderUser -> excelVO.setDeptLeaderNickname(deptLeaderUser.getNickname())); - }); - excelUsers.add(excelVO); - }); - - // 输出 - ExcelUtils.write(response, "用户数据.xls", "用户列表", UserExcelVO.class, excelUsers); + exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = userService.getUserPage(exportReqVO).getList(); + // 输出 Excel + Map deptMap = deptService.getDeptMap( + convertList(list, AdminUserDO::getDeptId)); + ExcelUtils.write(response, "用户数据.xls", "数据", UserRespVO.class, + UserConvert.INSTANCE.convertList(list, deptMap)); } @GetMapping("/get-import-template") @@ -171,7 +149,6 @@ public class UserController { UserImportExcelVO.builder().username("yuanma").deptId(2L).email("yuanma@iocoder.cn").mobile("15601701300") .nickname("源码").status(CommonStatusEnum.DISABLE.getStatus()).sex(SexEnum.FEMALE.getSex()).build() ); - // 输出 ExcelUtils.write(response, "用户导入模板.xls", "用户列表", UserImportExcelVO.class, list); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java index b3c517ad0..7ae72b84b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.controller.admin.user; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO; @@ -20,8 +19,8 @@ import cn.iocoder.yudao.module.system.service.permission.PermissionService; import cn.iocoder.yudao.module.system.service.permission.RoleService; import cn.iocoder.yudao.module.system.service.social.SocialUserService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -59,27 +58,18 @@ public class UserProfileController { @GetMapping("/get") @Operation(summary = "获得登录用户信息") @DataPermission(enable = false) // 关闭数据权限,避免只查看自己时,查询不到部门。 - public CommonResult profile() { + public CommonResult getUserProfile() { // 获得用户基本信息 AdminUserDO user = userService.getUser(getLoginUserId()); - UserProfileRespVO resp = UserConvert.INSTANCE.convert03(user); // 获得用户角色 List userRoles = roleService.getRoleListFromCache(permissionService.getUserRoleIdListByUserId(user.getId())); - resp.setRoles(UserConvert.INSTANCE.convertList(userRoles)); // 获得部门信息 - if (user.getDeptId() != null) { - DeptDO dept = deptService.getDept(user.getDeptId()); - resp.setDept(UserConvert.INSTANCE.convert02(dept)); - } + DeptDO dept = user.getDeptId() != null ? deptService.getDept(user.getDeptId()) : null; // 获得岗位信息 - if (CollUtil.isNotEmpty(user.getPostIds())) { - List posts = postService.getPostList(user.getPostIds()); - resp.setPosts(UserConvert.INSTANCE.convertList02(posts)); - } + List posts = CollUtil.isNotEmpty(user.getPostIds()) ? postService.getPostList(user.getPostIds()) : null; // 获得社交用户信息 List socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN.getValue()); - resp.setSocialUsers(UserConvert.INSTANCE.convertList03(socialUsers)); - return success(resp); + return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts, socialUsers)); } @PutMapping("/update") @@ -96,7 +86,8 @@ public class UserProfileController { return success(true); } - @RequestMapping(value = "/update-avatar", method = {RequestMethod.POST, RequestMethod.PUT}) // 解决 uni-app 不支持 Put 上传文件的问题 + @RequestMapping(value = "/update-avatar", + method = {RequestMethod.POST, RequestMethod.PUT}) // 解决 uni-app 不支持 Put 上传文件的问题 @Operation(summary = "上传用户个人头像") public CommonResult updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws Exception { if (file.isEmpty()) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java index 6abf1fb65..4f7c71ecd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileRespVO.java @@ -1,28 +1,38 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserBaseVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSimpleRespVO; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; import java.time.LocalDateTime; import java.util.List; - @Data -@EqualsAndHashCode(callSuper = true) -@NoArgsConstructor -@AllArgsConstructor @Schema(description = "管理后台 - 用户个人中心信息 Response VO") -public class UserProfileRespVO extends UserBaseVO { +public class UserProfileRespVO { @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long id; - @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; + @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + private String username; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String nickname; + + @Schema(description = "用户邮箱", example = "yudao@iocoder.cn") + private String email; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1") + private Integer sex; + + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") + private String avatar; @Schema(description = "最后登录 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.1") private String loginIp; @@ -36,58 +46,20 @@ public class UserProfileRespVO extends UserBaseVO { /** * 所属角色 */ - private List roles; - + private List roles; /** * 所在部门 */ - private Dept dept; - + private DeptSimpleRespVO dept; /** * 所属岗位数组 */ - private List posts; + private List posts; /** * 社交用户数组 */ private List socialUsers; - @Schema(description = "角色") - @Data - public static class Role { - - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "普通角色") - private String name; - - } - - @Schema(description = "部门") - @Data - public static class Dept { - - @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") - private String name; - - } - - @Schema(description = "岗位") - @Data - public static class Post { - - @Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "岗位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "开发") - private String name; - - } - @Schema(description = "社交用户") @Data public static class SocialUser { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java index 8c74bd1f5..f1e54ac90 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/profile/UserProfileUpdateReqVO.java @@ -7,6 +7,7 @@ import org.hibernate.validator.constraints.Length; import javax.validation.constraints.Email; import javax.validation.constraints.Size; + @Schema(description = "管理后台 - 用户个人信息更新 Request VO") @Data public class UserProfileUpdateReqVO { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserCreateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserCreateReqVO.java deleted file mode 100644 index dc5b7561a..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserCreateReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; - - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import org.hibernate.validator.constraints.Length; - -import javax.validation.constraints.NotEmpty; - -@Schema(description = "管理后台 - 用户创建 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class UserCreateReqVO extends UserBaseVO { - - @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") - @NotEmpty(message = "密码不能为空") - @Length(min = 4, max = 16, message = "密码长度为 4-16 位") - private String password; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExcelVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExcelVO.java deleted file mode 100644 index 16899c263..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExcelVO.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; - -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 用户 Excel 导出 VO - */ -@Data -public class UserExcelVO { - - @ExcelProperty("用户编号") - private Long id; - - @ExcelProperty("用户名称") - private String username; - - @ExcelProperty("用户昵称") - private String nickname; - - @ExcelProperty("用户邮箱") - private String email; - - @ExcelProperty("手机号码") - private String mobile; - - @ExcelProperty(value = "用户性别", converter = DictConvert.class) - @DictFormat(DictTypeConstants.USER_SEX) - private Integer sex; - - @ExcelProperty(value = "帐号状态", converter = DictConvert.class) - @DictFormat(DictTypeConstants.COMMON_STATUS) - private Integer status; - - @ExcelProperty("最后登录IP") - private String loginIp; - - @ExcelProperty("最后登录时间") - private LocalDateTime loginDate; - - @ExcelProperty("部门名称") - private String deptName; - - @ExcelProperty("部门负责人") - private String deptLeaderNickname; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java deleted file mode 100644 index f74771121..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserExportReqVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 用户导出 Request VO,参数和 UserPageReqVO 是一致的") -@Data -@NoArgsConstructor -@AllArgsConstructor -public class UserExportReqVO { - - @Schema(description = "用户账号,模糊匹配", example = "yudao") - private String username; - - @Schema(description = "手机号码,模糊匹配", example = "yudao") - private String mobile; - - @Schema(description = "展示状态,参见 CommonStatusEnum 枚举类", example = "1") - private Integer status; - - @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - - @Schema(description = "部门编号,同时筛选子部门", example = "1024") - private Long deptId; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java deleted file mode 100644 index 3c01ca9bb..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserPageItemRespVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; - -@Schema(description = "管理后台 - 用户分页时的信息 Response VO,相比用户基本信息来说,会多部门信息") -@Data -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class UserPageItemRespVO extends UserRespVO { - - /** - * 所在部门 - */ - private Dept dept; - - @Schema(description = "部门") - @Data - public static class Dept { - - @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "研发部") - private String name; - - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java index d4573da8f..2837318f9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java @@ -1,30 +1,72 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AllArgsConstructor; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; import java.time.LocalDateTime; +import java.util.Set; @Schema(description = "管理后台 - 用户信息 Response VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class UserRespVO extends UserBaseVO { +@ExcelIgnoreUnannotated +public class UserRespVO{ @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("用户编号") private Long id; + @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") + @ExcelProperty("用户名称") + private String username; + + @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("用户昵称") + private String nickname; + + @Schema(description = "备注", example = "我是一个用户") + private String remark; + + @Schema(description = "部门ID", example = "我是一个用户") + private Long deptId; + @Schema(description = "部门名称", example = "IT 部") + @ExcelProperty("部门名称") + private String deptName; + + @Schema(description = "岗位编号数组", example = "1") + private Set postIds; + + @Schema(description = "用户邮箱", example = "yudao@iocoder.cn") + @ExcelProperty("用户邮箱") + private String email; + + @Schema(description = "手机号码", example = "15601691300") + @ExcelProperty("手机号码") + private String mobile; + + @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1") + @ExcelProperty(value = "用户性别", converter = DictConvert.class) + @DictFormat(DictTypeConstants.USER_SEX) + private Integer sex; + + @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") + private String avatar; + @Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "帐号状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; @Schema(description = "最后登录 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.1") + @ExcelProperty("最后登录IP") private String loginIp; @Schema(description = "最后登录时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") + @ExcelProperty("最后登录时间") private LocalDateTime loginDate; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java similarity index 62% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java index 5008cb2d0..4ab2eddd2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSaveReqVO.java @@ -1,21 +1,22 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; +import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.validation.Mobile; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; -import javax.validation.constraints.Size; +import javax.validation.constraints.*; import java.util.Set; -/** - * 用户 Base VO,提供给添加、修改、详细的子 VO 使用 - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 - */ +@Schema(description = "管理后台 - 用户创建/修改 Request VO") @Data -public class UserBaseVO { +public class UserSaveReqVO { + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "用户编号不能为空") + private Long id; @Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") @NotBlank(message = "用户账号不能为空") @@ -51,4 +52,17 @@ public class UserBaseVO { @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png") private String avatar; + // ========== 仅【创建】时,需要传递的字段 ========== + + @Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + @Length(min = 4, max = 16, message = "密码长度为 4-16 位") + private String password; + + @AssertTrue(message = "密码不能为空") + @JsonIgnore + public boolean isPasswordValid() { + return id != null // 修改时,不需要传递 + || (ObjectUtil.isAllNotEmpty(password)); // 新增时,必须都传递 password + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java index f021d7213..6dac2869d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserSimpleRespVO.java @@ -17,4 +17,9 @@ public class UserSimpleRespVO { @Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") private String nickname; + @Schema(description = "部门ID", example = "我是一个用户") + private Long deptId; + @Schema(description = "部门名称", example = "IT 部") + private String deptName; + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateReqVO.java deleted file mode 100644 index 2267c506f..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 用户更新 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class UserUpdateReqVO extends UserBaseVO { - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "用户编号不能为空") - private Long id; - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java index 1f4f78c80..8c4b97f6f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/app/dict/AppDictDataController.java @@ -1,8 +1,9 @@ package cn.iocoder.yudao.module.system.controller.app.dict; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.app.dict.vo.AppDictDataRespVO; -import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.service.dict.DictDataService; import io.swagger.v3.oas.annotations.Operation; @@ -32,8 +33,9 @@ public class AppDictDataController { @Operation(summary = "根据字典类型查询字典数据信息") @Parameter(name = "type", description = "字典类型", required = true, example = "common_status") public CommonResult> getDictDataListByType(@RequestParam("type") String type) { - List list = dictDataService.getEnabledDictDataListByType(type); - return success(DictDataConvert.INSTANCE.convertList03(list)); + List list = dictDataService.getDictDataList( + CommonStatusEnum.ENABLE.getStatus(), type); + return success(BeanUtils.toBean(list, AppDictDataRespVO.class)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2ClientConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2ClientConvert.java deleted file mode 100755 index 87f408aac..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2ClientConvert.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.auth; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientRespVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * OAuth2 客户端 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface OAuth2ClientConvert { - - OAuth2ClientConvert INSTANCE = Mappers.getMapper(OAuth2ClientConvert.class); - - OAuth2ClientDO convert(OAuth2ClientCreateReqVO bean); - - OAuth2ClientDO convert(OAuth2ClientUpdateReqVO bean); - - OAuth2ClientRespVO convert(OAuth2ClientDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2TokenConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2TokenConvert.java deleted file mode 100644 index 17c62f0dd..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2TokenConvert.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.auth; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO; -import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface OAuth2TokenConvert { - - OAuth2TokenConvert INSTANCE = Mappers.getMapper(OAuth2TokenConvert.class); - - OAuth2AccessTokenCheckRespDTO convert(OAuth2AccessTokenDO bean); - - PageResult convert(PageResult page); - - OAuth2AccessTokenRespDTO convert2(OAuth2AccessTokenDO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/DeptConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/DeptConvert.java deleted file mode 100644 index e8ee7cee7..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/DeptConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.dept; - -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptRespVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; -import java.util.Map; - -@Mapper -public interface DeptConvert { - - DeptConvert INSTANCE = Mappers.getMapper(DeptConvert.class); - - List convertList(List list); - - List convertList02(List list); - - DeptRespVO convert(DeptDO bean); - - DeptDO convert(DeptCreateReqVO bean); - - DeptDO convert(DeptUpdateReqVO bean); - - List convertList03(List list); - - DeptRespDTO convert03(DeptDO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java deleted file mode 100644 index 86a548edb..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dept/PostConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.dept; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.*; -import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface PostConvert { - - PostConvert INSTANCE = Mappers.getMapper(PostConvert.class); - - List convertList02(List list); - - PageResult convertPage(PageResult page); - - PostRespVO convert(PostDO id); - - PostDO convert(PostCreateReqVO bean); - - PostDO convert(PostUpdateReqVO reqVO); - - List convertList03(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java deleted file mode 100644 index dbfad6678..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictDataConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.dict; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.*; -import cn.iocoder.yudao.module.system.controller.app.dict.vo.AppDictDataRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface DictDataConvert { - - DictDataConvert INSTANCE = Mappers.getMapper(DictDataConvert.class); - - List convertList(List list); - - DictDataRespVO convert(DictDataDO bean); - - PageResult convertPage(PageResult page); - - DictDataDO convert(DictDataUpdateReqVO bean); - - DictDataDO convert(DictDataCreateReqVO bean); - - List convertList02(List bean); - - DictDataRespDTO convert02(DictDataDO bean); - - List convertList03(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictTypeConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictTypeConvert.java deleted file mode 100644 index 392e3082e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/dict/DictTypeConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.dict; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.*; -import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface DictTypeConvert { - - DictTypeConvert INSTANCE = Mappers.getMapper(DictTypeConvert.class); - - PageResult convertPage(PageResult bean); - - DictTypeRespVO convert(DictTypeDO bean); - - DictTypeDO convert(DictTypeCreateReqVO bean); - - DictTypeDO convert(DictTypeUpdateReqVO bean); - - List convertList(List list); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/errorcode/ErrorCodeConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/errorcode/ErrorCodeConvert.java deleted file mode 100644 index 3e1abd86b..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/errorcode/ErrorCodeConvert.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.errorcode; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO; -import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 错误码 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface ErrorCodeConvert { - - ErrorCodeConvert INSTANCE = Mappers.getMapper(ErrorCodeConvert.class); - - ErrorCodeDO convert(ErrorCodeCreateReqVO bean); - - ErrorCodeDO convert(ErrorCodeUpdateReqVO bean); - - ErrorCodeRespVO convert(ErrorCodeDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - - ErrorCodeDO convert(ErrorCodeAutoGenerateReqDTO bean); - - List convertList03(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/LoginLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/LoginLogConvert.java deleted file mode 100644 index ea50d4b09..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/LoginLogConvert.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.logger; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface LoginLogConvert { - - LoginLogConvert INSTANCE = Mappers.getMapper(LoginLogConvert.class); - - PageResult convertPage(PageResult page); - - List convertList(List list); - - LoginLogDO convert(LoginLogCreateReqDTO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index b79ca3f72..7b3aff8c0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.convert.logger; -import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExcelVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -12,30 +11,18 @@ import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; @Mapper public interface OperateLogConvert { OperateLogConvert INSTANCE = Mappers.getMapper(OperateLogConvert.class); - OperateLogDO convert(OperateLogCreateReqDTO bean); - - PageResult convertPage(PageResult page); - - OperateLogRespVO convert(OperateLogDO bean); - - default List convertList(List list, Map userMap) { - return list.stream().map(operateLog -> { - OperateLogExcelVO excelVO = convert02(operateLog); - MapUtils.findAndThen(userMap, operateLog.getUserId(), user -> excelVO.setUserNickname(user.getNickname())); - excelVO.setSuccessStr(SUCCESS.getCode().equals(operateLog.getResultCode()) ? "成功" : "失败"); - return excelVO; - }).collect(Collectors.toList()); + default List convertList(List list, Map userMap) { + return CollectionUtils.convertList(list, log -> { + OperateLogRespVO logVO = BeanUtils.toBean(log, OperateLogRespVO.class); + MapUtils.findAndThen(userMap, log.getUserId(), user -> logVO.setUserNickname(user.getNickname())); + return logVO; + }); } - OperateLogExcelVO convert02(OperateLogDO bean); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java index ffd150135..5d20ac13d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailAccountConvert.java @@ -2,29 +2,15 @@ package cn.iocoder.yudao.module.system.convert.mail; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.mail.MailAccount; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.*; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import java.util.List; - @Mapper public interface MailAccountConvert { MailAccountConvert INSTANCE = Mappers.getMapper(MailAccountConvert.class); - MailAccountDO convert(MailAccountCreateReqVO bean); - - MailAccountDO convert(MailAccountUpdateReqVO bean); - - MailAccountRespVO convert(MailAccountDO bean); - - PageResult convertPage(PageResult pageResult); - - List convertList02(List list); - default MailAccount convert(MailAccountDO account, String nickname) { String from = StrUtil.isNotEmpty(nickname) ? nickname + " <" + account.getMail() + ">" : account.getMail(); return new MailAccount().setFrom(from).setAuth(true) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailLogConvert.java deleted file mode 100644 index c5599e355..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailLogConvert.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.mail; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface MailLogConvert { - - MailLogConvert INSTANCE = Mappers.getMapper(MailLogConvert.class); - - PageResult convertPage(PageResult pageResult); - - MailLogRespVO convert(MailLogDO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailTemplateConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailTemplateConvert.java deleted file mode 100644 index c130ffc74..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/mail/MailTemplateConvert.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.mail; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateRespVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateSimpleRespVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface MailTemplateConvert { - - MailTemplateConvert INSTANCE = Mappers.getMapper(MailTemplateConvert.class); - - MailTemplateDO convert(MailTemplateUpdateReqVO bean); - - MailTemplateDO convert(MailTemplateCreateReqVO bean); - - MailTemplateRespVO convert(MailTemplateDO bean); - - PageResult convertPage(PageResult pageResult); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java deleted file mode 100644 index ad2bedec7..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notice/NoticeConvert.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.notice; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeRespVO; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface NoticeConvert { - - NoticeConvert INSTANCE = Mappers.getMapper(NoticeConvert.class); - - PageResult convertPage(PageResult page); - - NoticeRespVO convert(NoticeDO bean); - - NoticeDO convert(NoticeUpdateReqVO bean); - - NoticeDO convert(NoticeCreateReqVO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notify/NotifyMessageConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notify/NotifyMessageConvert.java deleted file mode 100644 index 4a393d30c..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notify/NotifyMessageConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.notify; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyMessageDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 站内信 Convert - * - * @author xrcoder - */ -@Mapper -public interface NotifyMessageConvert { - - NotifyMessageConvert INSTANCE = Mappers.getMapper(NotifyMessageConvert.class); - - NotifyMessageRespVO convert(NotifyMessageDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notify/NotifyTemplateConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notify/NotifyTemplateConvert.java deleted file mode 100644 index 174780e22..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/notify/NotifyTemplateConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.notify; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 站内信模版 Convert - * - * @author xrcoder - */ -@Mapper(uses = DateUtils.class) -public interface NotifyTemplateConvert { - - NotifyTemplateConvert INSTANCE = Mappers.getMapper(NotifyTemplateConvert.class); - - NotifyTemplateDO convert(NotifyTemplateCreateReqVO bean); - - NotifyTemplateDO convert(NotifyTemplateUpdateReqVO bean); - - NotifyTemplateRespVO convert(NotifyTemplateDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2OpenConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2OpenConvert.java index 3426e5c8f..24c953754 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2OpenConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2OpenConvert.java @@ -4,6 +4,7 @@ import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO; @@ -25,21 +26,19 @@ public interface OAuth2OpenConvert { OAuth2OpenConvert INSTANCE = Mappers.getMapper(OAuth2OpenConvert.class); default OAuth2OpenAccessTokenRespVO convert(OAuth2AccessTokenDO bean) { - OAuth2OpenAccessTokenRespVO respVO = convert0(bean); + OAuth2OpenAccessTokenRespVO respVO = BeanUtils.toBean(bean, OAuth2OpenAccessTokenRespVO.class); respVO.setTokenType(SecurityFrameworkUtils.AUTHORIZATION_BEARER.toLowerCase()); respVO.setExpiresIn(OAuth2Utils.getExpiresIn(bean.getExpiresTime())); respVO.setScope(OAuth2Utils.buildScopeStr(bean.getScopes())); return respVO; } - OAuth2OpenAccessTokenRespVO convert0(OAuth2AccessTokenDO bean); default OAuth2OpenCheckTokenRespVO convert2(OAuth2AccessTokenDO bean) { - OAuth2OpenCheckTokenRespVO respVO = convert3(bean); + OAuth2OpenCheckTokenRespVO respVO = BeanUtils.toBean(bean, OAuth2OpenCheckTokenRespVO.class); respVO.setExp(LocalDateTimeUtil.toEpochMilli(bean.getExpiresTime()) / 1000L); respVO.setUserType(UserTypeEnum.ADMIN.getValue()); return respVO; } - OAuth2OpenCheckTokenRespVO convert3(OAuth2AccessTokenDO bean); default OAuth2OpenAuthorizeInfoRespVO convert(OAuth2ClientDO client, List approves) { // 构建 scopes diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2UserConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2UserConvert.java deleted file mode 100644 index b2610565a..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2UserConvert.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.oauth2; - -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; -import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; -import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface OAuth2UserConvert { - - OAuth2UserConvert INSTANCE = Mappers.getMapper(OAuth2UserConvert.class); - - OAuth2UserInfoRespVO convert(AdminUserDO bean); - OAuth2UserInfoRespVO.Dept convert(DeptDO dept); - List convertList(List list); - - UserProfileUpdateReqVO convert(OAuth2UserUpdateReqVO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/permission/MenuConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/permission/MenuConvert.java deleted file mode 100644 index 0fb3505cc..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/permission/MenuConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.permission; - -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSimpleRespVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface MenuConvert { - - MenuConvert INSTANCE = Mappers.getMapper(MenuConvert.class); - - List convertList(List list); - - MenuDO convert(MenuCreateReqVO bean); - - MenuDO convert(MenuUpdateReqVO bean); - - MenuRespVO convert(MenuDO bean); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java deleted file mode 100644 index 73475ee4d..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.permission; - -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*; -import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; -import cn.iocoder.yudao.module.system.service.permission.bo.RoleCreateReqBO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface RoleConvert { - - RoleConvert INSTANCE = Mappers.getMapper(RoleConvert.class); - - RoleDO convert(RoleUpdateReqVO bean); - - RoleRespVO convert(RoleDO bean); - - RoleDO convert(RoleCreateReqVO bean); - - List convertList02(List list); - - List convertList03(List list); - - RoleDO convert(RoleCreateReqBO bean); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sensitiveword/SensitiveWordConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sensitiveword/SensitiveWordConvert.java deleted file mode 100644 index fde03dbf3..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sensitiveword/SensitiveWordConvert.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.sensitiveword; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordRespVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 敏感词 Convert - * - * @author 永不言败 - */ -@Mapper -public interface SensitiveWordConvert { - - SensitiveWordConvert INSTANCE = Mappers.getMapper(SensitiveWordConvert.class); - - SensitiveWordDO convert(SensitiveWordCreateReqVO bean); - - SensitiveWordDO convert(SensitiveWordUpdateReqVO bean); - - SensitiveWordRespVO convert(SensitiveWordDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java deleted file mode 100644 index 10252c870..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsChannelConvert.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.sms; - -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelRespVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSimpleRespVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 短信渠道 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface SmsChannelConvert { - - SmsChannelConvert INSTANCE = Mappers.getMapper(SmsChannelConvert.class); - - SmsChannelDO convert(SmsChannelCreateReqVO bean); - - SmsChannelDO convert(SmsChannelUpdateReqVO bean); - - SmsChannelRespVO convert(SmsChannelDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList03(List list); - - SmsChannelProperties convert02(SmsChannelDO channel); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsLogConvert.java deleted file mode 100644 index 40efe60a1..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsLogConvert.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.sms; - -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 短信日志 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface SmsLogConvert { - - SmsLogConvert INSTANCE = Mappers.getMapper(SmsLogConvert.class); - - SmsLogRespVO convert(SmsLogDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsTemplateConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsTemplateConvert.java deleted file mode 100644 index b0fb02b8f..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/sms/SmsTemplateConvert.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.sms; - -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateRespVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SmsTemplateConvert { - - SmsTemplateConvert INSTANCE = Mappers.getMapper(SmsTemplateConvert.class); - - SmsTemplateDO convert(SmsTemplateCreateReqVO bean); - - SmsTemplateDO convert(SmsTemplateUpdateReqVO bean); - - SmsTemplateRespVO convert(SmsTemplateDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialClientConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialClientConvert.java deleted file mode 100644 index af227aa19..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialClientConvert.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.social; - -import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO; -import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientRespVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; -import me.chanjar.weixin.common.bean.WxJsapiSignature; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface SocialClientConvert { - - SocialClientConvert INSTANCE = Mappers.getMapper(SocialClientConvert.class); - - SocialWxJsapiSignatureRespDTO convert(WxJsapiSignature bean); - - SocialWxPhoneNumberInfoRespDTO convert(WxMaPhoneNumberInfo bean); - - SocialClientDO convert(SocialClientCreateReqVO bean); - - SocialClientDO convert(SocialClientUpdateReqVO bean); - - SocialClientRespVO convert(SocialClientDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialUserConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialUserConvert.java index c2e8a272e..9e679a242 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialUserConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/social/SocialUserConvert.java @@ -1,32 +1,17 @@ package cn.iocoder.yudao.module.system.convert.social; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; -import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserBindReqVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.SocialUserUnbindReqVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserRespVO; -import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; -import java.util.List; - @Mapper public interface SocialUserConvert { SocialUserConvert INSTANCE = Mappers.getMapper(SocialUserConvert.class); - @Mapping(target = "socialType", source = "reqVO.type") + @Mapping(source = "reqVO.type", target = "socialType") SocialUserBindReqDTO convert(Long userId, Integer userType, SocialUserBindReqVO reqVO); - SocialUserUnbindReqDTO convert(Long userId, Integer userType, SocialUserUnbindReqVO reqVO); - - SocialUserRespVO convert(SocialUserDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java index d40e481d8..669954d7e 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java @@ -1,17 +1,10 @@ package cn.iocoder.yudao.module.system.convert.tenant; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExcelVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserCreateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; -import java.util.List; - /** * 租户 Convert * @@ -22,20 +15,8 @@ public interface TenantConvert { TenantConvert INSTANCE = Mappers.getMapper(TenantConvert.class); - TenantDO convert(TenantCreateReqVO bean); - - TenantDO convert(TenantUpdateReqVO bean); - - TenantRespVO convert(TenantDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - - default UserCreateReqVO convert02(TenantCreateReqVO bean) { - UserCreateReqVO reqVO = new UserCreateReqVO(); + default UserSaveReqVO convert02(TenantSaveReqVO bean) { + UserSaveReqVO reqVO = new UserSaveReqVO(); reqVO.setUsername(bean.getUsername()); reqVO.setPassword(bean.getPassword()); reqVO.setNickname(bean.getContactName()).setMobile(bean.getContactMobile()); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantPackageConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantPackageConvert.java deleted file mode 100755 index ff8c7e4ae..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantPackageConvert.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.system.convert.tenant; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSimpleRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSimpleRespVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -/** - * 租户套餐 Convert - * - * @author 芋道源码 - */ -@Mapper -public interface TenantPackageConvert { - - TenantPackageConvert INSTANCE = Mappers.getMapper(TenantPackageConvert.class); - - TenantPackageDO convert(TenantPackageCreateReqVO bean); - - TenantPackageDO convert(TenantPackageUpdateReqVO bean); - - TenantPackageRespVO convert(TenantPackageDO bean); - - List convertList(List list); - - PageResult convertPage(PageResult page); - - List convertList02(List list); - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java index 0c5639c51..b58be2195 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/user/UserConvert.java @@ -1,10 +1,14 @@ package cn.iocoder.yudao.module.system.convert.user; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSimpleRespVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSimpleRespVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSimpleRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; @@ -21,36 +25,34 @@ public interface UserConvert { UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); - UserPageItemRespVO convert(AdminUserDO bean); + default List convertList(List list, Map deptMap) { + return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId()))); + } - UserPageItemRespVO.Dept convert(DeptDO bean); + default UserRespVO convert(AdminUserDO user, DeptDO dept) { + UserRespVO userVO = BeanUtils.toBean(user, UserRespVO.class); + if (dept != null) { + userVO.setDeptName(dept.getName()); + } + return userVO; + } - AdminUserDO convert(UserCreateReqVO bean); + default List convertSimpleList(List list, Map deptMap) { + return CollectionUtils.convertList(list, user -> { + UserSimpleRespVO userVO = BeanUtils.toBean(user, UserSimpleRespVO.class); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> userVO.setDeptName(dept.getName())); + return userVO; + }); + } - AdminUserDO convert(UserUpdateReqVO bean); - - UserExcelVO convert02(AdminUserDO bean); - - AdminUserDO convert(UserImportExcelVO bean); - - UserProfileRespVO convert03(AdminUserDO bean); - - List convertList(List list); - - UserProfileRespVO.Dept convert02(DeptDO bean); - - AdminUserDO convert(UserProfileUpdateReqVO bean); - - AdminUserDO convert(UserProfileUpdatePasswordReqVO bean); - - List convertList02(List list); - - List convertList03(List list); - - List convertList04(List list); - - AdminUserRespDTO convert4(AdminUserDO bean); - - List convertList4(List users); + default UserProfileRespVO convert(AdminUserDO user, List userRoles, + DeptDO dept, List posts, List socialUsers) { + UserProfileRespVO userVO = BeanUtils.toBean(user, UserProfileRespVO.class); + userVO.setRoles(BeanUtils.toBean(userRoles, RoleSimpleRespVO.class)); + userVO.setDept(BeanUtils.toBean(dept, DeptSimpleRespVO.class)); + userVO.setPosts(BeanUtils.toBean(posts, PostSimpleRespVO.class)); + userVO.setSocialUsers(BeanUtils.toBean(socialUsers, UserProfileRespVO.SocialUser.class)); + return userVO; + } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java index 31f90cfc4..a59fa8b6e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/dept/DeptDO.java @@ -21,6 +21,8 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class DeptDO extends TenantBaseDO { + public static final Long PARENT_ID_ROOT = 0L; + /** * 部门ID */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java index 173c21c4d..9f250ce69 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsLogDO.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms; -import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; -import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsFrameworkErrorCodeConstants; +import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; +import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @@ -115,19 +114,6 @@ public class SmsLogDO extends BaseDO { * 发送时间 */ private LocalDateTime sendTime; - /** - * 发送结果的编码 - * - * 枚举 {@link SmsFrameworkErrorCodeConstants} - */ - private Integer sendCode; - /** - * 发送结果的提示 - * - * 一般情况下,使用 {@link SmsFrameworkErrorCodeConstants} - * 异常情况下,通过格式化 Exception 的提示存储 - */ - private String sendMsg; /** * 短信 API 发送结果的编码 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java index 17b42efa3..0b78b7d67 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java @@ -59,10 +59,8 @@ public class TenantDO extends BaseDO { private Integer status; /** * 绑定域名 - * - * TODO 芋艿:目前是预留字段,未来会支持根据域名,自动查询到对应的租户。等等 */ - private String domain; + private String website; /** * 租户套餐编号 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java index ba062a2c0..e05c38c7e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dept/PostMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.dept; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import org.apache.ibatis.annotations.Mapper; @@ -28,13 +27,6 @@ public interface PostMapper extends BaseMapperX { .orderByDesc(PostDO::getId)); } - default List selectList(PostExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(PostDO::getCode, reqVO.getCode()) - .likeIfPresent(PostDO::getName, reqVO.getName()) - .eqIfPresent(PostDO::getStatus, reqVO.getStatus())); - } - default PostDO selectByName(String name) { return selectOne(PostDO::getName, name); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java index f92c86298..87a05c636 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictDataMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -41,17 +40,10 @@ public interface DictDataMapper extends BaseMapperX { .orderByDesc(Arrays.asList(DictDataDO::getDictType, DictDataDO::getSort))); } - default List selectList(DictDataExportReqVO reqVO) { + default List selectListByStatusAndDictType(Integer status, String dictType) { return selectList(new LambdaQueryWrapperX() - .likeIfPresent(DictDataDO::getLabel, reqVO.getLabel()) - .eqIfPresent(DictDataDO::getDictType, reqVO.getDictType()) - .eqIfPresent(DictDataDO::getStatus, reqVO.getStatus())); - } - - default List selectListByTypeAndStatus(String dictType, Integer status) { - return selectList(new LambdaQueryWrapper() - .eq(DictDataDO::getDictType, dictType) - .eq(DictDataDO::getStatus, status)); + .eqIfPresent(DictDataDO::getStatus, status) + .eqIfPresent(DictDataDO::getDictType, dictType)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java index 261f18cc4..52393a961 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/dict/DictTypeMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import org.apache.ibatis.annotations.Mapper; @@ -11,7 +10,6 @@ import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; import java.time.LocalDateTime; -import java.util.List; @Mapper public interface DictTypeMapper extends BaseMapperX { @@ -25,14 +23,6 @@ public interface DictTypeMapper extends BaseMapperX { .orderByDesc(DictTypeDO::getId)); } - default List selectList(DictTypeExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(DictTypeDO::getName, reqVO.getName()) - .likeIfPresent(DictTypeDO::getType, reqVO.getType()) - .eqIfPresent(DictTypeDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(DictTypeDO::getCreateTime, reqVO.getCreateTime())); - } - default DictTypeDO selectByType(String type) { return selectOne(DictTypeDO::getType, type); } @@ -41,8 +31,7 @@ public interface DictTypeMapper extends BaseMapperX { return selectOne(DictTypeDO::getName, name); } - int deleteById(@Param("id") Long id, @Param("deletedTime") LocalDateTime deletedTime); - @Update("UPDATE system_dict_type SET deleted = 1, deleted_time = #{deletedTime} WHERE id = #{id}") void updateToDelete(@Param("id") Long id, @Param("deletedTime") LocalDateTime deletedTime); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java index 93baced06..2e345e3ad 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/errorcode/ErrorCodeMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.errorcode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; import org.apache.ibatis.annotations.Mapper; @@ -25,16 +24,6 @@ public interface ErrorCodeMapper extends BaseMapperX { .orderByDesc(ErrorCodeDO::getCode)); } - default List selectList(ErrorCodeExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(ErrorCodeDO::getType, reqVO.getType()) - .likeIfPresent(ErrorCodeDO::getApplicationName, reqVO.getApplicationName()) - .eqIfPresent(ErrorCodeDO::getCode, reqVO.getCode()) - .likeIfPresent(ErrorCodeDO::getMessage, reqVO.getMessage()) - .betweenIfPresent(ErrorCodeDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ErrorCodeDO::getCode)); - } - default List selectListByCodes(Collection codes) { return selectList(ErrorCodeDO::getCode, codes); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java index 1617fe075..0cb47ebe7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/LoginLogMapper.java @@ -3,14 +3,11 @@ package cn.iocoder.yudao.module.system.dal.mysql.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - @Mapper public interface LoginLogMapper extends BaseMapperX { @@ -28,18 +25,4 @@ public interface LoginLogMapper extends BaseMapperX { return selectPage(reqVO, query); } - default List selectList(LoginLogExportReqVO reqVO) { - LambdaQueryWrapperX query = new LambdaQueryWrapperX() - .likeIfPresent(LoginLogDO::getUserIp, reqVO.getUserIp()) - .likeIfPresent(LoginLogDO::getUsername, reqVO.getUsername()) - .betweenIfPresent(LoginLogDO::getCreateTime, reqVO.getCreateTime()); - if (Boolean.TRUE.equals(reqVO.getStatus())) { - query.eq(LoginLogDO::getResult, LoginResultEnum.SUCCESS.getResult()); - } else if (Boolean.FALSE.equals(reqVO.getStatus())) { - query.gt(LoginLogDO::getResult, LoginResultEnum.SUCCESS.getResult()); - } - query.orderByDesc(LoginLogDO::getId); // 降序 - return selectList(query); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java index 86e53a510..0bed6b8cc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogMapper.java @@ -4,13 +4,11 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; -import java.util.List; @Mapper public interface OperateLogMapper extends BaseMapperX { @@ -30,19 +28,4 @@ public interface OperateLogMapper extends BaseMapperX { return selectPage(reqVO, query); } - default List selectList(OperateLogExportReqVO reqVO, Collection userIds) { - LambdaQueryWrapperX query = new LambdaQueryWrapperX() - .likeIfPresent(OperateLogDO::getModule, reqVO.getModule()) - .inIfPresent(OperateLogDO::getUserId, userIds) - .eqIfPresent(OperateLogDO::getType, reqVO.getType()) - .betweenIfPresent(OperateLogDO::getStartTime, reqVO.getStartTime()); - if (Boolean.TRUE.equals(reqVO.getSuccess())) { - query.eq(OperateLogDO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode()); - } else if (Boolean.FALSE.equals(reqVO.getSuccess())) { - query.gt(OperateLogDO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode()); - } - query.orderByDesc(OperateLogDO::getId); // 降序 - return selectList(query); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java index 55e853273..f6d86d1a1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMapper.java @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import org.apache.ibatis.annotations.Mapper; @@ -25,14 +24,6 @@ public interface RoleMapper extends BaseMapperX { .orderByDesc(RoleDO::getId)); } - default List selectList(RoleExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(RoleDO::getName, reqVO.getName()) - .likeIfPresent(RoleDO::getCode, reqVO.getCode()) - .eqIfPresent(RoleDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(BaseDO::getCreateTime, reqVO.getCreateTime())); - } - default RoleDO selectByName(String name) { return selectOne(RoleDO::getName, name); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sensitiveword/SensitiveWordMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sensitiveword/SensitiveWordMapper.java index 646e8f2b3..229171145 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sensitiveword/SensitiveWordMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sensitiveword/SensitiveWordMapper.java @@ -3,14 +3,12 @@ package cn.iocoder.yudao.module.system.dal.mysql.sensitiveword; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.time.LocalDateTime; -import java.util.List; /** * 敏感词 Mapper @@ -29,15 +27,6 @@ public interface SensitiveWordMapper extends BaseMapperX { .orderByDesc(SensitiveWordDO::getId)); } - default List selectList(SensitiveWordExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(SensitiveWordDO::getName, reqVO.getName()) - .likeIfPresent(SensitiveWordDO::getTags, reqVO.getTag()) - .eqIfPresent(SensitiveWordDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(SensitiveWordDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(SensitiveWordDO::getId)); - } - default SensitiveWordDO selectByName(String name) { return selectOne(SensitiveWordDO::getName, name); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java index 8ebd34fcf..f2388711a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsLogMapper.java @@ -3,13 +3,10 @@ package cn.iocoder.yudao.module.system.dal.mysql.sms; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - @Mapper public interface SmsLogMapper extends BaseMapperX { @@ -25,16 +22,4 @@ public interface SmsLogMapper extends BaseMapperX { .orderByDesc(SmsLogDO::getId)); } - default List selectList(SmsLogExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(SmsLogDO::getChannelId, reqVO.getChannelId()) - .eqIfPresent(SmsLogDO::getTemplateId, reqVO.getTemplateId()) - .likeIfPresent(SmsLogDO::getMobile, reqVO.getMobile()) - .eqIfPresent(SmsLogDO::getSendStatus, reqVO.getSendStatus()) - .betweenIfPresent(SmsLogDO::getSendTime, reqVO.getSendTime()) - .eqIfPresent(SmsLogDO::getReceiveStatus, reqVO.getReceiveStatus()) - .betweenIfPresent(SmsLogDO::getReceiveTime, reqVO.getReceiveTime()) - .orderByDesc(SmsLogDO::getId)); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java index ee6f54fef..a9a1ebb99 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/sms/SmsTemplateMapper.java @@ -3,13 +3,10 @@ package cn.iocoder.yudao.module.system.dal.mysql.sms; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - @Mapper public interface SmsTemplateMapper extends BaseMapperX { @@ -29,18 +26,6 @@ public interface SmsTemplateMapper extends BaseMapperX { .orderByDesc(SmsTemplateDO::getId)); } - default List selectList(SmsTemplateExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(SmsTemplateDO::getType, reqVO.getType()) - .eqIfPresent(SmsTemplateDO::getStatus, reqVO.getStatus()) - .likeIfPresent(SmsTemplateDO::getCode, reqVO.getCode()) - .likeIfPresent(SmsTemplateDO::getContent, reqVO.getContent()) - .likeIfPresent(SmsTemplateDO::getApiTemplateId, reqVO.getApiTemplateId()) - .eqIfPresent(SmsTemplateDO::getChannelId, reqVO.getChannelId()) - .betweenIfPresent(SmsTemplateDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(SmsTemplateDO::getId)); - } - default Long selectCountByChannelId(Long channelId) { return selectCount(SmsTemplateDO::getChannelId, channelId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialClientMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialClientMapper.java index 717a26142..4ebe226bf 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialClientMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialClientMapper.java @@ -20,7 +20,7 @@ public interface SocialClientMapper extends BaseMapperX { .likeIfPresent(SocialClientDO::getName, reqVO.getName()) .eqIfPresent(SocialClientDO::getSocialType, reqVO.getSocialType()) .eqIfPresent(SocialClientDO::getUserType, reqVO.getUserType()) - .eqIfPresent(SocialClientDO::getClientId, reqVO.getClientId()) + .likeIfPresent(SocialClientDO::getClientId, reqVO.getClientId()) .eqIfPresent(SocialClientDO::getStatus, reqVO.getStatus()) .orderByDesc(SocialClientDO::getId)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java index 8731e4628..aaca0160a 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.tenant; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import org.apache.ibatis.annotations.Mapper; @@ -28,20 +27,14 @@ public interface TenantMapper extends BaseMapperX { .orderByDesc(TenantDO::getId)); } - default List selectList(TenantExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(TenantDO::getName, reqVO.getName()) - .likeIfPresent(TenantDO::getContactName, reqVO.getContactName()) - .likeIfPresent(TenantDO::getContactMobile, reqVO.getContactMobile()) - .eqIfPresent(TenantDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(TenantDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(TenantDO::getId)); - } - default TenantDO selectByName(String name) { return selectOne(TenantDO::getName, name); } + default TenantDO selectByWebsite(String website) { + return selectOne(TenantDO::getWebsite, website); + } + default Long selectCountByPackageId(Long packageId) { return selectCount(TenantDO::getPackageId, packageId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java index 4e0827210..75bf3fa47 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/user/AdminUserMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.user; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.apache.ibatis.annotations.Mapper; @@ -36,15 +35,6 @@ public interface AdminUserMapper extends BaseMapperX { .orderByDesc(AdminUserDO::getId)); } - default List selectList(UserExportReqVO reqVO, Collection deptIds) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername()) - .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile()) - .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime()) - .inIfPresent(AdminUserDO::getDeptId, deptIds)); - } - default List selectListByNickname(String nickname) { return selectList(new LambdaQueryWrapperX().like(AdminUserDO::getNickname, nickname)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/rpc/config/RpcConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/rpc/config/RpcConfiguration.java index 73b7f8ccd..57ba6740a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/rpc/config/RpcConfiguration.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/rpc/config/RpcConfiguration.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.module.system.framework.rpc.config; import cn.iocoder.yudao.module.infra.api.file.FileApi; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) -@EnableFeignClients(clients = FileApi.class) +@EnableFeignClients(clients = {FileApi.class, WebSocketSenderApi.class}) public class RpcConfiguration { } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java index 1029b424c..11cb5f42e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptService.java @@ -1,13 +1,14 @@ package cn.iocoder.yudao.module.system.service.dept; -import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * 部门 Service 接口 @@ -19,17 +20,17 @@ public interface DeptService { /** * 创建部门 * - * @param reqVO 部门信息 + * @param createReqVO 部门信息 * @return 部门编号 */ - Long createDept(DeptCreateReqVO reqVO); + Long createDept(DeptSaveReqVO createReqVO); /** * 更新部门 * - * @param reqVO 部门信息 + * @param updateReqVO 部门信息 */ - void updateDept(DeptUpdateReqVO reqVO); + void updateDept(DeptSaveReqVO updateReqVO); /** * 删除部门 @@ -69,9 +70,6 @@ public interface DeptService { * @return 部门 Map */ default Map getDeptMap(Collection ids) { - if (CollUtil.isEmpty(ids)) { - return Collections.emptyMap(); - } List list = getDeptList(ids); return CollectionUtils.convertMap(list, DeptDO::getId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java index cde5a0021..183f11fc7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImpl.java @@ -3,15 +3,13 @@ package cn.iocoder.yudao.module.system.service.dept; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.dept.DeptConvert; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; -import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; @@ -42,14 +40,17 @@ public class DeptServiceImpl implements DeptService { @Override @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 - public Long createDept(DeptCreateReqVO reqVO) { - // 校验正确性 - if (reqVO.getParentId() == null) { - reqVO.setParentId(DeptIdEnum.ROOT.getId()); + public Long createDept(DeptSaveReqVO createReqVO) { + if (createReqVO.getParentId() == null) { + createReqVO.setParentId(DeptDO.PARENT_ID_ROOT); } - validateForCreateOrUpdate(null, reqVO.getParentId(), reqVO.getName()); + // 校验父部门的有效性 + validateParentDept(null, createReqVO.getParentId()); + // 校验部门名的唯一性 + validateDeptNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + // 插入部门 - DeptDO dept = DeptConvert.INSTANCE.convert(reqVO); + DeptDO dept = BeanUtils.toBean(createReqVO, DeptDO.class); deptMapper.insert(dept); return dept.getId(); } @@ -57,14 +58,19 @@ public class DeptServiceImpl implements DeptService { @Override @CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST, allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存 - public void updateDept(DeptUpdateReqVO reqVO) { - // 校验正确性 - if (reqVO.getParentId() == null) { - reqVO.setParentId(DeptIdEnum.ROOT.getId()); + public void updateDept(DeptSaveReqVO updateReqVO) { + if (updateReqVO.getParentId() == null) { + updateReqVO.setParentId(DeptDO.PARENT_ID_ROOT); } - validateForCreateOrUpdate(reqVO.getId(), reqVO.getParentId(), reqVO.getName()); + // 校验自己存在 + validateDeptExists(updateReqVO.getId()); + // 校验父部门的有效性 + validateParentDept(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验部门名的唯一性 + validateDeptNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + // 更新部门 - DeptDO updateObj = DeptConvert.INSTANCE.convert(reqVO); + DeptDO updateObj = BeanUtils.toBean(updateReqVO, DeptDO.class); deptMapper.updateById(updateObj); } @@ -82,15 +88,6 @@ public class DeptServiceImpl implements DeptService { deptMapper.deleteById(id); } - private void validateForCreateOrUpdate(Long id, Long parentId, String name) { - // 校验自己存在 - validateDeptExists(id); - // 校验父部门的有效性 - validateParentDept(id, parentId); - // 校验部门名的唯一性 - validateDeptNameUnique(id, parentId, name); - } - @VisibleForTesting void validateDeptExists(Long id) { if (id == null) { @@ -104,22 +101,36 @@ public class DeptServiceImpl implements DeptService { @VisibleForTesting void validateParentDept(Long id, Long parentId) { - if (parentId == null || DeptIdEnum.ROOT.getId().equals(parentId)) { + if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) { return; } - // 不能设置自己为父部门 - if (parentId.equals(id)) { + // 1. 不能设置自己为父部门 + if (Objects.equals(id, parentId)) { throw exception(DEPT_PARENT_ERROR); } - // 父岗位不存在 - DeptDO dept = deptMapper.selectById(parentId); - if (dept == null) { + // 2. 父部门不存在 + DeptDO parentDept = deptMapper.selectById(parentId); + if (parentDept == null) { throw exception(DEPT_PARENT_NOT_EXITS); } - // 父部门不能是原来的子部门 - List children = getChildDeptList(id); - if (children.stream().anyMatch(dept1 -> dept1.getId().equals(parentId))) { - throw exception(DEPT_PARENT_IS_CHILD); + // 3. 递归校验父部门,如果父部门是自己的子部门,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentDept.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(DEPT_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父部门 + if (parentId == null || DeptDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentDept = deptMapper.selectById(parentId); + if (parentDept == null) { + break; + } } } @@ -129,7 +140,7 @@ public class DeptServiceImpl implements DeptService { if (dept == null) { return; } - // 如果 id 为空,说明不用比较是否为相同 id 的岗位 + // 如果 id 为空,说明不用比较是否为相同 id 的部门 if (id == null) { throw exception(DEPT_NAME_DUPLICATE); } @@ -153,7 +164,9 @@ public class DeptServiceImpl implements DeptService { @Override public List getDeptList(DeptListReqVO reqVO) { - return deptMapper.selectList(reqVO); + List list = deptMapper.selectList(reqVO); + list.sort(Comparator.comparing(DeptDO::getSort)); + return list; } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java index c1b84c011..25604ceb3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostService.java @@ -1,19 +1,14 @@ package cn.iocoder.yudao.module.system.service.dept; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import org.springframework.lang.Nullable; import java.util.Collection; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; - /** * 岗位 Service 接口 * @@ -24,17 +19,17 @@ public interface PostService { /** * 创建岗位 * - * @param reqVO 岗位信息 + * @param createReqVO 岗位信息 * @return 岗位编号 */ - Long createPost(PostCreateReqVO reqVO); + Long createPost(PostSaveReqVO createReqVO); /** * 更新岗位 * - * @param reqVO 岗位信息 + * @param updateReqVO 岗位信息 */ - void updatePost(PostUpdateReqVO reqVO); + void updatePost(PostSaveReqVO updateReqVO); /** * 删除岗位信息 @@ -46,12 +41,10 @@ public interface PostService { /** * 获得岗位列表 * - * @param ids 岗位编号数组。如果为空,不进行筛选 + * @param ids 岗位编号数组 * @return 部门列表 */ - default List getPostList(@Nullable Collection ids) { - return getPostList(ids, asSet(CommonStatusEnum.ENABLE.getStatus(), CommonStatusEnum.DISABLE.getStatus())); - } + List getPostList(@Nullable Collection ids); /** * 获得符合条件的岗位列表 @@ -60,7 +53,8 @@ public interface PostService { * @param statuses 状态数组。如果为空,不进行筛选 * @return 部门列表 */ - List getPostList(@Nullable Collection ids, @Nullable Collection statuses); + List getPostList(@Nullable Collection ids, + @Nullable Collection statuses); /** * 获得岗位分页列表 @@ -70,14 +64,6 @@ public interface PostService { */ PageResult getPostPage(PostPageReqVO reqVO); - /** - * 获得岗位列表 - * - * @param reqVO 查询条件 - * @return 部门列表 - */ - List getPostList(PostExportReqVO reqVO); - /** * 获得岗位信息 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java index 3266a0c92..168386e50 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImpl.java @@ -3,11 +3,9 @@ package cn.iocoder.yudao.module.system.service.dept; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.dept.PostConvert; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.PostMapper; import org.springframework.stereotype.Service; @@ -15,6 +13,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -35,23 +34,23 @@ public class PostServiceImpl implements PostService { private PostMapper postMapper; @Override - public Long createPost(PostCreateReqVO reqVO) { + public Long createPost(PostSaveReqVO createReqVO) { // 校验正确性 - validatePostForCreateOrUpdate(null, reqVO.getName(), reqVO.getCode()); + validatePostForCreateOrUpdate(null, createReqVO.getName(), createReqVO.getCode()); // 插入岗位 - PostDO post = PostConvert.INSTANCE.convert(reqVO); + PostDO post = BeanUtils.toBean(createReqVO, PostDO.class); postMapper.insert(post); return post.getId(); } @Override - public void updatePost(PostUpdateReqVO reqVO) { + public void updatePost(PostSaveReqVO updateReqVO) { // 校验正确性 - validatePostForCreateOrUpdate(reqVO.getId(), reqVO.getName(), reqVO.getCode()); + validatePostForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getCode()); // 更新岗位 - PostDO updateObj = PostConvert.INSTANCE.convert(reqVO); + PostDO updateObj = BeanUtils.toBean(updateReqVO, PostDO.class); postMapper.updateById(updateObj); } @@ -109,6 +108,14 @@ public class PostServiceImpl implements PostService { } } + @Override + public List getPostList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return postMapper.selectBatchIds(ids); + } + @Override public List getPostList(Collection ids, Collection statuses) { return postMapper.selectList(ids, statuses); @@ -119,11 +126,6 @@ public class PostServiceImpl implements PostService { return postMapper.selectPage(reqVO); } - @Override - public List getPostList(PostExportReqVO reqVO) { - return postMapper.selectList(reqVO); - } - @Override public PostDO getPost(Long id) { return postMapper.selectById(id); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java index 3fc6a4071..a752476da 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataService.java @@ -1,11 +1,10 @@ package cn.iocoder.yudao.module.system.service.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; +import org.springframework.lang.Nullable; import java.util.Collection; import java.util.List; @@ -20,17 +19,17 @@ public interface DictDataService { /** * 创建字典数据 * - * @param reqVO 字典数据信息 + * @param createReqVO 字典数据信息 * @return 字典数据编号 */ - Long createDictData(DictDataCreateReqVO reqVO); + Long createDictData(DictDataSaveReqVO createReqVO); /** * 更新字典数据 * - * @param reqVO 字典数据信息 + * @param updateReqVO 字典数据信息 */ - void updateDictData(DictDataUpdateReqVO reqVO); + void updateDictData(DictDataSaveReqVO updateReqVO); /** * 删除字典数据 @@ -42,33 +41,19 @@ public interface DictDataService { /** * 获得字典数据列表 * + * @param status 状态 + * @param dictType 字典类型 * @return 字典数据全列表 */ - List getDictDataList(); + List getDictDataList(@Nullable Integer status, @Nullable String dictType); /** * 获得字典数据分页列表 * - * @param reqVO 分页请求 + * @param pageReqVO 分页请求 * @return 字典数据分页列表 */ - PageResult getDictDataPage(DictDataPageReqVO reqVO); - - /** - * 获得字典数据列表 - * - * @param reqVO 列表请求 - * @return 字典数据列表 - */ - List getDictDataList(DictDataExportReqVO reqVO); - - /** - * 获得字典数据列表 - * - * @param dictType 字典类型 - * @return 字典数据列表 - */ - List getEnabledDictDataListByType(String dictType); + PageResult getDictDataPage(DictDataPageReqVO pageReqVO); /** * 获得字典数据详情 @@ -84,7 +69,7 @@ public interface DictDataService { * @param dictType 字典类型 * @return 数据数量 */ - long countByDictType(String dictType); + long getDictDataCountByDictType(String dictType); /** * 校验字典数据们是否有效。如下情况,视为无效: @@ -113,4 +98,5 @@ public interface DictDataService { * @return 字典数据 */ DictDataDO parseDictData(String dictType, String label); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java index 8a49719fb..b9b87f0c4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java @@ -4,11 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.dict.DictDataConvert; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; @@ -48,29 +46,15 @@ public class DictDataServiceImpl implements DictDataService { private DictDataMapper dictDataMapper; @Override - public List getDictDataList() { - List list = dictDataMapper.selectList(DictDataDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); + public List getDictDataList(Integer status, String dictType) { + List list = dictDataMapper.selectListByStatusAndDictType(status, dictType); list.sort(COMPARATOR_TYPE_AND_SORT); return list; } @Override - public PageResult getDictDataPage(DictDataPageReqVO reqVO) { - return dictDataMapper.selectPage(reqVO); - } - - @Override - public List getDictDataList(DictDataExportReqVO reqVO) { - List list = dictDataMapper.selectList(reqVO); - list.sort(COMPARATOR_TYPE_AND_SORT); - return list; - } - - @Override - public List getEnabledDictDataListByType(String dictType) { - List list = dictDataMapper.selectListByTypeAndStatus(dictType, CommonStatusEnum.ENABLE.getStatus()); - list.sort(COMPARATOR_TYPE_AND_SORT); - return list; + public PageResult getDictDataPage(DictDataPageReqVO pageReqVO) { + return dictDataMapper.selectPage(pageReqVO); } @Override @@ -79,23 +63,29 @@ public class DictDataServiceImpl implements DictDataService { } @Override - public Long createDictData(DictDataCreateReqVO reqVO) { - // 校验正确性 - validateDictDataForCreateOrUpdate(null, reqVO.getValue(), reqVO.getDictType()); + public Long createDictData(DictDataSaveReqVO createReqVO) { + // 校验字典类型有效 + validateDictTypeExists(createReqVO.getDictType()); + // 校验字典数据的值的唯一性 + validateDictDataValueUnique(null, createReqVO.getDictType(), createReqVO.getValue()); // 插入字典类型 - DictDataDO dictData = DictDataConvert.INSTANCE.convert(reqVO); + DictDataDO dictData = BeanUtils.toBean(createReqVO, DictDataDO.class); dictDataMapper.insert(dictData); return dictData.getId(); } @Override - public void updateDictData(DictDataUpdateReqVO reqVO) { - // 校验正确性 - validateDictDataForCreateOrUpdate(reqVO.getId(), reqVO.getValue(), reqVO.getDictType()); + public void updateDictData(DictDataSaveReqVO updateReqVO) { + // 校验自己存在 + validateDictDataExists(updateReqVO.getId()); + // 校验字典类型有效 + validateDictTypeExists(updateReqVO.getDictType()); + // 校验字典数据的值的唯一性 + validateDictDataValueUnique(updateReqVO.getId(), updateReqVO.getDictType(), updateReqVO.getValue()); // 更新字典类型 - DictDataDO updateObj = DictDataConvert.INSTANCE.convert(reqVO); + DictDataDO updateObj = BeanUtils.toBean(updateReqVO, DictDataDO.class); dictDataMapper.updateById(updateObj); } @@ -109,19 +99,10 @@ public class DictDataServiceImpl implements DictDataService { } @Override - public long countByDictType(String dictType) { + public long getDictDataCountByDictType(String dictType) { return dictDataMapper.selectCountByDictType(dictType); } - private void validateDictDataForCreateOrUpdate(Long id, String value, String dictType) { - // 校验自己存在 - validateDictDataExists(id); - // 校验字典类型有效 - validateDictTypeExists(dictType); - // 校验字典数据的值的唯一性 - validateDictDataValueUnique(id, dictType, value); - } - @VisibleForTesting public void validateDictDataValueUnique(Long id, String dictType, String value) { DictDataDO dictData = dictDataMapper.selectByDictTypeAndValue(dictType, value); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java index 4b334b08b..40911891c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeService.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.system.service.dict; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import java.util.List; @@ -19,17 +17,17 @@ public interface DictTypeService { /** * 创建字典类型 * - * @param reqVO 字典类型信息 + * @param createReqVO 字典类型信息 * @return 字典类型编号 */ - Long createDictType(DictTypeCreateReqVO reqVO); + Long createDictType(DictTypeSaveReqVO createReqVO); /** * 更新字典类型 * - * @param reqVO 字典类型信息 + * @param updateReqVO 字典类型信息 */ - void updateDictType(DictTypeUpdateReqVO reqVO); + void updateDictType(DictTypeSaveReqVO updateReqVO); /** * 删除字典类型 @@ -41,18 +39,10 @@ public interface DictTypeService { /** * 获得字典类型分页列表 * - * @param reqVO 分页请求 + * @param pageReqVO 分页请求 * @return 字典类型分页列表 */ - PageResult getDictTypePage(DictTypePageReqVO reqVO); - - /** - * 获得字典类型列表 - * - * @param reqVO 列表请求 - * @return 字典类型列表 - */ - List getDictTypeList(DictTypeExportReqVO reqVO); + PageResult getDictTypePage(DictTypePageReqVO pageReqVO); /** * 获得字典类型详情 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java index cc731affe..5e7f27e55 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImpl.java @@ -3,11 +3,9 @@ package cn.iocoder.yudao.module.system.service.dict; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.dict.DictTypeConvert; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper; import com.google.common.annotations.VisibleForTesting; @@ -35,13 +33,8 @@ public class DictTypeServiceImpl implements DictTypeService { private DictTypeMapper dictTypeMapper; @Override - public PageResult getDictTypePage(DictTypePageReqVO reqVO) { - return dictTypeMapper.selectPage(reqVO); - } - - @Override - public List getDictTypeList(DictTypeExportReqVO reqVO) { - return dictTypeMapper.selectList(reqVO); + public PageResult getDictTypePage(DictTypePageReqVO pageReqVO) { + return dictTypeMapper.selectPage(pageReqVO); } @Override @@ -55,24 +48,30 @@ public class DictTypeServiceImpl implements DictTypeService { } @Override - public Long createDictType(DictTypeCreateReqVO reqVO) { - // 校验正确性 - validateDictTypeForCreateOrUpdate(null, reqVO.getName(), reqVO.getType()); + public Long createDictType(DictTypeSaveReqVO createReqVO) { + // 校验字典类型的名字的唯一性 + validateDictTypeNameUnique(null, createReqVO.getName()); + // 校验字典类型的类型的唯一性 + validateDictTypeUnique(null, createReqVO.getType()); // 插入字典类型 - DictTypeDO dictType = DictTypeConvert.INSTANCE.convert(reqVO) - .setDeletedTime(LocalDateTimeUtils.EMPTY); // 唯一索引,避免 null 值 + DictTypeDO dictType = BeanUtils.toBean(createReqVO, DictTypeDO.class); + dictType.setDeletedTime(LocalDateTimeUtils.EMPTY); // 唯一索引,避免 null 值 dictTypeMapper.insert(dictType); return dictType.getId(); } @Override - public void updateDictType(DictTypeUpdateReqVO reqVO) { - // 校验正确性 - validateDictTypeForCreateOrUpdate(reqVO.getId(), reqVO.getName(), null); + public void updateDictType(DictTypeSaveReqVO updateReqVO) { + // 校验自己存在 + validateDictTypeExists(updateReqVO.getId()); + // 校验字典类型的名字的唯一性 + validateDictTypeNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // 校验字典类型的类型的唯一性 + validateDictTypeUnique(updateReqVO.getId(), updateReqVO.getType()); // 更新字典类型 - DictTypeDO updateObj = DictTypeConvert.INSTANCE.convert(reqVO); + DictTypeDO updateObj = BeanUtils.toBean(updateReqVO, DictTypeDO.class); dictTypeMapper.updateById(updateObj); } @@ -81,7 +80,7 @@ public class DictTypeServiceImpl implements DictTypeService { // 校验是否存在 DictTypeDO dictType = validateDictTypeExists(id); // 校验是否有字典数据 - if (dictDataService.countByDictType(dictType.getType()) > 0) { + if (dictDataService.getDictDataCountByDictType(dictType.getType()) > 0) { throw exception(DICT_TYPE_HAS_CHILDREN); } // 删除字典类型 @@ -93,15 +92,6 @@ public class DictTypeServiceImpl implements DictTypeService { return dictTypeMapper.selectList(); } - private void validateDictTypeForCreateOrUpdate(Long id, String name, String type) { - // 校验自己存在 - validateDictTypeExists(id); - // 校验字典类型的名字的唯一性 - validateDictTypeNameUnique(id, name); - // 校验字典类型的类型的唯一性 - validateDictTypeUnique(id, type); - } - @VisibleForTesting void validateDictTypeNameUnique(Long id, String name) { DictTypeDO dictType = dictTypeMapper.selectByName(name); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java index 869784e36..b3894582d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeService.java @@ -3,11 +3,9 @@ package cn.iocoder.yudao.module.system.service.errorcode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; import javax.validation.Valid; import java.time.LocalDateTime; @@ -44,14 +42,14 @@ public interface ErrorCodeService { * @param createReqVO 创建信息 * @return 编号 */ - Long createErrorCode(@Valid ErrorCodeCreateReqVO createReqVO); + Long createErrorCode(@Valid ErrorCodeSaveReqVO createReqVO); /** * 更新错误码 * * @param updateReqVO 更新信息 */ - void updateErrorCode(@Valid ErrorCodeUpdateReqVO updateReqVO); + void updateErrorCode(@Valid ErrorCodeSaveReqVO updateReqVO); /** * 删除错误码 @@ -76,12 +74,4 @@ public interface ErrorCodeService { */ PageResult getErrorCodePage(ErrorCodePageReqVO pageReqVO); - /** - * 获得错误码列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 错误码列表 - */ - List getErrorCodeList(ErrorCodeExportReqVO exportReqVO); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java index ed0712a90..45dfb7c7d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceImpl.java @@ -2,13 +2,11 @@ package cn.iocoder.yudao.module.system.service.errorcode; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.errorcode.ErrorCodeConvert; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; import cn.iocoder.yudao.module.system.dal.mysql.errorcode.ErrorCodeMapper; import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum; @@ -43,12 +41,12 @@ public class ErrorCodeServiceImpl implements ErrorCodeService { private ErrorCodeMapper errorCodeMapper; @Override - public Long createErrorCode(ErrorCodeCreateReqVO createReqVO) { + public Long createErrorCode(ErrorCodeSaveReqVO createReqVO) { // 校验 code 重复 validateCodeDuplicate(createReqVO.getCode(), null); // 插入 - ErrorCodeDO errorCode = ErrorCodeConvert.INSTANCE.convert(createReqVO) + ErrorCodeDO errorCode = BeanUtils.toBean(createReqVO, ErrorCodeDO.class) .setType(ErrorCodeTypeEnum.MANUAL_OPERATION.getType()); errorCodeMapper.insert(errorCode); // 返回 @@ -56,14 +54,14 @@ public class ErrorCodeServiceImpl implements ErrorCodeService { } @Override - public void updateErrorCode(ErrorCodeUpdateReqVO updateReqVO) { + public void updateErrorCode(ErrorCodeSaveReqVO updateReqVO) { // 校验存在 validateErrorCodeExists(updateReqVO.getId()); // 校验 code 重复 validateCodeDuplicate(updateReqVO.getCode(), updateReqVO.getId()); // 更新 - ErrorCodeDO updateObj = ErrorCodeConvert.INSTANCE.convert(updateReqVO) + ErrorCodeDO updateObj = BeanUtils.toBean(updateReqVO, ErrorCodeDO.class) .setType(ErrorCodeTypeEnum.MANUAL_OPERATION.getType()); errorCodeMapper.updateById(updateObj); } @@ -116,11 +114,6 @@ public class ErrorCodeServiceImpl implements ErrorCodeService { return errorCodeMapper.selectPage(pageReqVO); } - @Override - public List getErrorCodeList(ErrorCodeExportReqVO exportReqVO) { - return errorCodeMapper.selectList(exportReqVO); - } - @Override @Transactional public void autoGenerateErrorCodes(List autoGenerateDTOs) { @@ -134,40 +127,40 @@ public class ErrorCodeServiceImpl implements ErrorCodeService { // 遍历 autoGenerateBOs 数组,逐个插入或更新。考虑到每次量级不大,就不走批量了 autoGenerateDTOs.forEach(autoGenerateDTO -> { - ErrorCodeDO errorCodeDO = errorCodeDOMap.get(autoGenerateDTO.getCode()); + ErrorCodeDO errorCode = errorCodeDOMap.get(autoGenerateDTO.getCode()); // 不存在,则进行新增 - if (errorCodeDO == null) { - errorCodeDO = ErrorCodeConvert.INSTANCE.convert(autoGenerateDTO) + if (errorCode == null) { + errorCode = BeanUtils.toBean(autoGenerateDTO, ErrorCodeDO.class) .setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType()); - errorCodeMapper.insert(errorCodeDO); + errorCodeMapper.insert(errorCode); return; } // 存在,则进行更新。更新有三个前置条件: // 条件 1. 只更新自动生成的错误码,即 Type 为 ErrorCodeTypeEnum.AUTO_GENERATION - if (!ErrorCodeTypeEnum.AUTO_GENERATION.getType().equals(errorCodeDO.getType())) { + if (!ErrorCodeTypeEnum.AUTO_GENERATION.getType().equals(errorCode.getType())) { return; } // 条件 2. 分组 applicationName 必须匹配,避免存在错误码冲突的情况 - if (!autoGenerateDTO.getApplicationName().equals(errorCodeDO.getApplicationName())) { + if (!autoGenerateDTO.getApplicationName().equals(errorCode.getApplicationName())) { log.error("[autoGenerateErrorCodes][自动创建({}/{}) 错误码失败,数据库中已经存在({}/{})]", autoGenerateDTO.getCode(), autoGenerateDTO.getApplicationName(), - errorCodeDO.getCode(), errorCodeDO.getApplicationName()); + errorCode.getCode(), errorCode.getApplicationName()); return; } // 条件 3. 错误提示语存在差异 - if (autoGenerateDTO.getMessage().equals(errorCodeDO.getMessage())) { + if (autoGenerateDTO.getMessage().equals(errorCode.getMessage())) { return; } // 最终匹配,进行更新 - errorCodeMapper.updateById(new ErrorCodeDO().setId(errorCodeDO.getId()).setMessage(autoGenerateDTO.getMessage())); + errorCodeMapper.updateById(new ErrorCodeDO().setId(errorCode.getId()).setMessage(autoGenerateDTO.getMessage())); }); } @Override public List getErrorCodeList(String applicationName, LocalDateTime minUpdateTime) { - List errorCodeDOs = errorCodeMapper.selectListByApplicationNameAndUpdateTimeGt( + List list = errorCodeMapper.selectListByApplicationNameAndUpdateTimeGt( applicationName, minUpdateTime); - return ErrorCodeConvert.INSTANCE.convertList03(errorCodeDOs); + return BeanUtils.toBean(list, ErrorCodeRespDTO.class); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java index 38b4fe78e..64cd07b74 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogService.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.system.service.logger; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import javax.validation.Valid; -import java.util.List; /** * 登录日志 Service 接口 @@ -17,18 +15,10 @@ public interface LoginLogService { /** * 获得登录日志分页 * - * @param reqVO 分页条件 + * @param pageReqVO 分页条件 * @return 登录日志分页 */ - PageResult getLoginLogPage(LoginLogPageReqVO reqVO); - - /** - * 获得登录日志列表 - * - * @param reqVO 列表条件 - * @return 登录日志列表 - */ - List getLoginLogList(LoginLogExportReqVO reqVO); + PageResult getLoginLogPage(LoginLogPageReqVO pageReqVO); /** * 创建登录日志 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java index 0b806f6da..e1de978c8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java @@ -1,17 +1,15 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; -import cn.iocoder.yudao.module.system.convert.logger.LoginLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.List; /** * 登录日志 Service 实现 @@ -24,18 +22,13 @@ public class LoginLogServiceImpl implements LoginLogService { private LoginLogMapper loginLogMapper; @Override - public PageResult getLoginLogPage(LoginLogPageReqVO reqVO) { - return loginLogMapper.selectPage(reqVO); - } - - @Override - public List getLoginLogList(LoginLogExportReqVO reqVO) { - return loginLogMapper.selectList(reqVO); + public PageResult getLoginLogPage(LoginLogPageReqVO pageReqVO) { + return loginLogMapper.selectPage(pageReqVO); } @Override public void createLoginLog(LoginLogCreateReqDTO reqDTO) { - LoginLogDO loginLog = LoginLogConvert.INSTANCE.convert(reqDTO); + LoginLogDO loginLog = BeanUtils.toBean(reqDTO, LoginLogDO.class); loginLogMapper.insert(loginLog); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java index 434ecbc46..89e562c65 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java @@ -2,12 +2,9 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; -import java.util.List; - /** * 操作日志 Service 接口 * @@ -25,17 +22,9 @@ public interface OperateLogService { /** * 获得操作日志分页列表 * - * @param reqVO 分页条件 + * @param pageReqVO 分页条件 * @return 操作日志分页列表 */ - PageResult getOperateLogPage(OperateLogPageReqVO reqVO); - - /** - * 获得操作日志列表 - * - * @param reqVO 列表条件 - * @return 日志列表 - */ - List getOperateLogList(OperateLogExportReqVO reqVO); + PageResult getOperateLogPage(OperateLogPageReqVO pageReqVO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index c899696ac..5890a7fb4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -3,11 +3,10 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; -import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; @@ -18,13 +17,16 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; -import java.util.Collections; -import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.RESULT_MAX_LENGTH; +/** + * 操作日志 Service 实现类 + * + * @author 芋道源码 + */ @Service @Validated @Slf4j @@ -38,38 +40,24 @@ public class OperateLogServiceImpl implements OperateLogService { @Override public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { - OperateLogDO logDO = OperateLogConvert.INSTANCE.convert(createReqDTO); - logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); - logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH)); - operateLogMapper.insert(logDO); + OperateLogDO log = BeanUtils.toBean(createReqDTO, OperateLogDO.class); + log.setJavaMethodArgs(StrUtils.maxLength(log.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); + log.setResultData(StrUtils.maxLength(log.getResultData(), RESULT_MAX_LENGTH)); + operateLogMapper.insert(log); } @Override - public PageResult getOperateLogPage(OperateLogPageReqVO reqVO) { + public PageResult getOperateLogPage(OperateLogPageReqVO pageReqVO) { // 处理基于用户昵称的查询 Collection userIds = null; - if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { - userIds = convertSet(userService.getUserListByNickname(reqVO.getUserNickname()), AdminUserDO::getId); + if (StrUtil.isNotEmpty(pageReqVO.getUserNickname())) { + userIds = convertSet(userService.getUserListByNickname(pageReqVO.getUserNickname()), AdminUserDO::getId); if (CollUtil.isEmpty(userIds)) { return PageResult.empty(); } } // 查询分页 - return operateLogMapper.selectPage(reqVO, userIds); - } - - @Override - public List getOperateLogList(OperateLogExportReqVO reqVO) { - // 处理基于用户昵称的查询 - Collection userIds = null; - if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { - userIds = convertSet(userService.getUserListByNickname(reqVO.getUserNickname()), AdminUserDO::getId); - if (CollUtil.isEmpty(userIds)) { - return Collections.emptyList(); - } - } - // 查询列表 - return operateLogMapper.selectList(reqVO, userIds); + return operateLogMapper.selectPage(pageReqVO, userIds); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java index 62e97a829..72d62568c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.service.mail; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import javax.validation.Valid; @@ -23,14 +22,14 @@ public interface MailAccountService { * @param createReqVO 邮箱账号信息 * @return 编号 */ - Long createMailAccount(@Valid MailAccountCreateReqVO createReqVO); + Long createMailAccount(@Valid MailAccountSaveReqVO createReqVO); /** * 修改邮箱账号 * * @param updateReqVO 邮箱账号信息 */ - void updateMailAccount(@Valid MailAccountUpdateReqVO updateReqVO); + void updateMailAccount(@Valid MailAccountSaveReqVO updateReqVO); /** * 删除邮箱账号 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java index 94b02dbab..73cd9d3a1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImpl.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.system.service.mail; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -39,21 +38,20 @@ public class MailAccountServiceImpl implements MailAccountService { private MailTemplateService mailTemplateService; @Override - public Long createMailAccount(MailAccountCreateReqVO createReqVO) { - // 插入 - MailAccountDO account = MailAccountConvert.INSTANCE.convert(createReqVO); + public Long createMailAccount(MailAccountSaveReqVO createReqVO) { + MailAccountDO account = BeanUtils.toBean(createReqVO, MailAccountDO.class); mailAccountMapper.insert(account); return account.getId(); } @Override @CacheEvict(value = RedisKeyConstants.MAIL_ACCOUNT, key = "#updateReqVO.id") - public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) { + public void updateMailAccount(MailAccountSaveReqVO updateReqVO) { // 校验是否存在 validateMailAccountExists(updateReqVO.getId()); // 更新 - MailAccountDO updateObj = MailAccountConvert.INSTANCE.convert(updateReqVO); + MailAccountDO updateObj = BeanUtils.toBean(updateReqVO, MailAccountDO.class); mailAccountMapper.updateById(updateObj); } @@ -63,7 +61,7 @@ public class MailAccountServiceImpl implements MailAccountService { // 校验是否存在账号 validateMailAccountExists(id); // 校验是否存在关联模版 - if (mailTemplateService.countByAccountId(id) > 0) { + if (mailTemplateService.getMailTemplateCountByAccountId(id) > 0) { throw exception(MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImpl.java index 3e7cdc48b..292acab07 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogServiceImpl.java @@ -12,7 +12,6 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.Date; import java.util.Map; import java.util.Objects; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java index 69e02c810..0f5a49f1d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.service.mail; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; import javax.validation.Valid; @@ -24,14 +23,14 @@ public interface MailTemplateService { * @param createReqVO 邮件信息 * @return 编号 */ - Long createMailTemplate(@Valid MailTemplateCreateReqVO createReqVO); + Long createMailTemplate(@Valid MailTemplateSaveReqVO createReqVO); /** * 邮件模版修改 * * @param updateReqVO 邮件信息 */ - void updateMailTemplate(@Valid MailTemplateUpdateReqVO updateReqVO); + void updateMailTemplate(@Valid MailTemplateSaveReqVO updateReqVO); /** * 邮件模版删除 @@ -86,6 +85,6 @@ public interface MailTemplateService { * @param accountId 账号编号 * @return 数量 */ - long countByAccountId(Long accountId); + long getMailTemplateCountByAccountId(Long accountId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java index 6d17c2b59..530d588a3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImpl.java @@ -4,10 +4,9 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -48,12 +47,12 @@ public class MailTemplateServiceImpl implements MailTemplateService { private MailTemplateMapper mailTemplateMapper; @Override - public Long createMailTemplate(MailTemplateCreateReqVO createReqVO) { + public Long createMailTemplate(MailTemplateSaveReqVO createReqVO) { // 校验 code 是否唯一 validateCodeUnique(null, createReqVO.getCode()); // 插入 - MailTemplateDO template = MailTemplateConvert.INSTANCE.convert(createReqVO) + MailTemplateDO template = BeanUtils.toBean(createReqVO, MailTemplateDO.class) .setParams(parseTemplateContentParams(createReqVO.getContent())); mailTemplateMapper.insert(template); return template.getId(); @@ -62,14 +61,14 @@ public class MailTemplateServiceImpl implements MailTemplateService { @Override @CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE, allEntries = true) // allEntries 清空所有缓存,因为可能修改到 code 字段,不好清理 - public void updateMailTemplate(@Valid MailTemplateUpdateReqVO updateReqVO) { + public void updateMailTemplate(@Valid MailTemplateSaveReqVO updateReqVO) { // 校验是否存在 validateMailTemplateExists(updateReqVO.getId()); // 校验 code 是否唯一 validateCodeUnique(updateReqVO.getId(),updateReqVO.getCode()); // 更新 - MailTemplateDO updateObj = MailTemplateConvert.INSTANCE.convert(updateReqVO) + MailTemplateDO updateObj = BeanUtils.toBean(updateReqVO, MailTemplateDO.class) .setParams(parseTemplateContentParams(updateReqVO.getContent())); mailTemplateMapper.updateById(updateObj); } @@ -132,7 +131,7 @@ public class MailTemplateServiceImpl implements MailTemplateService { } @Override - public long countByAccountId(Long accountId) { + public long getMailTemplateCountByAccountId(Long accountId) { return mailTemplateMapper.selectCountByAccountId(accountId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java index 432fe876e..c935c49b2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.service.notice; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; /** @@ -12,29 +11,29 @@ import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; public interface NoticeService { /** - * 创建岗位公告公告 + * 创建通知公告 * - * @param reqVO 岗位公告公告信息 - * @return 岗位公告公告编号 + * @param createReqVO 通知公告 + * @return 编号 */ - Long createNotice(NoticeCreateReqVO reqVO); + Long createNotice(NoticeSaveReqVO createReqVO); /** - * 更新岗位公告公告 + * 更新通知公告 * - * @param reqVO 岗位公告公告信息 + * @param reqVO 通知公告 */ - void updateNotice(NoticeUpdateReqVO reqVO); + void updateNotice(NoticeSaveReqVO reqVO); /** - * 删除岗位公告公告信息 + * 删除通知公告 * - * @param id 岗位公告公告编号 + * @param id 编号 */ void deleteNotice(Long id); /** - * 获得岗位公告公告分页列表 + * 获得通知公告分页列表 * * @param reqVO 分页条件 * @return 部门分页列表 @@ -42,10 +41,10 @@ public interface NoticeService { PageResult getNoticePage(NoticePageReqVO reqVO); /** - * 获得岗位公告公告信息 + * 获得通知公告 * - * @param id 岗位公告公告编号 - * @return 岗位公告公告信息 + * @param id 编号 + * @return 通知公告 */ NoticeDO getNotice(Long id); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java index 1930e64c1..f0204c3cf 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImpl.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.system.service.notice; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.notice.NoticeConvert; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper; import com.google.common.annotations.VisibleForTesting; @@ -27,18 +26,18 @@ public class NoticeServiceImpl implements NoticeService { private NoticeMapper noticeMapper; @Override - public Long createNotice(NoticeCreateReqVO reqVO) { - NoticeDO notice = NoticeConvert.INSTANCE.convert(reqVO); + public Long createNotice(NoticeSaveReqVO createReqVO) { + NoticeDO notice = BeanUtils.toBean(createReqVO, NoticeDO.class); noticeMapper.insert(notice); return notice.getId(); } @Override - public void updateNotice(NoticeUpdateReqVO reqVO) { + public void updateNotice(NoticeSaveReqVO updateReqVO) { // 校验是否存在 - validateNoticeExists(reqVO.getId()); + validateNoticeExists(updateReqVO.getId()); // 更新通知公告 - NoticeDO updateObj = NoticeConvert.INSTANCE.convert(reqVO); + NoticeDO updateObj = BeanUtils.toBean(updateReqVO, NoticeDO.class); noticeMapper.updateById(updateObj); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java index 2657e0dd9..76e1554ad 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.service.notify; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; import javax.validation.Valid; @@ -22,14 +21,14 @@ public interface NotifyTemplateService { * @param createReqVO 创建信息 * @return 编号 */ - Long createNotifyTemplate(@Valid NotifyTemplateCreateReqVO createReqVO); + Long createNotifyTemplate(@Valid NotifyTemplateSaveReqVO createReqVO); /** * 更新站内信模版 * * @param updateReqVO 更新信息 */ - void updateNotifyTemplate(@Valid NotifyTemplateUpdateReqVO updateReqVO); + void updateNotifyTemplate(@Valid NotifyTemplateSaveReqVO updateReqVO); /** * 删除站内信模版 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java index c28e42d7c..cd8e9076f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImpl.java @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.system.service.notify; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.notify.NotifyTemplateConvert; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -45,12 +44,12 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { private NotifyTemplateMapper notifyTemplateMapper; @Override - public Long createNotifyTemplate(NotifyTemplateCreateReqVO createReqVO) { + public Long createNotifyTemplate(NotifyTemplateSaveReqVO createReqVO) { // 校验站内信编码是否重复 validateNotifyTemplateCodeDuplicate(null, createReqVO.getCode()); // 插入 - NotifyTemplateDO notifyTemplate = NotifyTemplateConvert.INSTANCE.convert(createReqVO); + NotifyTemplateDO notifyTemplate = BeanUtils.toBean(createReqVO, NotifyTemplateDO.class); notifyTemplate.setParams(parseTemplateContentParams(notifyTemplate.getContent())); notifyTemplateMapper.insert(notifyTemplate); return notifyTemplate.getId(); @@ -59,14 +58,14 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { @Override @CacheEvict(cacheNames = RedisKeyConstants.NOTIFY_TEMPLATE, allEntries = true) // allEntries 清空所有缓存,因为可能修改到 code 字段,不好清理 - public void updateNotifyTemplate(NotifyTemplateUpdateReqVO updateReqVO) { + public void updateNotifyTemplate(NotifyTemplateSaveReqVO updateReqVO) { // 校验存在 validateNotifyTemplateExists(updateReqVO.getId()); // 校验站内信编码是否重复 validateNotifyTemplateCodeDuplicate(updateReqVO.getId(), updateReqVO.getCode()); // 更新 - NotifyTemplateDO updateObj = NotifyTemplateConvert.INSTANCE.convert(updateReqVO); + NotifyTemplateDO updateObj = BeanUtils.toBean(updateReqVO, NotifyTemplateDO.class); updateObj.setParams(parseTemplateContentParams(updateObj.getContent())); notifyTemplateMapper.updateById(updateObj); } @@ -135,4 +134,5 @@ public class NotifyTemplateServiceImpl implements NotifyTemplateService { public String formatNotifyTemplateContent(String content, Map params) { return StrUtil.format(content, params); } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java index de826c261..10735537f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.service.oauth2; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; import javax.validation.Valid; @@ -24,14 +23,14 @@ public interface OAuth2ClientService { * @param createReqVO 创建信息 * @return 编号 */ - Long createOAuth2Client(@Valid OAuth2ClientCreateReqVO createReqVO); + Long createOAuth2Client(@Valid OAuth2ClientSaveReqVO createReqVO); /** * 更新 OAuth2 客户端 * * @param updateReqVO 更新信息 */ - void updateOAuth2Client(@Valid OAuth2ClientUpdateReqVO updateReqVO); + void updateOAuth2Client(@Valid OAuth2ClientSaveReqVO updateReqVO); /** * 删除 OAuth2 客户端 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java index f1f102499..66392b131 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java @@ -6,11 +6,10 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.auth.OAuth2ClientConvert; +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -41,25 +40,25 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { private OAuth2ClientMapper oauth2ClientMapper; @Override - public Long createOAuth2Client(OAuth2ClientCreateReqVO createReqVO) { + public Long createOAuth2Client(OAuth2ClientSaveReqVO createReqVO) { validateClientIdExists(null, createReqVO.getClientId()); // 插入 - OAuth2ClientDO oauth2Client = OAuth2ClientConvert.INSTANCE.convert(createReqVO); - oauth2ClientMapper.insert(oauth2Client); - return oauth2Client.getId(); + OAuth2ClientDO client = BeanUtils.toBean(createReqVO, OAuth2ClientDO.class); + oauth2ClientMapper.insert(client); + return client.getId(); } @Override @CacheEvict(cacheNames = RedisKeyConstants.OAUTH_CLIENT, allEntries = true) // allEntries 清空所有缓存,因为可能修改到 clientId 字段,不好清理 - public void updateOAuth2Client(OAuth2ClientUpdateReqVO updateReqVO) { + public void updateOAuth2Client(OAuth2ClientSaveReqVO updateReqVO) { // 校验存在 validateOAuth2ClientExists(updateReqVO.getId()); // 校验 Client 未被占用 validateClientIdExists(updateReqVO.getId(), updateReqVO.getClientId()); // 更新 - OAuth2ClientDO updateObj = OAuth2ClientConvert.INSTANCE.convert(updateReqVO); + OAuth2ClientDO updateObj = BeanUtils.toBean(updateReqVO, OAuth2ClientDO.class); oauth2ClientMapper.updateById(updateObj); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java index e627ba1f4..ce201a230 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java @@ -1,8 +1,7 @@ package cn.iocoder.yudao.module.system.service.permission; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import java.util.Collection; @@ -18,17 +17,17 @@ public interface MenuService { /** * 创建菜单 * - * @param reqVO 菜单信息 + * @param createReqVO 菜单信息 * @return 创建出来的菜单编号 */ - Long createMenu(MenuCreateReqVO reqVO); + Long createMenu(MenuSaveVO createReqVO); /** * 更新菜单 * - * @param reqVO 菜单信息 + * @param updateReqVO 菜单信息 */ - void updateMenu(MenuUpdateReqVO reqVO); + void updateMenu(MenuSaveVO updateReqVO); /** * 删除菜单 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java index c26217516..bca2bd95a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java @@ -1,11 +1,9 @@ package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.permission.MenuConvert; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -21,7 +19,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Collection; -import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -47,16 +44,16 @@ public class MenuServiceImpl implements MenuService { private TenantService tenantService; @Override - @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#reqVO.permission", - condition = "#reqVO.permission != null") - public Long createMenu(MenuCreateReqVO reqVO) { + @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#createReqVO.permission", + condition = "#createReqVO.permission != null") + public Long createMenu(MenuSaveVO createReqVO) { // 校验父菜单存在 - validateParentMenu(reqVO.getParentId(), null); + validateParentMenu(createReqVO.getParentId(), null); // 校验菜单(自己) - validateMenu(reqVO.getParentId(), reqVO.getName(), null); + validateMenu(createReqVO.getParentId(), createReqVO.getName(), null); // 插入数据库 - MenuDO menu = MenuConvert.INSTANCE.convert(reqVO); + MenuDO menu = BeanUtils.toBean(createReqVO, MenuDO.class); initMenuProperty(menu); menuMapper.insert(menu); // 返回 @@ -66,20 +63,20 @@ public class MenuServiceImpl implements MenuService { @Override @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, allEntries = true) // allEntries 清空所有缓存,因为 permission 如果变更,涉及到新老两个 permission。直接清理,简单有效 - public void updateMenu(MenuUpdateReqVO reqVO) { + public void updateMenu(MenuSaveVO updateReqVO) { // 校验更新的菜单是否存在 - if (menuMapper.selectById(reqVO.getId()) == null) { + if (menuMapper.selectById(updateReqVO.getId()) == null) { throw exception(MENU_NOT_EXISTS); } // 校验父菜单存在 - validateParentMenu(reqVO.getParentId(), reqVO.getId()); + validateParentMenu(updateReqVO.getParentId(), updateReqVO.getId()); // 校验菜单(自己) - validateMenu(reqVO.getParentId(), reqVO.getName(), reqVO.getId()); + validateMenu(updateReqVO.getParentId(), updateReqVO.getName(), updateReqVO.getId()); // 更新到数据库 - MenuDO updateObject = MenuConvert.INSTANCE.convert(reqVO); - initMenuProperty(updateObject); - menuMapper.updateById(updateObject); + MenuDO updateObj = BeanUtils.toBean(updateReqVO, MenuDO.class); + initMenuProperty(updateObj); + menuMapper.updateById(updateObj); } @Override @@ -133,9 +130,6 @@ public class MenuServiceImpl implements MenuService { @Override public List getMenuList(Collection ids) { - if (CollectionUtil.isEmpty(ids)) { - return Collections.emptyList(); - } return menuMapper.selectBatchIds(ids); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java index 81bfcfc1f..dba2831ca 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java @@ -138,8 +138,9 @@ public class PermissionServiceImpl implements PermissionService { // 获得角色拥有菜单编号 Set dbMenuIds = convertSet(roleMenuMapper.selectListByRoleId(roleId), RoleMenuDO::getMenuId); // 计算新增和删除的菜单编号 - Collection createMenuIds = CollUtil.subtract(menuIds, dbMenuIds); - Collection deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIds); + Set menuIdList = CollUtil.emptyIfNull(menuIds); + Collection createMenuIds = CollUtil.subtract(menuIdList, dbMenuIds); + Collection deleteMenuIds = CollUtil.subtract(dbMenuIds, menuIdList); // 执行新增和删除。对于已经授权的菜单,不用做任何处理 if (CollUtil.isNotEmpty(createMenuIds)) { roleMenuMapper.insertBatch(CollectionUtils.convertList(createMenuIds, menuId -> { @@ -205,8 +206,9 @@ public class PermissionServiceImpl implements PermissionService { Set dbRoleIds = convertSet(userRoleMapper.selectListByUserId(userId), UserRoleDO::getRoleId); // 计算新增和删除的角色编号 - Collection createRoleIds = CollUtil.subtract(roleIds, dbRoleIds); - Collection deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIds); + Set roleIdList = CollUtil.emptyIfNull(roleIds); + Collection createRoleIds = CollUtil.subtract(roleIdList, dbRoleIds); + Collection deleteMenuIds = CollUtil.subtract(dbRoleIds, roleIdList); // 执行新增和删除。对于已经授权的角色,不用做任何处理 if (!CollectionUtil.isEmpty(createRoleIds)) { userRoleMapper.insertBatch(CollectionUtils.convertList(createRoleIds, roleId -> { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java index d837d1e8b..a97eb796d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.system.service.permission; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import javax.validation.Valid; @@ -22,18 +20,18 @@ public interface RoleService { /** * 创建角色 * - * @param reqVO 创建角色信息 + * @param createReqVO 创建角色信息 * @param type 角色类型 * @return 角色编号 */ - Long createRole(@Valid RoleCreateReqVO reqVO, Integer type); + Long createRole(@Valid RoleSaveReqVO createReqVO, Integer type); /** * 更新角色 * - * @param reqVO 更新角色信息 + * @param updateReqVO 更新角色信息 */ - void updateRole(@Valid RoleUpdateReqVO reqVO); + void updateRole(@Valid RoleSaveReqVO updateReqVO); /** * 删除角色 @@ -114,14 +112,6 @@ public interface RoleService { */ PageResult getRolePage(RolePageReqVO reqVO); - /** - * 获得角色列表 - * - * @param reqVO 列表查询 - * @return 角色列表 - */ - List getRoleList(RoleExportReqVO reqVO); - /** * 判断角色编号数组中,是否有管理员 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java index c8ae9f343..aa170d36e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java @@ -6,11 +6,9 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.permission.RoleConvert; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; @@ -50,11 +48,11 @@ public class RoleServiceImpl implements RoleService { @Override @Transactional(rollbackFor = Exception.class) - public Long createRole(RoleCreateReqVO reqVO, Integer type) { + public Long createRole(RoleSaveReqVO createReqVO, Integer type) { // 校验角色 - validateRoleDuplicate(reqVO.getName(), reqVO.getCode(), null); + validateRoleDuplicate(createReqVO.getName(), createReqVO.getCode(), null); // 插入到数据库 - RoleDO role = RoleConvert.INSTANCE.convert(reqVO); + RoleDO role = BeanUtils.toBean(createReqVO, RoleDO.class); role.setType(ObjectUtil.defaultIfNull(type, RoleTypeEnum.CUSTOM.getType())); role.setStatus(CommonStatusEnum.ENABLE.getStatus()); role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 @@ -64,15 +62,15 @@ public class RoleServiceImpl implements RoleService { } @Override - @CacheEvict(value = RedisKeyConstants.ROLE, key = "#reqVO.id") - public void updateRole(RoleUpdateReqVO reqVO) { + @CacheEvict(value = RedisKeyConstants.ROLE, key = "#updateReqVO.id") + public void updateRole(RoleSaveReqVO updateReqVO) { // 校验是否可以更新 - validateRoleForUpdate(reqVO.getId()); + validateRoleForUpdate(updateReqVO.getId()); // 校验角色的唯一字段是否重复 - validateRoleDuplicate(reqVO.getName(), reqVO.getCode(), reqVO.getId()); + validateRoleDuplicate(updateReqVO.getName(), updateReqVO.getCode(), updateReqVO.getId()); // 更新到数据库 - RoleDO updateObj = RoleConvert.INSTANCE.convert(reqVO); + RoleDO updateObj = BeanUtils.toBean(updateReqVO, RoleDO.class); roleMapper.updateById(updateObj); } @@ -208,11 +206,6 @@ public class RoleServiceImpl implements RoleService { return roleMapper.selectPage(reqVO); } - @Override - public List getRoleList(RoleExportReqVO reqVO) { - return roleMapper.selectList(reqVO); - } - @Override public boolean hasAnySuperAdmin(Collection ids) { if (CollectionUtil.isEmpty(ids)) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordService.java index e84e81f6d..4f0363274 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordService.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.system.service.sensitiveword; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; import javax.validation.Valid; @@ -24,14 +22,14 @@ public interface SensitiveWordService { * @param createReqVO 创建信息 * @return 编号 */ - Long createSensitiveWord(@Valid SensitiveWordCreateReqVO createReqVO); + Long createSensitiveWord(@Valid SensitiveWordSaveVO createReqVO); /** * 更新敏感词 * * @param updateReqVO 更新信息 */ - void updateSensitiveWord(@Valid SensitiveWordUpdateReqVO updateReqVO); + void updateSensitiveWord(@Valid SensitiveWordSaveVO updateReqVO); /** * 删除敏感词 @@ -63,14 +61,6 @@ public interface SensitiveWordService { */ PageResult getSensitiveWordPage(SensitiveWordPageReqVO pageReqVO); - /** - * 获得敏感词列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 敏感词列表 - */ - List getSensitiveWordList(SensitiveWordExportReqVO exportReqVO); - /** * 获得所有敏感词的标签数组 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java index 991708c36..08ee30958 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImpl.java @@ -4,11 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordExportReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.sensitiveword.SensitiveWordConvert; +import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; import cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper; import cn.iocoder.yudao.module.system.util.collection.SimpleTrie; @@ -141,12 +139,12 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { } @Override - public Long createSensitiveWord(SensitiveWordCreateReqVO createReqVO) { + public Long createSensitiveWord(SensitiveWordSaveVO createReqVO) { // 校验唯一性 validateSensitiveWordNameUnique(null, createReqVO.getName()); // 插入 - SensitiveWordDO sensitiveWord = SensitiveWordConvert.INSTANCE.convert(createReqVO); + SensitiveWordDO sensitiveWord = BeanUtils.toBean(createReqVO, SensitiveWordDO.class); sensitiveWordMapper.insert(sensitiveWord); // 刷新缓存 @@ -155,13 +153,13 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { } @Override - public void updateSensitiveWord(SensitiveWordUpdateReqVO updateReqVO) { + public void updateSensitiveWord(SensitiveWordSaveVO updateReqVO) { // 校验唯一性 validateSensitiveWordExists(updateReqVO.getId()); validateSensitiveWordNameUnique(updateReqVO.getId(), updateReqVO.getName()); // 更新 - SensitiveWordDO updateObj = SensitiveWordConvert.INSTANCE.convert(updateReqVO); + SensitiveWordDO updateObj = BeanUtils.toBean(updateReqVO, SensitiveWordDO.class); sensitiveWordMapper.updateById(updateObj); // 刷新缓存 @@ -214,11 +212,6 @@ public class SensitiveWordServiceImpl implements SensitiveWordService { return sensitiveWordMapper.selectPage(pageReqVO); } - @Override - public List getSensitiveWordList(SensitiveWordExportReqVO exportReqVO) { - return sensitiveWordMapper.selectList(exportReqVO); - } - @Override public Set getSensitiveWordTagSet() { return sensitiveWordTagsCache; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java index 34540d6ed..c820630da 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import javax.validation.Valid; @@ -24,14 +23,14 @@ public interface SmsChannelService { * @param createReqVO 创建信息 * @return 编号 */ - Long createSmsChannel(@Valid SmsChannelCreateReqVO createReqVO); + Long createSmsChannel(@Valid SmsChannelSaveReqVO createReqVO); /** * 更新短信渠道 * * @param updateReqVO 更新信息 */ - void updateSmsChannel(@Valid SmsChannelUpdateReqVO updateReqVO); + void updateSmsChannel(@Valid SmsChannelSaveReqVO updateReqVO); /** * 删除短信渠道 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java index 1c6670547..0187bbee9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java @@ -2,13 +2,12 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.sms.SmsChannelConvert; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; import com.google.common.cache.CacheLoader; @@ -47,7 +46,7 @@ public class SmsChannelServiceImpl implements SmsChannelService { // 查询,然后尝试刷新 SmsChannelDO channel = smsChannelMapper.selectById(id); if (channel != null) { - SmsChannelProperties properties = SmsChannelConvert.INSTANCE.convert02(channel); + SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); smsClientFactory.createOrUpdateSmsClient(properties); } return smsClientFactory.getSmsClient(id); @@ -67,7 +66,7 @@ public class SmsChannelServiceImpl implements SmsChannelService { // 查询,然后尝试刷新 SmsChannelDO channel = smsChannelMapper.selectByCode(code); if (channel != null) { - SmsChannelProperties properties = SmsChannelConvert.INSTANCE.convert02(channel); + SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); smsClientFactory.createOrUpdateSmsClient(properties); } return smsClientFactory.getSmsClient(code); @@ -85,18 +84,18 @@ public class SmsChannelServiceImpl implements SmsChannelService { private SmsTemplateService smsTemplateService; @Override - public Long createSmsChannel(SmsChannelCreateReqVO createReqVO) { - SmsChannelDO channel = SmsChannelConvert.INSTANCE.convert(createReqVO); + public Long createSmsChannel(SmsChannelSaveReqVO createReqVO) { + SmsChannelDO channel = BeanUtils.toBean(createReqVO, SmsChannelDO.class); smsChannelMapper.insert(channel); return channel.getId(); } @Override - public void updateSmsChannel(SmsChannelUpdateReqVO updateReqVO) { + public void updateSmsChannel(SmsChannelSaveReqVO updateReqVO) { // 校验存在 SmsChannelDO channel = validateSmsChannelExists(updateReqVO.getId()); // 更新 - SmsChannelDO updateObj = SmsChannelConvert.INSTANCE.convert(updateReqVO); + SmsChannelDO updateObj = BeanUtils.toBean(updateReqVO, SmsChannelDO.class); smsChannelMapper.updateById(updateObj); // 清空缓存 @@ -108,7 +107,7 @@ public class SmsChannelServiceImpl implements SmsChannelService { // 校验存在 SmsChannelDO channel = validateSmsChannelExists(id); // 校验是否有在使用该账号的模版 - if (smsTemplateService.countByChannelId(id) > 0) { + if (smsTemplateService.getSmsTemplateCountByChannelId(id) > 0) { throw exception(SMS_CHANNEL_HAS_CHILDREN); } // 删除 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java index e9c668ccd..0c86c0f07 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogService.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import java.time.LocalDateTime; -import java.util.List; import java.util.Map; /** @@ -37,15 +35,15 @@ public interface SmsLogService { * 更新日志的发送结果 * * @param id 日志编号 - * @param sendCode 发送结果的编码 - * @param sendMsg 发送结果的提示 + * @param success 发送是否成功 * @param apiSendCode 短信 API 发送结果的编码 * @param apiSendMsg 短信 API 发送失败的提示 * @param apiRequestId 短信 API 发送返回的唯一请求 ID * @param apiSerialNo 短信 API 发送返回的序号 */ - void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, - String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo); + void updateSmsSendResult(Long id, Boolean success, + String apiSendCode, String apiSendMsg, + String apiRequestId, String apiSerialNo); /** * 更新日志的接收结果 @@ -56,7 +54,8 @@ public interface SmsLogService { * @param apiReceiveCode API 接收结果的编码 * @param apiReceiveMsg API 接收结果的说明 */ - void updateSmsReceiveResult(Long id, Boolean success, LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg); + void updateSmsReceiveResult(Long id, Boolean success, + LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg); /** * 获得短信日志分页 @@ -66,12 +65,4 @@ public interface SmsLogService { */ PageResult getSmsLogPage(SmsLogPageReqVO pageReqVO); - /** - * 获得短信日志列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 短信日志列表 - */ - List getSmsLogList(SmsLogExportReqVO exportReqVO); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java index 40e7d1c0a..c79b94123 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImpl.java @@ -1,12 +1,10 @@ package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsLogMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum; import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; import lombok.extern.slf4j.Slf4j; @@ -14,7 +12,6 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.List; import java.util.Map; import java.util.Objects; @@ -55,13 +52,12 @@ public class SmsLogServiceImpl implements SmsLogService { } @Override - public void updateSmsSendResult(Long id, Integer sendCode, String sendMsg, + public void updateSmsSendResult(Long id, Boolean success, String apiSendCode, String apiSendMsg, String apiRequestId, String apiSerialNo) { - SmsSendStatusEnum sendStatus = CommonResult.isSuccess(sendCode) ? - SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; - smsLogMapper.updateById(SmsLogDO.builder().id(id).sendStatus(sendStatus.getStatus()) - .sendTime(LocalDateTime.now()).sendCode(sendCode).sendMsg(sendMsg) + SmsSendStatusEnum sendStatus = success ? SmsSendStatusEnum.SUCCESS : SmsSendStatusEnum.FAILURE; + smsLogMapper.updateById(SmsLogDO.builder().id(id) + .sendStatus(sendStatus.getStatus()).sendTime(LocalDateTime.now()) .apiSendCode(apiSendCode).apiSendMsg(apiSendMsg) .apiRequestId(apiRequestId).apiSerialNo(apiSerialNo).build()); } @@ -80,9 +76,4 @@ public class SmsLogServiceImpl implements SmsLogService { return smsLogMapper.selectPage(pageReqVO); } - @Override - public List getSmsLogList(SmsLogExportReqVO exportReqVO) { - return smsLogMapper.selectList(exportReqVO); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java index 4807f1ea6..4650bd4f8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; @@ -8,7 +9,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; @@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; import cn.iocoder.yudao.module.system.service.member.MemberService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.google.common.annotations.VisibleForTesting; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -35,6 +36,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; * @author 芋道源码 */ @Service +@Slf4j public class SmsSendServiceImpl implements SmsSendService { @Resource @@ -158,11 +160,17 @@ public class SmsSendServiceImpl implements SmsSendService { SmsClient smsClient = smsChannelService.getSmsClient(message.getChannelId()); Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); // 发送短信 - SmsCommonResult sendResult = smsClient.sendSms(message.getLogId(), message.getMobile(), - message.getApiTemplateId(), message.getTemplateParams()); - smsLogService.updateSmsSendResult(message.getLogId(), sendResult.getCode(), sendResult.getMsg(), - sendResult.getApiCode(), sendResult.getApiMsg(), sendResult.getApiRequestId(), - sendResult.getData() != null ? sendResult.getData().getSerialNo() : null); + try { + SmsSendRespDTO sendResponse = smsClient.sendSms(message.getLogId(), message.getMobile(), + message.getApiTemplateId(), message.getTemplateParams()); + smsLogService.updateSmsSendResult(message.getLogId(), sendResponse.getSuccess(), + sendResponse.getApiCode(), sendResponse.getApiMsg(), + sendResponse.getApiRequestId(), sendResponse.getSerialNo()); + } catch (Throwable ex) { + log.error("[doSendSms][发送短信异常,日志编号({})]", message.getLogId(), ex); + smsLogService.updateSmsSendResult(message.getLogId(), false, + "EXCEPTION", ExceptionUtil.getRootCauseMessage(ex), null, null); + } } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java index f3f886f55..9d6ac3a1e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateService.java @@ -1,14 +1,11 @@ package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import javax.validation.Valid; -import java.util.List; import java.util.Map; /** @@ -25,14 +22,14 @@ public interface SmsTemplateService { * @param createReqVO 创建信息 * @return 编号 */ - Long createSmsTemplate(@Valid SmsTemplateCreateReqVO createReqVO); + Long createSmsTemplate(@Valid SmsTemplateSaveReqVO createReqVO); /** * 更新短信模板 * * @param updateReqVO 更新信息 */ - void updateSmsTemplate(@Valid SmsTemplateUpdateReqVO updateReqVO); + void updateSmsTemplate(@Valid SmsTemplateSaveReqVO updateReqVO); /** * 删除短信模板 @@ -65,22 +62,13 @@ public interface SmsTemplateService { */ PageResult getSmsTemplatePage(SmsTemplatePageReqVO pageReqVO); - /** - * 获得短信模板列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 短信模板分页 - */ - List getSmsTemplateList(SmsTemplateExportReqVO exportReqVO); - /** * 获得指定短信渠道下的短信模板数量 * * @param channelId 短信渠道编号 * @return 数量 */ - Long countByChannelId(Long channelId); - + Long getSmsTemplateCountByChannelId(Long channelId); /** * 格式化短信内容 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java index ba3a7484b..219710f27 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java @@ -1,17 +1,17 @@ package cn.iocoder.yudao.module.system.service.sms; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; +import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.sms.SmsTemplateConvert; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; @@ -21,11 +21,11 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import org.springframework.util.Assert; import javax.annotation.Resource; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.regex.Pattern; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -53,7 +53,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { private SmsChannelService smsChannelService; @Override - public Long createSmsTemplate(SmsTemplateCreateReqVO createReqVO) { + public Long createSmsTemplate(SmsTemplateSaveReqVO createReqVO) { // 校验短信渠道 SmsChannelDO channelDO = validateSmsChannel(createReqVO.getChannelId()); // 校验短信编码是否重复 @@ -62,7 +62,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { validateApiTemplate(createReqVO.getChannelId(), createReqVO.getApiTemplateId()); // 插入 - SmsTemplateDO template = SmsTemplateConvert.INSTANCE.convert(createReqVO); + SmsTemplateDO template = BeanUtils.toBean(createReqVO, SmsTemplateDO.class); template.setParams(parseTemplateContentParams(template.getContent())); template.setChannelCode(channelDO.getCode()); smsTemplateMapper.insert(template); @@ -73,7 +73,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { @Override @CacheEvict(cacheNames = RedisKeyConstants.SMS_TEMPLATE, allEntries = true) // allEntries 清空所有缓存,因为可能修改到 code 字段,不好清理 - public void updateSmsTemplate(SmsTemplateUpdateReqVO updateReqVO) { + public void updateSmsTemplate(SmsTemplateSaveReqVO updateReqVO) { // 校验存在 validateSmsTemplateExists(updateReqVO.getId()); // 校验短信渠道 @@ -84,7 +84,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { validateApiTemplate(updateReqVO.getChannelId(), updateReqVO.getApiTemplateId()); // 更新 - SmsTemplateDO updateObj = SmsTemplateConvert.INSTANCE.convert(updateReqVO); + SmsTemplateDO updateObj = BeanUtils.toBean(updateReqVO, SmsTemplateDO.class); updateObj.setParams(parseTemplateContentParams(updateObj.getContent())); updateObj.setChannelCode(channelDO.getCode()); smsTemplateMapper.updateById(updateObj); @@ -124,12 +124,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { } @Override - public List getSmsTemplateList(SmsTemplateExportReqVO exportReqVO) { - return smsTemplateMapper.selectList(exportReqVO); - } - - @Override - public Long countByChannelId(Long channelId) { + public Long getSmsTemplateCountByChannelId(Long channelId) { return smsTemplateMapper.selectCountByChannelId(channelId); } @@ -171,9 +166,24 @@ public class SmsTemplateServiceImpl implements SmsTemplateService { // 获得短信模板 SmsClient smsClient = smsChannelService.getSmsClient(channelId); Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId)); - SmsCommonResult templateResult = smsClient.getSmsTemplate(apiTemplateId); - // 校验短信模板是否正确 - templateResult.checkError(); + SmsTemplateRespDTO template; + try { + template = smsClient.getSmsTemplate(apiTemplateId); + } catch (Throwable ex) { + throw exception(SMS_TEMPLATE_API_ERROR, ExceptionUtil.getRootCauseMessage(ex)); + } + // 校验短信模版 + if (template == null) { + throw exception(SMS_TEMPLATE_API_NOT_FOUND); + } + if (Objects.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.CHECKING.getStatus())) { + throw exception(SMS_TEMPLATE_API_AUDIT_CHECKING); + } + if (Objects.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.FAIL.getStatus())) { + throw exception(SMS_TEMPLATE_API_AUDIT_FAIL, template.getAuditReason()); + } + Assert.equals(template.getAuditStatus(), SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), + String.format("短信模板(%s) 审核状态(%d) 不正确", apiTemplateId, template.getAuditStatus())); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java index 35e9d5962..dba86c699 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.system.service.social; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import com.xingyuv.jushauth.model.AuthUser; @@ -70,14 +69,14 @@ public interface SocialClientService { * @param createReqVO 创建信息 * @return 编号 */ - Long createSocialClient(@Valid SocialClientCreateReqVO createReqVO); + Long createSocialClient(@Valid SocialClientSaveReqVO createReqVO); /** * 更新社交客户端 * * @param updateReqVO 更新信息 */ - void updateSocialClient(@Valid SocialClientUpdateReqVO updateReqVO); + void updateSocialClient(@Valid SocialClientSaveReqVO updateReqVO); /** * 删除社交客户端 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 6c8381663..e13f08529 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -12,11 +12,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.cache.CacheUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; -import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.social.SocialClientConvert; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; @@ -31,6 +29,7 @@ import com.xingyuv.jushauth.model.AuthResponse; import com.xingyuv.jushauth.model.AuthUser; import com.xingyuv.jushauth.request.AuthRequest; import com.xingyuv.jushauth.utils.AuthStateUtils; +import com.xingyuv.justauth.AuthRequestFactory; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.bean.WxJsapiSignature; @@ -59,8 +58,8 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; @Slf4j public class SocialClientServiceImpl implements SocialClientService { - @Resource // 由于自定义了 YudaoAuthRequestFactory 无法覆盖默认的 AuthRequestFactory,所以只能注入它 - private YudaoAuthRequestFactory yudaoAuthRequestFactory; + @Resource + private AuthRequestFactory authRequestFactory; @Resource private WxMpService wxMpService; @@ -145,7 +144,7 @@ public class SocialClientServiceImpl implements SocialClientService { */ private AuthRequest buildAuthRequest(Integer socialType, Integer userType) { // 1. 先查找默认的配置项,从 application-*.yaml 中读取 - AuthRequest request = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource()); + AuthRequest request = authRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource()); Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType)); // 2. 查询 DB 的配置项,如果存在则进行覆盖 SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(socialType, userType); @@ -267,26 +266,25 @@ public class SocialClientServiceImpl implements SocialClientService { // =================== 客户端管理 =================== @Override - public Long createSocialClient(SocialClientCreateReqVO createReqVO) { + public Long createSocialClient(SocialClientSaveReqVO createReqVO) { // 校验重复 validateSocialClientUnique(null, createReqVO.getUserType(), createReqVO.getSocialType()); // 插入 - SocialClientDO socialClient = SocialClientConvert.INSTANCE.convert(createReqVO); - socialClientMapper.insert(socialClient); - // 返回 - return socialClient.getId(); + SocialClientDO client = BeanUtils.toBean(createReqVO, SocialClientDO.class); + socialClientMapper.insert(client); + return client.getId(); } @Override - public void updateSocialClient(SocialClientUpdateReqVO updateReqVO) { + public void updateSocialClient(SocialClientSaveReqVO updateReqVO) { // 校验存在 validateSocialClientExists(updateReqVO.getId()); // 校验重复 validateSocialClientUnique(updateReqVO.getId(), updateReqVO.getUserType(), updateReqVO.getSocialType()); // 更新 - SocialClientDO updateObj = SocialClientConvert.INSTANCE.convert(updateReqVO); + SocialClientDO updateObj = BeanUtils.toBean(updateReqVO, SocialClientDO.class); socialClientMapper.updateById(updateObj); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java index c58426a2b..1abe4feeb 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java @@ -1,9 +1,8 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; import javax.validation.Valid; @@ -22,14 +21,14 @@ public interface TenantPackageService { * @param createReqVO 创建信息 * @return 编号 */ - Long createTenantPackage(@Valid TenantPackageCreateReqVO createReqVO); + Long createTenantPackage(@Valid TenantPackageSaveReqVO createReqVO); /** * 更新租户套餐 * * @param updateReqVO 更新信息 */ - void updateTenantPackage(@Valid TenantPackageUpdateReqVO updateReqVO); + void updateTenantPackage(@Valid TenantPackageSaveReqVO updateReqVO); /** * 删除租户套餐 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java index 8a65ab1f0..3fd76a154 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.tenant.TenantPackageConvert; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper; @@ -38,9 +37,9 @@ public class TenantPackageServiceImpl implements TenantPackageService { private TenantService tenantService; @Override - public Long createTenantPackage(TenantPackageCreateReqVO createReqVO) { + public Long createTenantPackage(TenantPackageSaveReqVO createReqVO) { // 插入 - TenantPackageDO tenantPackage = TenantPackageConvert.INSTANCE.convert(createReqVO); + TenantPackageDO tenantPackage = BeanUtils.toBean(createReqVO, TenantPackageDO.class); tenantPackageMapper.insert(tenantPackage); // 返回 return tenantPackage.getId(); @@ -48,11 +47,11 @@ public class TenantPackageServiceImpl implements TenantPackageService { @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 - public void updateTenantPackage(TenantPackageUpdateReqVO updateReqVO) { + public void updateTenantPackage(TenantPackageSaveReqVO updateReqVO) { // 校验存在 TenantPackageDO tenantPackage = validateTenantPackageExists(updateReqVO.getId()); // 更新 - TenantPackageDO updateObj = TenantPackageConvert.INSTANCE.convert(updateReqVO); + TenantPackageDO updateObj = BeanUtils.toBean(updateReqVO, TenantPackageDO.class); tenantPackageMapper.updateById(updateObj); // 如果菜单发生变化,则修改每个租户的菜单 if (!CollUtil.isEqualList(tenantPackage.getMenuIds(), updateReqVO.getMenuIds())) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java index 3dacfefe7..c7e879b8e 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java @@ -2,10 +2,8 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler; import cn.iocoder.yudao.module.system.service.tenant.handler.TenantMenuHandler; @@ -27,14 +25,14 @@ public interface TenantService { * @param createReqVO 创建信息 * @return 编号 */ - Long createTenant(@Valid TenantCreateReqVO createReqVO); + Long createTenant(@Valid TenantSaveReqVO createReqVO); /** * 更新租户 * * @param updateReqVO 更新信息 */ - void updateTenant(@Valid TenantUpdateReqVO updateReqVO); + void updateTenant(@Valid TenantSaveReqVO updateReqVO); /** * 更新租户的角色菜单 @@ -67,22 +65,22 @@ public interface TenantService { */ PageResult getTenantPage(TenantPageReqVO pageReqVO); - /** - * 获得租户列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 租户列表 - */ - List getTenantList(TenantExportReqVO exportReqVO); - /** * 获得名字对应的租户 * - * @param name 组户名 + * @param name 租户名 * @return 租户 */ TenantDO getTenantByName(String name); + /** + * 获得域名对应的租户 + * + * @param website 域名 + * @return 租户 + */ + TenantDO getTenantByWebsite(String website); + /** * 获得使用指定套餐的租户数量 * @@ -128,4 +126,5 @@ public interface TenantService { * @param id 租户编号 */ void validTenant(Long id); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java index fd49bf970..b4bdf1036 100755 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java @@ -3,18 +3,18 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.tenant.config.TenantProperties; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; @@ -96,16 +96,18 @@ public class TenantServiceImpl implements TenantService { @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 - public Long createTenant(TenantCreateReqVO createReqVO) { + public Long createTenant(TenantSaveReqVO createReqVO) { // 校验租户名称是否重复 validTenantNameDuplicate(createReqVO.getName(), null); + // 校验租户域名是否重复 + validTenantWebsiteDuplicate(createReqVO.getWebsite(), null); // 校验套餐被禁用 TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId()); // 创建租户 - TenantDO tenant = TenantConvert.INSTANCE.convert(createReqVO); + TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class); tenantMapper.insert(tenant); - + // 创建租户的管理员 TenantUtils.execute(tenant.getId(), () -> { // 创建角色 Long roleId = createRole(tenantPackage); @@ -117,7 +119,7 @@ public class TenantServiceImpl implements TenantService { return tenant.getId(); } - private Long createUser(Long roleId, TenantCreateReqVO createReqVO) { + private Long createUser(Long roleId, TenantSaveReqVO createReqVO) { // 创建用户 Long userId = userService.createUser(TenantConvert.INSTANCE.convert02(createReqVO)); // 分配角色 @@ -127,7 +129,7 @@ public class TenantServiceImpl implements TenantService { private Long createRole(TenantPackageDO tenantPackage) { // 创建角色 - RoleCreateReqVO reqVO = new RoleCreateReqVO(); + RoleSaveReqVO reqVO = new RoleSaveReqVO(); reqVO.setName(RoleCodeEnum.TENANT_ADMIN.getName()).setCode(RoleCodeEnum.TENANT_ADMIN.getCode()) .setSort(0).setRemark("系统自动生成"); Long roleId = roleService.createRole(reqVO, RoleTypeEnum.SYSTEM.getType()); @@ -137,17 +139,19 @@ public class TenantServiceImpl implements TenantService { } @Override - @DSTransactional - public void updateTenant(TenantUpdateReqVO updateReqVO) { + @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 + public void updateTenant(TenantSaveReqVO updateReqVO) { // 校验存在 TenantDO tenant = validateUpdateTenant(updateReqVO.getId()); // 校验租户名称是否重复 validTenantNameDuplicate(updateReqVO.getName(), updateReqVO.getId()); + // 校验租户域名是否重复 + validTenantWebsiteDuplicate(updateReqVO.getWebsite(), updateReqVO.getId()); // 校验套餐被禁用 TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId()); // 更新租户 - TenantDO updateObj = TenantConvert.INSTANCE.convert(updateReqVO); + TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class); tenantMapper.updateById(updateObj); // 如果套餐发生变化,则修改其角色的权限 if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) { @@ -169,6 +173,23 @@ public class TenantServiceImpl implements TenantService { } } + private void validTenantWebsiteDuplicate(String website, Long id) { + if (StrUtil.isEmpty(website)) { + return; + } + TenantDO tenant = tenantMapper.selectByWebsite(website); + if (tenant == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同名字的租户 + if (id == null) { + throw exception(TENANT_WEBSITE_DUPLICATE, website); + } + if (!tenant.getId().equals(id)) { + throw exception(TENANT_WEBSITE_DUPLICATE, website); + } + } + @Override @DSTransactional public void updateTenantRoleMenu(Long tenantId, Set menuIds) { @@ -225,13 +246,13 @@ public class TenantServiceImpl implements TenantService { } @Override - public List getTenantList(TenantExportReqVO exportReqVO) { - return tenantMapper.selectList(exportReqVO); + public TenantDO getTenantByName(String name) { + return tenantMapper.selectByName(name); } @Override - public TenantDO getTenantByName(String name) { - return tenantMapper.selectByName(name); + public TenantDO getTenantByWebsite(String website) { + return tenantMapper.selectByWebsite(website); } @Override diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java index e10b9e997..ed9fbdf83 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java @@ -1,16 +1,22 @@ package cn.iocoder.yudao.module.system.service.user; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; -import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import javax.validation.Valid; import java.io.InputStream; -import java.util.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * 后台用户 Service 接口 @@ -22,17 +28,17 @@ public interface AdminUserService { /** * 创建用户 * - * @param reqVO 用户信息 + * @param createReqVO 用户信息 * @return 用户编号 */ - Long createUser(@Valid UserCreateReqVO reqVO); + Long createUser(@Valid UserSaveReqVO createReqVO); /** * 修改用户 * - * @param reqVO 用户信息 + * @param updateReqVO 用户信息 */ - void updateUser(@Valid UserUpdateReqVO reqVO); + void updateUser(@Valid UserSaveReqVO updateReqVO); /** * 更新用户的最后登陆信息 @@ -167,14 +173,6 @@ public interface AdminUserService { return CollectionUtils.convertMap(getUserList(ids), AdminUserDO::getId); } - /** - * 获得用户列表 - * - * @param reqVO 列表请求 - * @return 用户列表 - */ - List getUserList(UserExportReqVO reqVO); - /** * 获得用户列表,基于昵称模糊匹配 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java index dbfc02ed3..5f438708c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java @@ -8,12 +8,15 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; -import cn.iocoder.yudao.module.system.convert.user.UserConvert; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -76,7 +79,7 @@ public class AdminUserServiceImpl implements AdminUserService { @Override @Transactional(rollbackFor = Exception.class) - public Long createUser(UserCreateReqVO reqVO) { + public Long createUser(UserSaveReqVO createReqVO) { // 校验账户配合 tenantService.handleTenantInfo(tenant -> { long count = userMapper.selectCount(); @@ -85,12 +88,12 @@ public class AdminUserServiceImpl implements AdminUserService { } }); // 校验正确性 - validateUserForCreateOrUpdate(null, reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), - reqVO.getDeptId(), reqVO.getPostIds()); + validateUserForCreateOrUpdate(null, createReqVO.getUsername(), + createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds()); // 插入用户 - AdminUserDO user = UserConvert.INSTANCE.convert(reqVO); + AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 - user.setPassword(encodePassword(reqVO.getPassword())); // 加密密码 + user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码 userMapper.insert(user); // 插入关联岗位 if (CollectionUtil.isNotEmpty(user.getPostIds())) { @@ -102,22 +105,23 @@ public class AdminUserServiceImpl implements AdminUserService { @Override @Transactional(rollbackFor = Exception.class) - public void updateUser(UserUpdateReqVO reqVO) { + public void updateUser(UserSaveReqVO updateReqVO) { + updateReqVO.setPassword(null); // 特殊:此处不更新密码 // 校验正确性 - validateUserForCreateOrUpdate(reqVO.getId(), reqVO.getUsername(), reqVO.getMobile(), reqVO.getEmail(), - reqVO.getDeptId(), reqVO.getPostIds()); + validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(), + updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds()); // 更新用户 - AdminUserDO updateObj = UserConvert.INSTANCE.convert(reqVO); + AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class); userMapper.updateById(updateObj); // 更新岗位 - updateUserPost(reqVO, updateObj); + updateUserPost(updateReqVO, updateObj); } - private void updateUserPost(UserUpdateReqVO reqVO, AdminUserDO updateObj) { + private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) { Long userId = reqVO.getId(); Set dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId); // 计算新增和删除的岗位编号 - Set postIds = updateObj.getPostIds(); + Set postIds = CollUtil.emptyIfNull(updateObj.getPostIds()); Collection createPostIds = CollUtil.subtract(postIds, dbPostIds); Collection deletePostIds = CollUtil.subtract(dbPostIds, postIds); // 执行新增和删除。对于已经授权的菜单,不用做任何处理 @@ -142,7 +146,7 @@ public class AdminUserServiceImpl implements AdminUserService { validateEmailUnique(id, reqVO.getEmail()); validateMobileUnique(id, reqVO.getMobile()); // 执行更新 - userMapper.updateById(UserConvert.INSTANCE.convert(reqVO).setId(id)); + userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id)); } @Override @@ -156,7 +160,7 @@ public class AdminUserServiceImpl implements AdminUserService { } @Override - public String updateUserAvatar(Long id, InputStream avatarFile) throws Exception { + public String updateUserAvatar(Long id, InputStream avatarFile) { validateUserExists(id); // 存储文件 String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile)); @@ -271,11 +275,6 @@ public class AdminUserServiceImpl implements AdminUserService { }); } - @Override - public List getUserList(UserExportReqVO reqVO) { - return userMapper.selectList(reqVO, getDeptCondition(reqVO.getDeptId())); - } - @Override public List getUserListByNickname(String nickname) { return userMapper.selectListByNickname(nickname); @@ -415,7 +414,7 @@ public class AdminUserServiceImpl implements AdminUserService { // 判断如果不存在,在进行插入 AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); if (existUser == null) { - userMapper.insert(UserConvert.INSTANCE.convert(importUser) + userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class) .setPassword(encodePassword(userInitPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组 respVO.getCreateUsernames().add(importUser.getUsername()); return; @@ -425,7 +424,7 @@ public class AdminUserServiceImpl implements AdminUserService { respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg()); return; } - AdminUserDO updateUser = UserConvert.INSTANCE.convert(importUser); + AdminUserDO updateUser = BeanUtils.toBean(importUser, AdminUserDO.class); updateUser.setId(existUser.getId()); userMapper.updateById(updateUser); respVO.getUpdateUsernames().add(importUser.getUsername()); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml index b075dad29..9a8da02a9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application.yaml @@ -56,7 +56,7 @@ mybatis-plus: logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 - type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-aliases-package: ${yudao.info.base-package}.dal.dataobject encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 @@ -72,8 +72,6 @@ spring: --- #################### RPC 远程调用相关配置 #################### ---- #################### MQ 消息队列相关配置 #################### - --- #################### 消息队列相关 #################### # rocketmq 配置项,对应 RocketMQProperties 配置类 @@ -151,6 +149,7 @@ yudao: enable: true ignore-urls: - /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号 + - /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号 - /admin-api/system/captcha/get-image # 获取图片验证码,和租户无关 - /admin-api/system/captcha/get # 获取图片验证码,和租户无关 - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java index cf9dc5a35..abfa225da 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/DeptServiceImplTest.java @@ -3,12 +3,10 @@ package cn.iocoder.yudao.module.system.service.dept; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper; -import cn.iocoder.yudao.module.system.enums.dept.DeptIdEnum; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -40,8 +38,9 @@ public class DeptServiceImplTest extends BaseDbUnitTest { @Test public void testCreateDept() { // 准备参数 - DeptCreateReqVO reqVO = randomPojo(DeptCreateReqVO.class, o -> { - o.setParentId(DeptIdEnum.ROOT.getId()); + DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> { + o.setId(null); // 防止 id 被设置 + o.setParentId(DeptDO.PARENT_ID_ROOT); o.setStatus(randomCommonStatus()); }); @@ -51,7 +50,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { assertNotNull(deptId); // 校验记录的属性是否正确 DeptDO deptDO = deptMapper.selectById(deptId); - assertPojoEquals(reqVO, deptDO); + assertPojoEquals(reqVO, deptDO, "id"); } @Test @@ -60,9 +59,9 @@ public class DeptServiceImplTest extends BaseDbUnitTest { DeptDO dbDeptDO = randomPojo(DeptDO.class, o -> o.setStatus(randomCommonStatus())); deptMapper.insert(dbDeptDO);// @Sql: 先插入出一条存在的数据 // 准备参数 - DeptUpdateReqVO reqVO = randomPojo(DeptUpdateReqVO.class, o -> { + DeptSaveReqVO reqVO = randomPojo(DeptSaveReqVO.class, o -> { // 设置更新的 ID - o.setParentId(DeptIdEnum.ROOT.getId()); + o.setParentId(DeptDO.PARENT_ID_ROOT); o.setId(dbDeptDO.getId()); o.setStatus(randomCommonStatus()); }); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImplTest.java index 87c44b346..a6412277c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dept/PostServiceImplTest.java @@ -4,10 +4,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dept.vo.post.PostSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.dal.mysql.dept.PostMapper; import org.junit.jupiter.api.Test; @@ -44,8 +42,9 @@ public class PostServiceImplTest extends BaseDbUnitTest { @Test public void testCreatePost_success() { // 准备参数 - PostCreateReqVO reqVO = randomPojo(PostCreateReqVO.class, - o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus())); + PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, + o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus())) + .setId(null); // 防止 id 被设置 // 调用 Long postId = postService.createPost(reqVO); @@ -53,7 +52,7 @@ public class PostServiceImplTest extends BaseDbUnitTest { assertNotNull(postId); // 校验记录的属性是否正确 PostDO post = postMapper.selectById(postId); - assertPojoEquals(reqVO, post); + assertPojoEquals(reqVO, post, "id"); } @Test @@ -62,7 +61,7 @@ public class PostServiceImplTest extends BaseDbUnitTest { PostDO postDO = randomPostDO(); postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据 // 准备参数 - PostUpdateReqVO reqVO = randomPojo(PostUpdateReqVO.class, o -> { + PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, o -> { // 设置更新的 ID o.setId(postDO.getId()); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); @@ -103,7 +102,7 @@ public class PostServiceImplTest extends BaseDbUnitTest { PostDO postDO = randomPostDO(); postMapper.insert(postDO);// @Sql: 先插入出一条存在的数据 // 准备参数 - PostCreateReqVO reqVO = randomPojo(PostCreateReqVO.class, + PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, // 模拟 name 重复 o -> o.setName(postDO.getName())); assertServiceException(() -> postService.createPost(reqVO), POST_NAME_DUPLICATE); @@ -118,7 +117,7 @@ public class PostServiceImplTest extends BaseDbUnitTest { PostDO codePostDO = randomPostDO(); postMapper.insert(codePostDO); // 准备参数 - PostUpdateReqVO reqVO = randomPojo(PostUpdateReqVO.class, o -> { + PostSaveReqVO reqVO = randomPojo(PostSaveReqVO.class, o -> { // 设置更新的 ID o.setId(postDO.getId()); // 模拟 code 重复 @@ -155,31 +154,25 @@ public class PostServiceImplTest extends BaseDbUnitTest { } @Test - public void testGetPostList_export() { + public void testGetPostList() { // mock 数据 - PostDO postDO = randomPojo(PostDO.class, o -> { - o.setName("码仔"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - }); - postMapper.insert(postDO); - // 测试 name 不匹配 - postMapper.insert(cloneIgnoreId(postDO, o -> o.setName("程序员"))); - // 测试 status 不匹配 - postMapper.insert(cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + PostDO postDO01 = randomPojo(PostDO.class); + postMapper.insert(postDO01); + // 测试 id 不匹配 + PostDO postDO02 = randomPojo(PostDO.class); + postMapper.insert(postDO02); // 准备参数 - PostExportReqVO reqVO = new PostExportReqVO(); - reqVO.setName("码"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + List ids = singletonList(postDO01.getId()); // 调用 - List list = postService.getPostList(reqVO); + List list = postService.getPostList(ids); // 断言 assertEquals(1, list.size()); - assertPojoEquals(postDO, list.get(0)); + assertPojoEquals(postDO01, list.get(0)); } @Test - public void testGetPostList() { + public void testGetPostList_idsAndStatus() { // mock 数据 PostDO postDO01 = randomPojo(PostDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); postMapper.insert(postDO01); @@ -251,4 +244,5 @@ public class PostServiceImplTest extends BaseDbUnitTest { }; return randomPojo(PostDO.class, ArrayUtils.append(consumer, consumers)); } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImplTest.java index bb962b0dd..68edd735f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImplTest.java @@ -4,10 +4,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import cn.iocoder.yudao.module.system.dal.mysql.dict.DictDataMapper; @@ -52,10 +50,15 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { DictDataDO dictDataDO03 = randomDictDataDO().setDictType("yunai").setSort(3) .setStatus(CommonStatusEnum.DISABLE.getStatus()); dictDataMapper.insert(dictDataDO03); + DictDataDO dictDataDO04 = randomDictDataDO().setDictType("yunai2").setSort(3) + .setStatus(CommonStatusEnum.DISABLE.getStatus()); + dictDataMapper.insert(dictDataDO04); // 准备参数 + Integer status = CommonStatusEnum.ENABLE.getStatus(); + String dictType = "yunai"; // 调用 - List dictDataDOList = dictDataService.getDictDataList(); + List dictDataDOList = dictDataService.getDictDataList(status, dictType); // 断言 assertEquals(2, dictDataDOList.size()); assertPojoEquals(dictDataDO02, dictDataDOList.get(0)); @@ -91,34 +94,6 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbDictData, pageResult.getList().get(0)); } - @Test - public void testGetDictDataList_export() { - // mock 数据 - DictDataDO dbDictData = randomPojo(DictDataDO.class, o -> { // 等会查询到 - o.setLabel("芋艿"); - o.setDictType("yunai"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - }); - dictDataMapper.insert(dbDictData); - // 测试 label 不匹配 - dictDataMapper.insert(cloneIgnoreId(dbDictData, o -> o.setLabel("艿"))); - // 测试 dictType 不匹配 - dictDataMapper.insert(cloneIgnoreId(dbDictData, o -> o.setDictType("nai"))); - // 测试 status 不匹配 - dictDataMapper.insert(cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 准备参数 - DictDataExportReqVO reqVO = new DictDataExportReqVO(); - reqVO.setLabel("芋"); - reqVO.setDictType("yunai"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - - // 调用 - List list = dictDataService.getDictDataList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbDictData, list.get(0)); - } - @Test public void testGetDictData() { // mock 数据 @@ -136,8 +111,9 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { @Test public void testCreateDictData_success() { // 准备参数 - DictDataCreateReqVO reqVO = randomPojo(DictDataCreateReqVO.class, - o -> o.setStatus(randomCommonStatus())); + DictDataSaveReqVO reqVO = randomPojo(DictDataSaveReqVO.class, + o -> o.setStatus(randomCommonStatus())) + .setId(null); // 防止 id 被赋值 // mock 方法 when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType())); @@ -147,7 +123,7 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { assertNotNull(dictDataId); // 校验记录的属性是否正确 DictDataDO dictData = dictDataMapper.selectById(dictDataId); - assertPojoEquals(reqVO, dictData); + assertPojoEquals(reqVO, dictData, "id"); } @Test @@ -156,7 +132,7 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { DictDataDO dbDictData = randomDictDataDO(); dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据 // 准备参数 - DictDataUpdateReqVO reqVO = randomPojo(DictDataUpdateReqVO.class, o -> { + DictDataSaveReqVO reqVO = randomPojo(DictDataSaveReqVO.class, o -> { o.setId(dbDictData.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); }); @@ -265,7 +241,7 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { } @Test - public void testCountByDictType() { + public void testGetDictDataCountByDictType() { // mock 数据 dictDataMapper.insert(randomDictDataDO(o -> o.setDictType("yunai"))); dictDataMapper.insert(randomDictDataDO(o -> o.setDictType("tudou"))); @@ -274,7 +250,7 @@ public class DictDataServiceImplTest extends BaseDbUnitTest { String dictType = "yunai"; // 调用 - long count = dictDataService.countByDictType(dictType); + long count = dictDataService.getDictDataCountByDictType(dictType); // 校验 assertEquals(2L, count); } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImplTest.java index fc9387019..82b4b2f2e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/dict/DictTypeServiceImplTest.java @@ -4,10 +4,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.dict.vo.type.DictTypeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO; import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper; import org.junit.jupiter.api.Test; @@ -74,38 +72,6 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbDictType, pageResult.getList().get(0)); } - @Test - public void testGetDictTypeList_export() { - // mock 数据 - DictTypeDO dbDictType = randomPojo(DictTypeDO.class, o -> { // 等会查询到 - o.setName("yunai"); - o.setType("芋艿"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2021, 1, 15)); - }); - dictTypeMapper.insert(dbDictType); - // 测试 name 不匹配 - dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setName("tudou"))); - // 测试 type 不匹配 - dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setType("土豆"))); - // 测试 status 不匹配 - dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 createTime 不匹配 - dictTypeMapper.insert(cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1)))); - // 准备参数 - DictTypeExportReqVO reqVO = new DictTypeExportReqVO(); - reqVO.setName("nai"); - reqVO.setType("艿"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2021, 1, 10, 2021, 1, 20)); - - // 调用 - List list = dictTypeService.getDictTypeList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbDictType, list.get(0)); - } - @Test public void testGetDictType_id() { // mock 数据 @@ -139,8 +105,9 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { @Test public void testCreateDictType_success() { // 准备参数 - DictTypeCreateReqVO reqVO = randomPojo(DictTypeCreateReqVO.class, - o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus())); + DictTypeSaveReqVO reqVO = randomPojo(DictTypeSaveReqVO.class, + o -> o.setStatus(randomEle(CommonStatusEnum.values()).getStatus())) + .setId(null); // 避免 id 被赋值 // 调用 Long dictTypeId = dictTypeService.createDictType(reqVO); @@ -148,7 +115,7 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { assertNotNull(dictTypeId); // 校验记录的属性是否正确 DictTypeDO dictType = dictTypeMapper.selectById(dictTypeId); - assertPojoEquals(reqVO, dictType); + assertPojoEquals(reqVO, dictType, "id"); } @Test @@ -157,7 +124,7 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { DictTypeDO dbDictType = randomDictTypeDO(); dictTypeMapper.insert(dbDictType);// @Sql: 先插入出一条存在的数据 // 准备参数 - DictTypeUpdateReqVO reqVO = randomPojo(DictTypeUpdateReqVO.class, o -> { + DictTypeSaveReqVO reqVO = randomPojo(DictTypeSaveReqVO.class, o -> { o.setId(dbDictType.getId()); // 设置更新的 ID o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); }); @@ -191,7 +158,7 @@ public class DictTypeServiceImplTest extends BaseDbUnitTest { // 准备参数 Long id = dbDictType.getId(); // mock 方法 - when(dictDataService.countByDictType(eq(dbDictType.getType()))).thenReturn(1L); + when(dictDataService.getDictDataCountByDictType(eq(dbDictType.getType()))).thenReturn(1L); // 调用, 并断言异常 assertServiceException(() -> dictTypeService.deleteDictType(id), DICT_TYPE_HAS_CHILDREN); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java index cd5e01307..d35ee7b3a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/errorcode/ErrorCodeServiceTest.java @@ -5,10 +5,8 @@ import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeAutoGenerateReqDTO; import cn.iocoder.yudao.module.system.api.errorcode.dto.ErrorCodeRespDTO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.errorcode.vo.ErrorCodeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.errorcode.ErrorCodeDO; import cn.iocoder.yudao.module.system.dal.mysql.errorcode.ErrorCodeMapper; import cn.iocoder.yudao.module.system.enums.errorcode.ErrorCodeTypeEnum; @@ -44,7 +42,8 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { @Test public void testCreateErrorCode_success() { // 准备参数 - ErrorCodeCreateReqVO reqVO = randomPojo(ErrorCodeCreateReqVO.class); + ErrorCodeSaveReqVO reqVO = randomPojo(ErrorCodeSaveReqVO.class) + .setId(null); // 防止 id 被赋值 // 调用 Long errorCodeId = errorCodeService.createErrorCode(reqVO); @@ -52,7 +51,7 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { assertNotNull(errorCodeId); // 校验记录的属性是否正确 ErrorCodeDO errorCode = errorCodeMapper.selectById(errorCodeId); - assertPojoEquals(reqVO, errorCode); + assertPojoEquals(reqVO, errorCode, "id"); assertEquals(ErrorCodeTypeEnum.MANUAL_OPERATION.getType(), errorCode.getType()); } @@ -62,7 +61,7 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { ErrorCodeDO dbErrorCode = randomErrorCodeDO(); errorCodeMapper.insert(dbErrorCode);// @Sql: 先插入出一条存在的数据 // 准备参数 - ErrorCodeUpdateReqVO reqVO = randomPojo(ErrorCodeUpdateReqVO.class, o -> { + ErrorCodeSaveReqVO reqVO = randomPojo(ErrorCodeSaveReqVO.class, o -> { o.setId(dbErrorCode.getId()); // 设置更新的 ID }); @@ -133,25 +132,6 @@ public class ErrorCodeServiceTest extends BaseDbUnitTest { return dbErrorCode; } - @Test - public void testGetErrorCodeList_export() { - // mock 数据 - ErrorCodeDO dbErrorCode = initGetErrorCodePage(); - // 准备参数 - ErrorCodeExportReqVO reqVO = new ErrorCodeExportReqVO(); - reqVO.setType(ErrorCodeTypeEnum.AUTO_GENERATION.getType()); - reqVO.setApplicationName("tu"); - reqVO.setCode(1); - reqVO.setMessage("ma"); - reqVO.setCreateTime(buildBetweenTime(2020, 11, 1, 2020, 11, 30)); - - // 调用 - List list = errorCodeService.getErrorCodeList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbErrorCode, list.get(0)); - } - @Test public void testValidateCodeDuplicate_codeDuplicateForCreate() { // 准备参数 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java index 66eebc0bd..530c27408 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImplTest.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog.LoginLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper; @@ -11,7 +10,6 @@ import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; @@ -64,38 +62,6 @@ public class LoginLogServiceImplTest extends BaseDbUnitTest { assertPojoEquals(loginLogDO, pageResult.getList().get(0)); } - @Test - public void testGetLoginLogList() { - // mock 数据 - LoginLogDO loginLogDO = randomPojo(LoginLogDO.class, o -> { - o.setUserIp("192.168.199.16"); - o.setUsername("wang"); - o.setResult(SUCCESS.getResult()); - o.setCreateTime(buildTime(2021, 3, 6)); - }); - loginLogMapper.insert(loginLogDO); - // 测试 status 不匹配 - loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setResult(CAPTCHA_CODE_ERROR.getResult()))); - // 测试 ip 不匹配 - loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setUserIp("192.168.128.18"))); - // 测试 username 不匹配 - loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setUsername("yunai"))); - // 测试 createTime 不匹配 - loginLogMapper.insert(cloneIgnoreId(loginLogDO, o -> o.setCreateTime(buildTime(2021, 2, 6)))); - // 构造调用参数 - LoginLogExportReqVO reqVO = new LoginLogExportReqVO(); - reqVO.setUsername("wang"); - reqVO.setUserIp("192.168.199"); - reqVO.setStatus(true); - reqVO.setCreateTime(buildBetweenTime(2021, 3, 5, 2021, 3, 7)); - - // 调用service方法 - List list = loginLogService.getLoginLogList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(loginLogDO, list.get(0)); - } - @Test public void testCreateLoginLog() { LoginLogCreateReqDTO reqDTO = randomPojo(LoginLogCreateReqDTO.class); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java index 14b007e25..ecc01d796 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImplTest.java @@ -9,7 +9,6 @@ import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.framework.test.core.util.RandomUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -21,7 +20,6 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.Collections; -import java.util.List; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; @@ -46,7 +44,7 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { private AdminUserService userService; @Test - public void testCreateOperateLogAsync() { + public void testCreateOperateLog() { OperateLogCreateReqDTO reqVO = RandomUtils.randomPojo(OperateLogCreateReqDTO.class, o -> o.setExts(MapUtil.builder("orderId", randomLongId()).build())); @@ -105,51 +103,4 @@ public class OperateLogServiceImplTest extends BaseDbUnitTest { assertPojoEquals(operateLogDO, pageResult.getList().get(0)); } - @Test - public void testGetOperateLogs() { - // mock(用户信息) - AdminUserDO user = RandomUtils.randomPojo(AdminUserDO.class, o -> { - o.setNickname("wang"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - }); - when(userService.getUserListByNickname("wang")).thenReturn(Collections.singletonList(user)); - Long userId = user.getId(); - - // 构造操作日志 - OperateLogDO operateLogDO = RandomUtils.randomPojo(OperateLogDO.class, o -> { - o.setUserId(userId); - o.setUserType(randomEle(UserTypeEnum.values()).getValue()); - o.setModule("order"); - o.setType(OperateTypeEnum.CREATE.getType()); - o.setStartTime(buildTime(2021, 3, 6)); - o.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode()); - o.setExts(MapUtil.builder("orderId", randomLongId()).build()); - }); - operateLogMapper.insert(operateLogDO); - // 测试 userId 不匹配 - operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setUserId(userId + 1))); - // 测试 module 不匹配 - operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setModule("user"))); - // 测试 type 不匹配 - operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setType(OperateTypeEnum.IMPORT.getType()))); - // 测试 createTime 不匹配 - operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setStartTime(buildTime(2021, 2, 6)))); - // 测试 resultCode 不匹配 - operateLogMapper.insert(cloneIgnoreId(operateLogDO, o -> o.setResultCode(BAD_REQUEST.getCode()))); - - // 构造调用参数 - OperateLogExportReqVO reqVO = new OperateLogExportReqVO(); - reqVO.setUserNickname("wang"); - reqVO.setModule("order"); - reqVO.setType(OperateTypeEnum.CREATE.getType()); - reqVO.setStartTime(buildBetweenTime(2021, 3, 5, 2021, 3, 7)); - reqVO.setSuccess(true); - - // 调用 service 方法 - List list = operateLogServiceImpl.getOperateLogList(reqVO); - // 断言,只查到了一条符合条件的 - assertEquals(1, list.size()); - assertPojoEquals(operateLogDO, list.get(0)); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImplTest.java index ea2725e25..6e1bf0d05 100755 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailAccountServiceImplTest.java @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.system.service.mail; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; import org.junit.jupiter.api.Test; @@ -43,7 +42,8 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { @Test public void testCreateMailAccount_success() { // 准备参数 - MailAccountCreateReqVO reqVO = randomPojo(MailAccountCreateReqVO.class, o -> o.setMail(randomEmail())); + MailAccountSaveReqVO reqVO = randomPojo(MailAccountSaveReqVO.class, o -> o.setMail(randomEmail())) + .setId(null); // 防止 id 被赋值 // 调用 Long mailAccountId = mailAccountService.createMailAccount(reqVO); @@ -51,7 +51,7 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { assertNotNull(mailAccountId); // 校验记录的属性是否正确 MailAccountDO mailAccount = mailAccountMapper.selectById(mailAccountId); - assertPojoEquals(reqVO, mailAccount); + assertPojoEquals(reqVO, mailAccount, "id"); } @Test @@ -60,7 +60,7 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { MailAccountDO dbMailAccount = randomPojo(MailAccountDO.class); mailAccountMapper.insert(dbMailAccount);// @Sql: 先插入出一条存在的数据 // 准备参数 - MailAccountUpdateReqVO reqVO = randomPojo(MailAccountUpdateReqVO.class, o -> { + MailAccountSaveReqVO reqVO = randomPojo(MailAccountSaveReqVO.class, o -> { o.setId(dbMailAccount.getId()); // 设置更新的 ID o.setMail(randomEmail()); }); @@ -75,7 +75,7 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateMailAccount_notExists() { // 准备参数 - MailAccountUpdateReqVO reqVO = randomPojo(MailAccountUpdateReqVO.class); + MailAccountSaveReqVO reqVO = randomPojo(MailAccountSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> mailAccountService.updateMailAccount(reqVO), MAIL_ACCOUNT_NOT_EXISTS); @@ -89,7 +89,7 @@ public class MailAccountServiceImplTest extends BaseDbUnitTest { // 准备参数 Long id = dbMailAccount.getId(); // mock 方法(无关联模版) - when(mailTemplateService.countByAccountId(eq(id))).thenReturn(0L); + when(mailTemplateService.getMailTemplateCountByAccountId(eq(id))).thenReturn(0L); // 调用 mailAccountService.deleteMailAccount(id); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java index 8776595ea..7199bd325 100755 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java @@ -3,9 +3,8 @@ package cn.iocoder.yudao.module.system.service.mail; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; import org.junit.jupiter.api.Test; @@ -43,7 +42,8 @@ public class MailTemplateServiceImplTest extends BaseDbUnitTest { @Test public void testCreateMailTemplate_success() { // 准备参数 - MailTemplateCreateReqVO reqVO = randomPojo(MailTemplateCreateReqVO.class); + MailTemplateSaveReqVO reqVO = randomPojo(MailTemplateSaveReqVO.class) + .setId(null); // 防止 id 被赋值 // 调用 Long mailTemplateId = mailTemplateService.createMailTemplate(reqVO); @@ -51,7 +51,7 @@ public class MailTemplateServiceImplTest extends BaseDbUnitTest { assertNotNull(mailTemplateId); // 校验记录的属性是否正确 MailTemplateDO mailTemplate = mailTemplateMapper.selectById(mailTemplateId); - assertPojoEquals(reqVO, mailTemplate); + assertPojoEquals(reqVO, mailTemplate, "id"); } @Test @@ -60,7 +60,7 @@ public class MailTemplateServiceImplTest extends BaseDbUnitTest { MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class); mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据 // 准备参数 - MailTemplateUpdateReqVO reqVO = randomPojo(MailTemplateUpdateReqVO.class, o -> { + MailTemplateSaveReqVO reqVO = randomPojo(MailTemplateSaveReqVO.class, o -> { o.setId(dbMailTemplate.getId()); // 设置更新的 ID }); @@ -74,7 +74,7 @@ public class MailTemplateServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateMailTemplate_notExists() { // 准备参数 - MailTemplateUpdateReqVO reqVO = randomPojo(MailTemplateUpdateReqVO.class); + MailTemplateSaveReqVO reqVO = randomPojo(MailTemplateSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> mailTemplateService.updateMailTemplate(reqVO), MAIL_TEMPLATE_NOT_EXISTS); @@ -207,7 +207,7 @@ public class MailTemplateServiceImplTest extends BaseDbUnitTest { Long accountId = dbMailTemplate.getAccountId(); // 调用 - long count = mailTemplateService.countByAccountId(accountId); + long count = mailTemplateService.getMailTemplateCountByAccountId(accountId); // 断言 assertEquals(1, count); } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java index b4727096a..dfde83538 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notice/NoticeServiceImplTest.java @@ -3,9 +3,8 @@ package cn.iocoder.yudao.module.system.service.notice; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notice.vo.NoticeSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notice.NoticeDO; import cn.iocoder.yudao.module.system.dal.mysql.notice.NoticeMapper; import org.junit.jupiter.api.Test; @@ -72,14 +71,15 @@ class NoticeServiceImplTest extends BaseDbUnitTest { @Test public void testCreateNotice_success() { // 准备参数 - NoticeCreateReqVO reqVO = randomPojo(NoticeCreateReqVO.class); + NoticeSaveReqVO reqVO = randomPojo(NoticeSaveReqVO.class) + .setId(null); // 避免 id 被赋值 // 调用 Long noticeId = noticeService.createNotice(reqVO); // 校验插入属性是否正确 assertNotNull(noticeId); NoticeDO notice = noticeMapper.selectById(noticeId); - assertPojoEquals(reqVO, notice); + assertPojoEquals(reqVO, notice, "id"); } @Test @@ -89,7 +89,7 @@ class NoticeServiceImplTest extends BaseDbUnitTest { noticeMapper.insert(dbNoticeDO); // 准备更新参数 - NoticeUpdateReqVO reqVO = randomPojo(NoticeUpdateReqVO.class, o -> o.setId(dbNoticeDO.getId())); + NoticeSaveReqVO reqVO = randomPojo(NoticeSaveReqVO.class, o -> o.setId(dbNoticeDO.getId())); // 更新 noticeService.updateNotice(reqVO); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImplTest.java index 04c410fb7..d49f48cce 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifyTemplateServiceImplTest.java @@ -3,9 +3,8 @@ package cn.iocoder.yudao.module.system.service.notify; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.notify.vo.template.NotifyTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.notify.NotifyTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.notify.NotifyTemplateMapper; import org.junit.jupiter.api.Test; @@ -41,8 +40,9 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest { @Test public void testCreateNotifyTemplate_success() { // 准备参数 - NotifyTemplateCreateReqVO reqVO = randomPojo(NotifyTemplateCreateReqVO.class, - o -> o.setStatus(randomCommonStatus())); + NotifyTemplateSaveReqVO reqVO = randomPojo(NotifyTemplateSaveReqVO.class, + o -> o.setStatus(randomCommonStatus())) + .setId(null); // 防止 id 被赋值 // 调用 Long notifyTemplateId = notifyTemplateService.createNotifyTemplate(reqVO); @@ -50,7 +50,7 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest { assertNotNull(notifyTemplateId); // 校验记录的属性是否正确 NotifyTemplateDO notifyTemplate = notifyTemplateMapper.selectById(notifyTemplateId); - assertPojoEquals(reqVO, notifyTemplate); + assertPojoEquals(reqVO, notifyTemplate, "id"); } @Test @@ -59,7 +59,7 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest { NotifyTemplateDO dbNotifyTemplate = randomPojo(NotifyTemplateDO.class); notifyTemplateMapper.insert(dbNotifyTemplate);// @Sql: 先插入出一条存在的数据 // 准备参数 - NotifyTemplateUpdateReqVO reqVO = randomPojo(NotifyTemplateUpdateReqVO.class, o -> { + NotifyTemplateSaveReqVO reqVO = randomPojo(NotifyTemplateSaveReqVO.class, o -> { o.setId(dbNotifyTemplate.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); }); @@ -74,7 +74,7 @@ public class NotifyTemplateServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateNotifyTemplate_notExists() { // 准备参数 - NotifyTemplateUpdateReqVO reqVO = randomPojo(NotifyTemplateUpdateReqVO.class); + NotifyTemplateSaveReqVO reqVO = randomPojo(NotifyTemplateSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> notifyTemplateService.updateNotifyTemplate(reqVO), NOTIFY_TEMPLATE_NOT_EXISTS); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java index 25b31220c..3d4e436ab 100755 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java @@ -4,9 +4,8 @@ import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper; import org.junit.jupiter.api.Test; @@ -42,8 +41,9 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { @Test public void testCreateOAuth2Client_success() { // 准备参数 - OAuth2ClientCreateReqVO reqVO = randomPojo(OAuth2ClientCreateReqVO.class, - o -> o.setLogo(randomString())); + OAuth2ClientSaveReqVO reqVO = randomPojo(OAuth2ClientSaveReqVO.class, + o -> o.setLogo(randomString())) + .setId(null); // 防止 id 被赋值 // 调用 Long oauth2ClientId = oauth2ClientService.createOAuth2Client(reqVO); @@ -51,7 +51,7 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { assertNotNull(oauth2ClientId); // 校验记录的属性是否正确 OAuth2ClientDO oAuth2Client = oauth2ClientMapper.selectById(oauth2ClientId); - assertPojoEquals(reqVO, oAuth2Client); + assertPojoEquals(reqVO, oAuth2Client, "id"); } @Test @@ -60,7 +60,7 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class); oauth2ClientMapper.insert(dbOAuth2Client);// @Sql: 先插入出一条存在的数据 // 准备参数 - OAuth2ClientUpdateReqVO reqVO = randomPojo(OAuth2ClientUpdateReqVO.class, o -> { + OAuth2ClientSaveReqVO reqVO = randomPojo(OAuth2ClientSaveReqVO.class, o -> { o.setId(dbOAuth2Client.getId()); // 设置更新的 ID o.setLogo(randomString()); }); @@ -75,7 +75,7 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateOAuth2Client_notExists() { // 准备参数 - OAuth2ClientUpdateReqVO reqVO = randomPojo(OAuth2ClientUpdateReqVO.class); + OAuth2ClientSaveReqVO reqVO = randomPojo(OAuth2ClientSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> oauth2ClientService.updateOAuth2Client(reqVO), OAUTH2_CLIENT_NOT_EXISTS); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java index a0c17b3fb..3a95fd30f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.system.service.permission; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper; import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum; @@ -14,7 +13,8 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; -import java.util.*; +import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; @@ -51,16 +51,16 @@ public class MenuServiceImplTest extends BaseDbUnitTest { menuMapper.insert(menuDO); Long parentId = menuDO.getId(); // 准备参数 - MenuCreateReqVO reqVO = randomPojo(MenuCreateReqVO.class, o -> { + MenuSaveVO reqVO = randomPojo(MenuSaveVO.class, o -> { o.setParentId(parentId); o.setName("testSonName"); o.setType(MenuTypeEnum.MENU.getType()); - }); + }).setId(null); // 防止 id 被赋值 Long menuId = menuService.createMenu(reqVO); // 校验记录的属性是否正确 MenuDO dbMenu = menuMapper.selectById(menuId); - assertPojoEquals(reqVO, dbMenu); + assertPojoEquals(reqVO, dbMenu, "id"); } @Test @@ -69,7 +69,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest { MenuDO sonMenuDO = createParentAndSonMenu(); Long sonId = sonMenuDO.getId(); // 准备参数 - MenuUpdateReqVO reqVO = randomPojo(MenuUpdateReqVO.class, o -> { + MenuSaveVO reqVO = randomPojo(MenuSaveVO.class, o -> { o.setId(sonId); o.setName("testSonName"); // 修改名字 o.setParentId(sonMenuDO.getParentId()); @@ -86,7 +86,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateMenu_sonIdNotExist() { // 准备参数 - MenuUpdateReqVO reqVO = randomPojo(MenuUpdateReqVO.class); + MenuSaveVO reqVO = randomPojo(MenuSaveVO.class); // 调用,并断言异常 assertServiceException(() -> menuService.updateMenu(reqVO), MENU_NOT_EXISTS); } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java index 5c7e96398..6b590e161 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImplTest.java @@ -4,10 +4,8 @@ import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RolePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper; import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum; @@ -52,13 +50,14 @@ public class RoleServiceImplTest extends BaseDbUnitTest { @Test public void testCreateRole() { // 准备参数 - RoleCreateReqVO reqVO = randomPojo(RoleCreateReqVO.class); + RoleSaveReqVO reqVO = randomPojo(RoleSaveReqVO.class) + .setId(null); // 防止 id 被赋值 // 调用 Long roleId = roleService.createRole(reqVO, null); // 断言 RoleDO roleDO = roleMapper.selectById(roleId); - assertPojoEquals(reqVO, roleDO); + assertPojoEquals(reqVO, roleDO, "id"); assertEquals(RoleTypeEnum.CUSTOM.getType(), roleDO.getType()); assertEquals(CommonStatusEnum.ENABLE.getStatus(), roleDO.getStatus()); assertEquals(DataScopeEnum.ALL.getScope(), roleDO.getDataScope()); @@ -71,7 +70,7 @@ public class RoleServiceImplTest extends BaseDbUnitTest { roleMapper.insert(roleDO); // 准备参数 Long id = roleDO.getId(); - RoleUpdateReqVO reqVO = randomPojo(RoleUpdateReqVO.class, o -> o.setId(id)); + RoleSaveReqVO reqVO = randomPojo(RoleSaveReqVO.class, o -> o.setId(id)); // 调用 roleService.updateRole(reqVO); @@ -256,36 +255,6 @@ public class RoleServiceImplTest extends BaseDbUnitTest { } } - @Test - public void testGetRoleList() { - // mock 数据 - RoleDO dbRole = randomPojo(RoleDO.class, o -> { // 等会查询到 - o.setName("土豆"); - o.setCode("tudou"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2022, 2, 8)); - }); - roleMapper.insert(dbRole); - // 测试 name 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setName("红薯"))); - // 测试 code 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCode("hong"))); - // 测试 createTime 不匹配 - roleMapper.insert(cloneIgnoreId(dbRole, o -> o.setCreateTime(buildTime(2022, 2, 16)))); - // 准备参数 - RoleExportReqVO reqVO = new RoleExportReqVO(); - reqVO.setName("土豆"); - reqVO.setCode("tu"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2022, 2, 1, 2022, 2, 12)); - - // 调用 - List list = roleService.getRoleList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbRole, list.get(0)); - } - @Test public void testGetRolePage() { // mock 数据 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java index 47f1ea923..cc7b11d50 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sensitiveword/SensitiveWordServiceImplTest.java @@ -4,10 +4,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sensitiveword.vo.SensitiveWordSaveVO; import cn.iocoder.yudao.module.system.dal.dataobject.sensitiveword.SensitiveWordDO; import cn.iocoder.yudao.module.system.dal.mysql.sensitiveword.SensitiveWordMapper; import org.junit.jupiter.api.BeforeEach; @@ -83,7 +81,8 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @Test public void testCreateSensitiveWord_success() { // 准备参数 - SensitiveWordCreateReqVO reqVO = randomPojo(SensitiveWordCreateReqVO.class); + SensitiveWordSaveVO reqVO = randomPojo(SensitiveWordSaveVO.class) + .setId(null); // 防止 id 被赋值 // 调用 Long sensitiveWordId = sensitiveWordService.createSensitiveWord(reqVO); @@ -91,7 +90,7 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { assertNotNull(sensitiveWordId); // 校验记录的属性是否正确 SensitiveWordDO sensitiveWord = sensitiveWordMapper.selectById(sensitiveWordId); - assertPojoEquals(reqVO, sensitiveWord); + assertPojoEquals(reqVO, sensitiveWord, "id"); } @Test @@ -100,7 +99,7 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { SensitiveWordDO dbSensitiveWord = randomPojo(SensitiveWordDO.class); sensitiveWordMapper.insert(dbSensitiveWord);// @Sql: 先插入出一条存在的数据 // 准备参数 - SensitiveWordUpdateReqVO reqVO = randomPojo(SensitiveWordUpdateReqVO.class, o -> { + SensitiveWordSaveVO reqVO = randomPojo(SensitiveWordSaveVO.class, o -> { o.setId(dbSensitiveWord.getId()); // 设置更新的 ID }); @@ -114,7 +113,7 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateSensitiveWord_notExists() { // 准备参数 - SensitiveWordUpdateReqVO reqVO = randomPojo(SensitiveWordUpdateReqVO.class); + SensitiveWordSaveVO reqVO = randomPojo(SensitiveWordSaveVO.class); // 调用, 并断言异常 assertServiceException(() -> sensitiveWordService.updateSensitiveWord(reqVO), SENSITIVE_WORD_NOT_EXISTS); @@ -204,36 +203,6 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbSensitiveWord, pageResult.getList().get(0)); } - @Test - public void testGetSensitiveWordList_export() { - // mock 数据 - SensitiveWordDO dbSensitiveWord = randomPojo(SensitiveWordDO.class, o -> { // 等会查询到 - o.setName("笨蛋"); - o.setTags(Arrays.asList("论坛", "蔬菜")); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2022, 2, 8)); - }); - sensitiveWordMapper.insert(dbSensitiveWord); - // 测试 name 不匹配 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setName("傻瓜"))); - // 测试 tags 不匹配 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setTags(Arrays.asList("短信", "日用品")))); - // 测试 createTime 不匹配 - sensitiveWordMapper.insert(cloneIgnoreId(dbSensitiveWord, o -> o.setCreateTime(buildTime(2022, 2, 16)))); - // 准备参数 - SensitiveWordExportReqVO reqVO = new SensitiveWordExportReqVO(); - reqVO.setName("笨"); - reqVO.setTag("论坛"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2022, 2, 1, 2022, 2, 12)); - - // 调用 - List list = sensitiveWordService.getSensitiveWordList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSensitiveWord, list.get(0)); - } - @Test public void testValidateText_noTag() { testInitLocalCache(); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java index 6bb32a8f3..551f39f04 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java @@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelUpdateReqVO; -import cn.iocoder.yudao.module.system.convert.sms.SmsChannelConvert; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper; import org.junit.jupiter.api.Test; @@ -48,7 +47,8 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { @Test public void testCreateSmsChannel_success() { // 准备参数 - SmsChannelCreateReqVO reqVO = randomPojo(SmsChannelCreateReqVO.class, o -> o.setStatus(randomCommonStatus())); + SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class, o -> o.setStatus(randomCommonStatus())) + .setId(null); // 防止 id 被赋值 // 调用 Long smsChannelId = smsChannelService.createSmsChannel(reqVO); @@ -56,7 +56,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { assertNotNull(smsChannelId); // 校验记录的属性是否正确 SmsChannelDO smsChannel = smsChannelMapper.selectById(smsChannelId); - assertPojoEquals(reqVO, smsChannel); + assertPojoEquals(reqVO, smsChannel, "id"); // 断言 cache assertNull(smsChannelService.getIdClientCache().getIfPresent(smsChannel.getId())); assertNull(smsChannelService.getCodeClientCache().getIfPresent(smsChannel.getCode())); @@ -68,7 +68,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class); smsChannelMapper.insert(dbSmsChannel);// @Sql: 先插入出一条存在的数据 // 准备参数 - SmsChannelUpdateReqVO reqVO = randomPojo(SmsChannelUpdateReqVO.class, o -> { + SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class, o -> { o.setId(dbSmsChannel.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); o.setCallbackUrl(randomString()); @@ -87,7 +87,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { @Test public void testUpdateSmsChannel_notExists() { // 准备参数 - SmsChannelUpdateReqVO reqVO = randomPojo(SmsChannelUpdateReqVO.class); + SmsChannelSaveReqVO reqVO = randomPojo(SmsChannelSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> smsChannelService.updateSmsChannel(reqVO), SMS_CHANNEL_NOT_EXISTS); @@ -127,7 +127,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { // 准备参数 Long id = dbSmsChannel.getId(); // mock 方法 - when(smsTemplateService.countByChannelId(eq(id))).thenReturn(10L); + when(smsTemplateService.getSmsTemplateCountByChannelId(eq(id))).thenReturn(10L); // 调用, 并断言异常 assertServiceException(() -> smsChannelService.deleteSmsChannel(id), SMS_CHANNEL_HAS_CHILDREN); @@ -164,31 +164,31 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { @Test public void testGetSmsChannelPage() { - // mock 数据 - SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到 - o.setSignature("芋道源码"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2020, 12, 12)); - }); - smsChannelMapper.insert(dbSmsChannel); - // 测试 signature 不匹配 - smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码"))); - // 测试 status 不匹配 - smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 createTime 不匹配 - smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11)))); - // 准备参数 - SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO(); - reqVO.setSignature("芋道"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24)); + // mock 数据 + SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到 + o.setSignature("芋道源码"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setCreateTime(buildTime(2020, 12, 12)); + }); + smsChannelMapper.insert(dbSmsChannel); + // 测试 signature 不匹配 + smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码"))); + // 测试 status 不匹配 + smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 createTime 不匹配 + smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11)))); + // 准备参数 + SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO(); + reqVO.setSignature("芋道"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24)); - // 调用 - PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSmsChannel, pageResult.getList().get(0)); + // 调用 + PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSmsChannel, pageResult.getList().get(0)); } @Test @@ -207,7 +207,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { // 断言 assertSame(client, mockClient); verify(smsClientFactory).createOrUpdateSmsClient(argThat(arg -> { - SmsChannelProperties properties = SmsChannelConvert.INSTANCE.convert02(channel); + SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); return properties.equals(arg); })); } @@ -228,7 +228,7 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { // 断言 assertSame(client, mockClient); verify(smsClientFactory).createOrUpdateSmsClient(argThat(arg -> { - SmsChannelProperties properties = SmsChannelConvert.INSTANCE.convert02(channel); + SmsChannelProperties properties = BeanUtils.toBean(channel, SmsChannelProperties.class); return properties.equals(arg); })); } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java index 2380ca09e..eed34b988 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java @@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; @@ -19,7 +17,6 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.time.LocalDateTime; -import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -87,50 +84,6 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbSmsLog, pageResult.getList().get(0)); } - @Test - public void testGetSmsLogList() { - // mock 数据 - SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 - o.setChannelId(1L); - o.setTemplateId(10L); - o.setMobile("15601691300"); - o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - o.setSendTime(buildTime(2020, 11, 11)); - o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - o.setReceiveTime(buildTime(2021, 11, 11)); - }); - smsLogMapper.insert(dbSmsLog); - // 测试 channelId 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); - // 测试 templateId 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); - // 测试 mobile 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); - // 测试 sendStatus 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); - // 测试 sendTime 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); - // 测试 receiveStatus 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); - // 测试 receiveTime 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); - // 准备参数 - SmsLogExportReqVO reqVO = new SmsLogExportReqVO(); - reqVO.setChannelId(1L); - reqVO.setTemplateId(10L); - reqVO.setMobile("156"); - reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - reqVO.setSendTime(buildBetweenTime(2020, 11, 1, 2020, 11, 30)); - reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - reqVO.setReceiveTime(buildBetweenTime(2021, 11, 1, 2021, 11, 30)); - - // 调用 - List list = smsLogService.getSmsLogList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSmsLog, list.get(0)); - } - @Test public void testCreateSmsLog() { // 准备参数 @@ -172,22 +125,20 @@ public class SmsLogServiceImplTest extends BaseDbUnitTest { smsLogMapper.insert(dbSmsLog); // 准备参数 Long id = dbSmsLog.getId(); - Integer sendCode = randomInteger(); - String sendMsg = randomString(); + Boolean success = randomBoolean(); String apiSendCode = randomString(); String apiSendMsg = randomString(); String apiRequestId = randomString(); String apiSerialNo = randomString(); // 调用 - smsLogService.updateSmsSendResult(id, sendCode, sendMsg, + smsLogService.updateSmsSendResult(id, success, apiSendCode, apiSendMsg, apiRequestId, apiSerialNo); // 断言 dbSmsLog = smsLogMapper.selectById(id); - assertEquals(CommonResult.isSuccess(sendCode) ? SmsSendStatusEnum.SUCCESS.getStatus() - : SmsSendStatusEnum.FAILURE.getStatus(), dbSmsLog.getSendStatus()); + assertEquals(success ? SmsSendStatusEnum.SUCCESS.getStatus() : SmsSendStatusEnum.FAILURE.getStatus(), + dbSmsLog.getSendStatus()); assertNotNull(dbSmsLog.getSendTime()); - assertEquals(sendMsg, dbSmsLog.getSendMsg()); assertEquals(apiSendCode, dbSmsLog.getApiSendCode()); assertEquals(apiSendMsg, dbSmsLog.getApiSendMsg()); assertEquals(apiRequestId, dbSmsLog.getApiRequestId()); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java index ee3e8b107..96742c9a8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; @@ -244,15 +243,14 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { @Test @SuppressWarnings("unchecked") - public void testDoSendSms() { + public void testDoSendSms() throws Throwable { // 准备参数 SmsSendMessage message = randomPojo(SmsSendMessage.class); // mock SmsClientFactory 的方法 SmsClient smsClient = spy(SmsClient.class); when(smsChannelService.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient); // mock SmsClient 的方法 - SmsCommonResult sendResult = randomPojo(SmsCommonResult.class, SmsSendRespDTO.class); - sendResult.setData(randomPojo(SmsSendRespDTO.class)); + SmsSendRespDTO sendResult = randomPojo(SmsSendRespDTO.class); when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()), eq(message.getTemplateParams()))).thenReturn(sendResult); @@ -260,8 +258,8 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { smsService.doSendSms(message); // 断言 verify(smsLogService).updateSmsSendResult(eq(message.getLogId()), - eq(sendResult.getCode()), eq(sendResult.getMsg()), eq(sendResult.getApiCode()), - eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getData().getSerialNo())); + eq(sendResult.getSuccess()), eq(sendResult.getApiCode()), + eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getSerialNo())); } @Test diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java index ad6b6e733..4ba4d43fd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java @@ -1,18 +1,15 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; @@ -65,13 +62,13 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { @Test @SuppressWarnings("unchecked") - public void testCreateSmsTemplate_success() { + public void testCreateSmsTemplate_success() throws Throwable { // 准备参数 - SmsTemplateCreateReqVO reqVO = randomPojo(SmsTemplateCreateReqVO.class, o -> { + SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> { o.setContent("正在进行登录操作{operation},您的验证码是{code}"); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围 - }); + }).setId(null); // 防止 id 被赋值 // mock Channel 的方法 SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> { o.setId(reqVO.getChannelId()); @@ -80,8 +77,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); // mock 获得 API 短信模板成功 when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); - when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class, - o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode()))); + when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn( + randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()))); // 调用 Long smsTemplateId = smsTemplateService.createSmsTemplate(reqVO); @@ -89,19 +86,19 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { assertNotNull(smsTemplateId); // 校验记录的属性是否正确 SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(smsTemplateId); - assertPojoEquals(reqVO, smsTemplate); + assertPojoEquals(reqVO, smsTemplate, "id"); assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams()); assertEquals(channelDO.getCode(), smsTemplate.getChannelCode()); } @Test @SuppressWarnings("unchecked") - public void testUpdateSmsTemplate_success() { + public void testUpdateSmsTemplate_success() throws Throwable { // mock 数据 SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO(); smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据 // 准备参数 - SmsTemplateUpdateReqVO reqVO = randomPojo(SmsTemplateUpdateReqVO.class, o -> { + SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> { o.setId(dbSmsTemplate.getId()); // 设置更新的 ID o.setContent("正在进行登录操作{operation},您的验证码是{code}"); o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 @@ -115,8 +112,8 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO); // mock 获得 API 短信模板成功 when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient); - when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class, - o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode()))); + when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn( + randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()))); // 调用 smsTemplateService.updateSmsTemplate(reqVO); @@ -130,7 +127,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateSmsTemplate_notExists() { // 准备参数 - SmsTemplateUpdateReqVO reqVO = randomPojo(SmsTemplateUpdateReqVO.class); + SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> smsTemplateService.updateSmsTemplate(reqVO), SMS_TEMPLATE_NOT_EXISTS); @@ -204,50 +201,6 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbSmsTemplate, pageResult.getList().get(0)); } - @Test - public void testGetSmsTemplateList() { - // mock 数据 - SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到 - o.setType(SmsTemplateTypeEnum.PROMOTION.getType()); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCode("tudou"); - o.setContent("芋道源码"); - o.setApiTemplateId("yunai"); - o.setChannelId(1L); - o.setCreateTime(buildTime(2021, 11, 11)); - }); - smsTemplateMapper.insert(dbSmsTemplate); - // 测试 type 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); - // 测试 status 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 code 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma"))); - // 测试 content 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码"))); - // 测试 apiTemplateId 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai"))); - // 测试 channelId 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L))); - // 测试 createTime 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); - // 准备参数 - SmsTemplateExportReqVO reqVO = new SmsTemplateExportReqVO(); - reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCode("tu"); - reqVO.setContent("芋道"); - reqVO.setApiTemplateId("yu"); - reqVO.setChannelId(1L); - reqVO.setCreateTime(buildBetweenTime(2021, 11, 1, 2021, 12, 1)); - - // 调用 - List list = smsTemplateService.getSmsTemplateList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSmsTemplate, list.get(0)); - } - @Test public void testValidateSmsChannel_success() { // 准备参数 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java new file mode 100644 index 000000000..601255b8b --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.system.service.social; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO; +import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_CLIENT_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:单测后续补充下; +/** + * {@link SocialClientServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(SocialClientServiceImpl.class) +@Disabled +public class SocialClientServiceImplTest extends BaseDbUnitTest { + + @Resource + private SocialClientServiceImpl socialClientService; + + @Resource + private SocialClientMapper socialClientMapper; + + @Test + public void testCreateSocialClient_success() { + // 准备参数 + SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class) + .setId(null); // 防止 id 被赋值 + + // 调用 + Long socialClientId = socialClientService.createSocialClient(reqVO); + // 断言 + assertNotNull(socialClientId); + // 校验记录的属性是否正确 + SocialClientDO socialClient = socialClientMapper.selectById(socialClientId); + assertPojoEquals(reqVO, socialClient, "id"); + } + + @Test + public void testUpdateSocialClient_success() { + // mock 数据 + SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class); + socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据 + // 准备参数 + SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class, o -> { + o.setId(dbSocialClient.getId()); // 设置更新的 ID + }); + + // 调用 + socialClientService.updateSocialClient(reqVO); + // 校验是否更新正确 + SocialClientDO socialClient = socialClientMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, socialClient); + } + + @Test + public void testUpdateSocialClient_notExists() { + // 准备参数 + SocialClientSaveReqVO reqVO = randomPojo(SocialClientSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> socialClientService.updateSocialClient(reqVO), SOCIAL_CLIENT_NOT_EXISTS); + } + + @Test + public void testDeleteSocialClient_success() { + // mock 数据 + SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class); + socialClientMapper.insert(dbSocialClient);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbSocialClient.getId(); + + // 调用 + socialClientService.deleteSocialClient(id); + // 校验数据不存在了 + assertNull(socialClientMapper.selectById(id)); + } + + @Test + public void testDeleteSocialClient_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> socialClientService.deleteSocialClient(id), SOCIAL_CLIENT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetSocialClientPage() { + // mock 数据 + SocialClientDO dbSocialClient = randomPojo(SocialClientDO.class, o -> { // 等会查询到 + o.setName(null); + o.setSocialType(null); + o.setUserType(null); + o.setClientId(null); + o.setClientSecret(null); + o.setStatus(null); + o.setCreateTime(null); + }); + socialClientMapper.insert(dbSocialClient); + // 测试 name 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setName(null))); + // 测试 socialType 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setSocialType(null))); + // 测试 userType 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setUserType(null))); + // 测试 clientId 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientId(null))); + // 测试 clientSecret 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setClientSecret(null))); + // 测试 status 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + socialClientMapper.insert(cloneIgnoreId(dbSocialClient, o -> o.setCreateTime(null))); + // 准备参数 + SocialClientPageReqVO reqVO = new SocialClientPageReqVO(); + reqVO.setName(null); + reqVO.setSocialType(null); + reqVO.setUserType(null); + reqVO.setClientId(null); + reqVO.setStatus(null); + + // 调用 + PageResult pageResult = socialClientService.getSocialClientPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSocialClient, pageResult.getList().get(0)); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java index 5b09a0f2b..8a4f3df5e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.system.service.social; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; @@ -15,6 +14,7 @@ import com.xingyuv.jushauth.model.AuthCallback; import com.xingyuv.jushauth.model.AuthResponse; import com.xingyuv.jushauth.model.AuthUser; import com.xingyuv.jushauth.request.AuthRequest; +import com.xingyuv.justauth.AuthRequestFactory; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -46,7 +46,7 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { private SocialUserBindMapper socialUserBindMapper; @MockBean - private YudaoAuthRequestFactory authRequestFactory; + private AuthRequestFactory authRequestFactory; // TODO 芋艿:后续统一修复 // @Test diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java index 1990b639e..ab4784b97 100755 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImplTest.java @@ -3,9 +3,8 @@ package cn.iocoder.yudao.module.system.service.tenant; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper; @@ -21,8 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.bui import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.*; @@ -50,7 +48,9 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { @Test public void testCreateTenantPackage_success() { // 准备参数 - TenantPackageCreateReqVO reqVO = randomPojo(TenantPackageCreateReqVO.class); + TenantPackageSaveReqVO reqVO = randomPojo(TenantPackageSaveReqVO.class, + o -> o.setStatus(randomCommonStatus())) + .setId(null); // 防止 id 被赋值 // 调用 Long tenantPackageId = tenantPackageService.createTenantPackage(reqVO); @@ -58,17 +58,19 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { assertNotNull(tenantPackageId); // 校验记录的属性是否正确 TenantPackageDO tenantPackage = tenantPackageMapper.selectById(tenantPackageId); - assertPojoEquals(reqVO, tenantPackage); + assertPojoEquals(reqVO, tenantPackage, "id"); } @Test public void testUpdateTenantPackage_success() { // mock 数据 - TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class); + TenantPackageDO dbTenantPackage = randomPojo(TenantPackageDO.class, + o -> o.setStatus(randomCommonStatus())); tenantPackageMapper.insert(dbTenantPackage);// @Sql: 先插入出一条存在的数据 // 准备参数 - TenantPackageUpdateReqVO reqVO = randomPojo(TenantPackageUpdateReqVO.class, o -> { + TenantPackageSaveReqVO reqVO = randomPojo(TenantPackageSaveReqVO.class, o -> { o.setId(dbTenantPackage.getId()); // 设置更新的 ID + o.setStatus(randomCommonStatus()); }); // mock 方法 Long tenantId01 = randomLongId(); @@ -90,7 +92,7 @@ public class TenantPackageServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateTenantPackage_notExists() { // 准备参数 - TenantPackageUpdateReqVO reqVO = randomPojo(TenantPackageUpdateReqVO.class); + TenantPackageSaveReqVO reqVO = randomPojo(TenantPackageSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> tenantPackageService.updateTenantPackage(reqVO), TENANT_PACKAGE_NOT_EXISTS); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java index 2dd539b2e..62e7808c8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImplTest.java @@ -5,10 +5,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.tenant.config.TenantProperties; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; @@ -152,15 +150,15 @@ public class TenantServiceImplTest extends BaseDbUnitTest { }))).thenReturn(300L); // 准备参数 - TenantCreateReqVO reqVO = randomPojo(TenantCreateReqVO.class, o -> { + TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class, o -> { o.setContactName("芋道"); o.setContactMobile("15601691300"); o.setPackageId(100L); o.setStatus(randomCommonStatus()); - o.setDomain("https://www.iocoder.cn"); + o.setWebsite("https://www.iocoder.cn"); o.setUsername("yunai"); o.setPassword("yuanma"); - }); + }).setId(null); // 设置为 null,方便后面校验 // 调用 Long tenantId = tenantService.createTenant(reqVO); @@ -168,7 +166,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { assertNotNull(tenantId); // 校验记录的属性是否正确 TenantDO tenant = tenantMapper.selectById(tenantId); - assertPojoEquals(reqVO, tenant); + assertPojoEquals(reqVO, tenant, "id"); assertEquals(300L, tenant.getContactUserId()); // verify 分配权限 verify(permissionService).assignRoleMenu(eq(200L), same(tenantPackage.getMenuIds())); @@ -182,10 +180,10 @@ public class TenantServiceImplTest extends BaseDbUnitTest { TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setStatus(randomCommonStatus())); tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据 // 准备参数 - TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class, o -> { + TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class, o -> { o.setId(dbTenant.getId()); // 设置更新的 ID o.setStatus(randomCommonStatus()); - o.setDomain(randomString()); + o.setWebsite(randomString()); }); // mock 套餐 @@ -214,7 +212,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateTenant_notExists() { // 准备参数 - TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class); + TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class); // 调用, 并断言异常 assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_NOT_EXISTS); @@ -226,7 +224,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { TenantDO dbTenant = randomPojo(TenantDO.class, o -> o.setPackageId(PACKAGE_ID_SYSTEM)); tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据 // 准备参数 - TenantUpdateReqVO reqVO = randomPojo(TenantUpdateReqVO.class, o -> { + TenantSaveReqVO reqVO = randomPojo(TenantSaveReqVO.class, o -> { o.setId(dbTenant.getId()); // 设置更新的 ID }); @@ -321,42 +319,6 @@ public class TenantServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbTenant, pageResult.getList().get(0)); } - @Test - public void testGetTenantList() { - // mock 数据 - TenantDO dbTenant = randomPojo(TenantDO.class, o -> { // 等会查询到 - o.setName("芋道源码"); - o.setContactName("芋艿"); - o.setContactMobile("15601691300"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2020, 12, 12)); - }); - tenantMapper.insert(dbTenant); - // 测试 name 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setName(randomString()))); - // 测试 contactName 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactName(randomString()))); - // 测试 contactMobile 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactMobile(randomString()))); - // 测试 status 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 createTime 不匹配 - tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12)))); - // 准备参数 - TenantExportReqVO reqVO = new TenantExportReqVO(); - reqVO.setName("芋道"); - reqVO.setContactName("艿"); - reqVO.setContactMobile("1560"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24)); - - // 调用 - List list = tenantService.getTenantList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbTenant, list.get(0)); - } - @Test public void testGetTenantByName() { // mock 数据 diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java index acc4357cc..03d7f8808 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java @@ -10,7 +10,10 @@ import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.infra.api.file.FileApi; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO; import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO; @@ -80,11 +83,11 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { @Test public void testCreatUser_success() { // 准备参数 - UserCreateReqVO reqVO = randomPojo(UserCreateReqVO.class, o -> { + UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class, o -> { o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex()); o.setMobile(randomString()); o.setPostIds(asSet(1L, 2L)); - }); + }).setId(null); // 避免 id 被赋值 // mock 账户额度充足 TenantDO tenant = randomPojo(TenantDO.class, o -> o.setAccountCount(1)); doNothing().when(tenantService).handleTenantInfo(argThat(handler -> { @@ -111,7 +114,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { Long userId = userService.createUser(reqVO); // 断言 AdminUserDO user = userMapper.selectById(userId); - assertPojoEquals(reqVO, user, "password"); + assertPojoEquals(reqVO, user, "password", "id"); assertEquals("yudaoyuanma", user.getPassword()); assertEquals(CommonStatusEnum.ENABLE.getStatus(), user.getStatus()); // 断言关联岗位 @@ -123,7 +126,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { @Test public void testCreatUser_max() { // 准备参数 - UserCreateReqVO reqVO = randomPojo(UserCreateReqVO.class); + UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class); // mock 账户额度不足 TenantDO tenant = randomPojo(TenantDO.class, o -> o.setAccountCount(-1)); doNothing().when(tenantService).handleTenantInfo(argThat(handler -> { @@ -143,7 +146,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(1L)); userPostMapper.insert(new UserPostDO().setUserId(dbUser.getId()).setPostId(2L)); // 准备参数 - UserUpdateReqVO reqVO = randomPojo(UserUpdateReqVO.class, o -> { + UserSaveReqVO reqVO = randomPojo(UserSaveReqVO.class, o -> { o.setId(dbUser.getId()); o.setSex(RandomUtil.randomEle(SexEnum.values()).getSex()); o.setMobile(randomString()); @@ -167,7 +170,7 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { userService.updateUser(reqVO); // 断言 AdminUserDO user = userMapper.selectById(reqVO.getId()); - assertPojoEquals(reqVO, user); + assertPojoEquals(reqVO, user, "password"); // 断言关联岗位 List userPosts = userPostMapper.selectListByUserId(user.getId()); assertEquals(2L, userPosts.get(0).getPostId()); @@ -355,28 +358,6 @@ public class AdminUserServiceImplTest extends BaseDbUnitTest { assertPojoEquals(dbUser, pageResult.getList().get(0)); } - @Test - public void testGetUserList_export() { - // mock 数据 - AdminUserDO dbUser = initGetUserPageData(); - // 准备参数 - UserExportReqVO reqVO = new UserExportReqVO(); - reqVO.setUsername("tu"); - reqVO.setMobile("1560"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24)); - reqVO.setDeptId(1L); // 其中,1L 是 2L 的父部门 - // mock 方法 - List deptList = newArrayList(randomPojo(DeptDO.class, o -> o.setId(2L))); - when(deptService.getChildDeptList(eq(reqVO.getDeptId()))).thenReturn(deptList); - - // 调用 - List list = userService.getUserList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbUser, list.get(0)); - } - /** * 初始化 getUserPage 方法的测试数据 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql index 7045b4e1c..ffe0f2609 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql @@ -411,7 +411,7 @@ CREATE TABLE IF NOT EXISTS "system_tenant" ( "contact_name" varchar(255) NOT NULL, "contact_mobile" varchar(255), "status" tinyint NOT NULL, - "domain" varchar(63) DEFAULT '', + "website" varchar(63) DEFAULT '', "package_id" bigint NOT NULL, "expire_time" timestamp NOT NULL, "account_count" int NOT NULL, diff --git a/yudao-ui-admin-uniapp/README.md b/yudao-ui/yudao-ui-admin-uniapp/README.md similarity index 100% rename from yudao-ui-admin-uniapp/README.md rename to yudao-ui/yudao-ui-admin-uniapp/README.md diff --git a/yudao-ui-admin-vben/README.md b/yudao-ui/yudao-ui-admin-vben/README.md similarity index 100% rename from yudao-ui-admin-vben/README.md rename to yudao-ui/yudao-ui-admin-vben/README.md diff --git a/yudao-ui-admin-vue2/README.md b/yudao-ui/yudao-ui-admin-vue2/README.md similarity index 100% rename from yudao-ui-admin-vue2/README.md rename to yudao-ui/yudao-ui-admin-vue2/README.md diff --git a/yudao-ui-admin-vue3/README.md b/yudao-ui/yudao-ui-admin-vue3/README.md similarity index 100% rename from yudao-ui-admin-vue3/README.md rename to yudao-ui/yudao-ui-admin-vue3/README.md diff --git a/yudao-ui-mall-uniapp/README.md b/yudao-ui/yudao-ui-mall-uniapp/README.md similarity index 100% rename from yudao-ui-mall-uniapp/README.md rename to yudao-ui/yudao-ui-mall-uniapp/README.md