diff --git a/.DS_Store b/.DS_Store index 8406d508bca176e90b7f717667ad1c8f1a08dc3d..a0cc682e9fc0e78be316502f41253d0a2607da9a 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/README.md b/README.md index c0ecdf6f497b656aef3f0f0bd09c139e2cc2e59c..62252f9ac397809c6defd2bfb677d802d1ab6307 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- Downloads + Downloads Downloads - Downloads +

**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!** @@ -308,26 +308,26 @@ | 框架 | 说明 | 版本 | 学习指南 | |---------------------------------------------------------------------------------------------|------------------|----------------|----------------------------------------------------------------| -| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 3.5.5 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | +| [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.7.18 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | | -| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.27 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | -| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.12 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | -| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 4.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | +| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.23 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.5.7 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | | [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 /7.0 | | -| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.35.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | -| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 6.2.9 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | -| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 6.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | -| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 8.0.2 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | -| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 7.0.0 | [文档](https://doc.iocoder.cn/bpm/) | -| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | -| [Springdoc](https://springdoc.org/) | Swagger 文档 | 2.8.9 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | -| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 9.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | -| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 3.5.2 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | -| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.30.14 | | +| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.32.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | +| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | +| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.11 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) | +| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) | +| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) | +| [Quartz](https://github.com/quartz-scheduler) | 任务调度组件 | 2.3.2 | [文档](http://www.iocoder.cn/Spring-Boot/Job/?yudao) | +| [Springdoc](https://springdoc.org/) | Swagger 文档 | 1.7.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) | +| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) | +| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) | +| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.5 | | | [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.6.3 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) | -| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.38 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | -| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.12.2 | - | -| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 5.17.0 | - | +| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.34 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) | +| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - | +| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - | ## 🐷 演示图 diff --git a/pom.xml b/pom.xml index a1891c93044bb838fa46724ea9119fc27c8ab516..0ce0784e8175729c76601018ee24d159314b2d62 100644 --- a/pom.xml +++ b/pom.xml @@ -23,8 +23,9 @@ - + + ${project.artifactId} @@ -32,9 +33,9 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2025.09-SNAPSHOT + 2025.09-jdk8-SNAPSHOT - 17 + 1.8 ${java.version} ${java.version} 3.5.3 @@ -42,7 +43,7 @@ 1.7.2 1.18.38 - 3.5.5 + 2.7.18 1.6.3 UTF-8 @@ -100,11 +101,6 @@ ${mapstruct.version} - - false - - -parameters - diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index ae977dd971580bf2d9faf720cd7635111cf302e6..a841d303c9e6216d7a4f7512ea2a188cc9351584 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -15,7 +15,7 @@ services: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-123456} volumes: - mysql:/var/lib/mysql/ - - ./sql/mysql/ruoyi-vue-pro.sql:/docker-entrypoint-initdb.d/ruoyi-vue-pro.sql:ro + - ../../sql/mysql/ruoyi-vue-pro.sql:/docker-entrypoint-initdb.d/ruoyi-vue-pro.sql:ro redis: container_name: yudao-redis @@ -50,7 +50,7 @@ services: --spring.datasource.dynamic.datasource.slave.url=${SLAVE_DATASOURCE_URL:-jdbc:mysql://yudao-mysql:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true} --spring.datasource.dynamic.datasource.slave.username=${SLAVE_DATASOURCE_USERNAME:-root} --spring.datasource.dynamic.datasource.slave.password=${SLAVE_DATASOURCE_PASSWORD:-123456} - --spring.data.redis.host=${REDIS_HOST:-yudao-redis} + --spring.redis.host=${REDIS_HOST:-yudao-redis} depends_on: - mysql - redis 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 deleted file mode 100644 index fbc4c6bc1b6b768bf1778a69b6701e4564e42d44..0000000000000000000000000000000000000000 --- a/sql/dm/flowable-patch/src/main/java/liquibase/database/core/DmDatabase.java +++ /dev/null @@ -1,598 +0,0 @@ -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 deleted file mode 100644 index cda2492e2f10592e6a2f8e1f161b7ae404b2afb6..0000000000000000000000000000000000000000 --- a/sql/dm/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java +++ /dev/null @@ -1,165 +0,0 @@ -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 deleted file mode 100644 index 33c52d5510fbca3fc09c2152ce0caf54f44ef081..0000000000000000000000000000000000000000 --- a/sql/dm/flowable-patch/src/main/java/org/flowable/common/engine/impl/AbstractEngineConfiguration.java +++ /dev/null @@ -1,2068 +0,0 @@ -/* 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 deleted file mode 100644 index 1932c7a3fc573f2c2f5c35b9797a6e11106cb34f..0000000000000000000000000000000000000000 --- a/sql/dm/flowable-patch/src/main/resources/META-INF/package-info.md +++ /dev/null @@ -1 +0,0 @@ -防止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 deleted file mode 100644 index efbcfcca21102738a8dab638c90bbe234d552489..0000000000000000000000000000000000000000 --- a/sql/dm/flowable-patch/src/main/resources/META-INF/services/liquibase.database.Database +++ /dev/null @@ -1,21 +0,0 @@ -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/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 8d8ea44dcc6846899bb8ff428b944cdc970b3e73..98b5641bdedb9e6cf3935aeaa7a71645ffe2a450 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,13 +14,16 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2025.09-SNAPSHOT - 1.7.2 + 2025.09-jdk8-SNAPSHOT + 1.6.0 - 3.5.5 + 5.3.39 + 5.8.16 + 2.7.18 - 2.8.11 + 1.8.0 4.5.0 + 2.5 1.2.27 3.5.19 @@ -38,31 +41,30 @@ 2.2.7 - 9.5.0 - 3.5.2 + 8.12.0 + 2.7.15 0.33.0 - 8.0.2.RELEASE + 7.2.11.RELEASE 1.1.11 - 5.2.0 + 4.11.0 - 7.0.1 + 6.8.0 1.4.0 1.21.2 1.18.38 1.6.3 5.8.40 - 6.0.0-M22 1.3.0 - 2.4.1 + 2.4 1.2.83 33.4.8-jre 2.14.5 3.11.1 3.18.0 0.1.55 - 3.2.2 + 2.9.3 2.7.0 3.0.6 4.2.4.Final @@ -76,6 +78,8 @@ 2.1.1 2.1.0 4.7.7-20250808.182223 + + 1.2.13 @@ -88,6 +92,20 @@ pom import + + org.springframework + spring-framework-bom + ${spring.framework.version} + pom + import + + + org.springframework.security + spring-security-bom + ${spring.security.version} + pom + import + org.springframework.boot spring-boot-dependencies @@ -153,18 +171,12 @@ com.github.xiaoymin - knife4j-openapi3-jakarta-spring-boot-starter + knife4j-openapi3-spring-boot-starter ${knife4j.version} - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - - org.springdoc - springdoc-openapi-starter-webmvc-ui + springdoc-openapi-ui ${springdoc.version} @@ -177,7 +189,7 @@ com.alibaba - druid-spring-boot-3-starter + druid-spring-boot-starter ${druid.version} @@ -188,12 +200,12 @@ com.baomidou - mybatis-plus-spring-boot3-starter + mybatis-plus-boot-starter ${mybatis-plus.version} com.baomidou - mybatis-plus-jsqlparser + mybatis-plus-jsqlparser-4.9 ${mybatis-plus.version} @@ -203,7 +215,7 @@ com.baomidou - dynamic-datasource-spring-boot3-starter + dynamic-datasource-spring-boot-starter ${dynamic-datasource.version} @@ -253,8 +265,18 @@ org.springframework.boot spring-boot-starter-actuator + + org.redisson + + redisson-spring-data-35 + + + org.redisson + redisson-spring-data-27 + ${redisson.version} + com.dameng @@ -383,14 +405,6 @@ ${spring-boot-admin.version} - - - cn.iocoder.boot - yudao-spring-boot-starter-test - ${revision} - test - - org.mockito mockito-inline @@ -478,11 +492,6 @@ hutool-all ${hutool-5.version} - - org.dromara.hutool - hutool-extra - ${hutool-6.version} - cn.idev.excel @@ -599,12 +608,12 @@ org.jeecgframework.jimureport - jimureport-spring-boot3-starter-fastjson2 + jimureport-spring-boot-starter ${jimureport.version} org.jeecgframework.jimureport - jimubi-spring-boot3-starter + jimubi-spring-boot-starter ${jimubi.version} @@ -654,6 +663,18 @@ org.eclipse.paho.client.mqttv3 ${mqtt.version} + + + + ch.qos.logback + logback-core + ${logback.version} + + + ch.qos.logback + logback-classic + ${logback.version} + diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index 76e674099b9d377a18508c013692cbdc703f9c24..d22b4638b724f550fe2f11783afaf4e58dfc0f75 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -23,7 +23,6 @@ yudao-spring-boot-starter-mq yudao-spring-boot-starter-excel - yudao-spring-boot-starter-test yudao-spring-boot-starter-biz-tenant yudao-spring-boot-starter-biz-data-permission diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index 4ede9eff2db3f5c4a88fc113bf207ca5842736c7..f364df7c3544d26151ecf6c85492ad6aca58d096 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -60,7 +60,7 @@ org.springdoc - springdoc-openapi-starter-webmvc-ui + springdoc-openapi-ui provided diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiAccessLogCommonApi.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiAccessLogCommonApi.java index efa9ca18380ee936ec1ccf4439de298cf5652641..3f4ff25bef23d668e620b4c9fc7e5e207ac0ec29 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiAccessLogCommonApi.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiAccessLogCommonApi.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.framework.common.biz.infra.logger; import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO; -import jakarta.validation.Valid; import org.springframework.scheduling.annotation.Async; +import javax.validation.Valid; + /** * API 访问日志的 API 接口 * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiErrorLogCommonApi.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiErrorLogCommonApi.java index 98743be31f76f9cfd36314632affde84107c3732..8905d0a4893593ea80066ea78b37e67a05e2fbbc 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiErrorLogCommonApi.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/ApiErrorLogCommonApi.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.common.biz.infra.logger; import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; - -import jakarta.validation.Valid; import org.springframework.scheduling.annotation.Async; +import javax.validation.Valid; + /** * API 错误日志的 API 接口 * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiAccessLogCreateReqDTO.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiAccessLogCreateReqDTO.java index b579cd31bc98da7b74ba6703b45e8184b3d10830..d4263576cb06dcee107acdc7dd5a81f879126f9b 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiAccessLogCreateReqDTO.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiAccessLogCreateReqDTO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.framework.common.biz.infra.logger.dto; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; /** diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiErrorLogCreateReqDTO.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiErrorLogCreateReqDTO.java index ae5cd1d4da00d0f6587cfe598d8f11db7be093f5..e5939f53b550dfdc0c9640151d4741dfb8feccc6 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiErrorLogCreateReqDTO.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/infra/logger/dto/ApiErrorLogCreateReqDTO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.framework.common.biz.infra.logger.dto; import lombok.Data; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; /** diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/OperateLogCommonApi.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/OperateLogCommonApi.java index 96753e0f6a18b58c892f3ad8a0dcfda5e59969c9..845181f4ec4661a82b3e8ef9c717a47523712399 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/OperateLogCommonApi.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/OperateLogCommonApi.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.framework.common.biz.system.logger; import cn.iocoder.yudao.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO; -import jakarta.validation.Valid; import org.springframework.scheduling.annotation.Async; +import javax.validation.Valid; + /** * 操作日志 API 接口 * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/dto/OperateLogCreateReqDTO.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/dto/OperateLogCreateReqDTO.java index a2d799025186a15c62b0b5a94d77acb978b05fb8..561697a6a2843b37672f5ee6733f1c395f32f750 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/dto/OperateLogCreateReqDTO.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/logger/dto/OperateLogCreateReqDTO.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.framework.common.biz.system.logger.dto; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + /** * 系统操作日志 Create Request DTO * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/OAuth2TokenCommonApi.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/OAuth2TokenCommonApi.java index c23d936c9a9068e8271b0927b7b9749c611e7067..7c692c8dfd2aea50f36bbea7826b9b6b1099abf2 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/OAuth2TokenCommonApi.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/OAuth2TokenCommonApi.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessToken import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCreateReqDTO; import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenRespDTO; -import jakarta.validation.Valid; +import javax.validation.Valid; /** * OAuth2.0 Token API 接口 diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/dto/OAuth2AccessTokenCreateReqDTO.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/dto/OAuth2AccessTokenCreateReqDTO.java index 72dcd9be8216bf7fb67744e8a55546e38c669d57..12df04a68eb2688b2896d3ad0a425581c7800170 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/dto/OAuth2AccessTokenCreateReqDTO.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/biz/system/oauth2/dto/OAuth2AccessTokenCreateReqDTO.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import lombok.Data; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotNull; import java.io.Serializable; import java.util.List; 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 268d117f95744785489a5c795e29e53f29f6f9f3..97819f993825ec23fefc5ba155f448870f91b3eb 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 @@ -3,9 +3,9 @@ package cn.iocoder.yudao.framework.common.pojo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.Min; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; import java.io.Serializable; @Schema(description="分页参数") diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java index 85a644f1f162adde7c4f626ec52cd9f75ddd243f..3f662a85e7256ad9840d2151b8a26a6924ff9ccc 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/http/HttpUtils.java @@ -7,11 +7,12 @@ import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; -import jakarta.servlet.http.HttpServletRequest; +import lombok.SneakyThrows; import org.springframework.util.StringUtils; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; +import javax.servlet.http.HttpServletRequest; import java.net.URI; import java.net.URLEncoder; import java.nio.charset.Charset; @@ -31,8 +32,9 @@ public class HttpUtils { * @param value 参数 * @return 编码后的参数 */ + @SneakyThrows public static String encodeUtf8(String value) { - return URLEncoder.encode(value, StandardCharsets.UTF_8); + return URLEncoder.encode(value, StandardCharsets.UTF_8.name()); } @SuppressWarnings("unchecked") diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index 905f5d5416a97b54dc5d568cc2f550c17bc4289a..3bffc2fda3d58d7a88dda7bbf2567aed04a5d97a 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -1,16 +1,19 @@ package cn.iocoder.yudao.framework.common.util.servlet; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.servlet.JakartaServletUtil; +import cn.hutool.extra.servlet.ServletUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.MediaType; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; import java.util.Map; /** @@ -29,7 +32,22 @@ public class ServletUtils { @SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码 public static void writeJSON(HttpServletResponse response, Object object) { String content = JsonUtils.toJsonString(object); - JakartaServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); + ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE); + } + + /** + * 返回附件 + * + * @param response 响应 + * @param filename 文件名 + * @param content 附件内容 + */ + public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException { + // 设置 header 和 contentType + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + // 输出附件 + IoUtil.write(response.getOutputStream(), false, content); } /** @@ -67,7 +85,7 @@ public class ServletUtils { if (request == null) { return null; } - return JakartaServletUtil.getClientIP(request); + return ServletUtil.getClientIP(request); } public static boolean isJsonRequest(ServletRequest request) { @@ -77,7 +95,7 @@ public class ServletUtils { public static String getBody(HttpServletRequest request) { // 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取 if (isJsonRequest(request)) { - return JakartaServletUtil.getBody(request); + return ServletUtil.getBody(request); } return null; } @@ -85,21 +103,21 @@ public class ServletUtils { public static byte[] getBodyBytes(HttpServletRequest request) { // 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取 if (isJsonRequest(request)) { - return JakartaServletUtil.getBodyBytes(request); + return ServletUtil.getBodyBytes(request); } return null; } public static String getClientIP(HttpServletRequest request) { - return JakartaServletUtil.getClientIP(request); + return ServletUtil.getClientIP(request); } public static Map getParamMap(HttpServletRequest request) { - return JakartaServletUtil.getParamMap(request); + return ServletUtil.getParamMap(request); } public static Map getHeaderMap(HttpServletRequest request) { - return JakartaServletUtil.getHeaderMap(request); + return ServletUtil.getHeaderMap(request); } } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java index a71ebd30583654ab7240b2428160871409694cd9..436a9e6690732ad65d4ee01cc29afa8724036624 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java @@ -4,10 +4,10 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import org.springframework.util.StringUtils; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; -import jakarta.validation.Validation; -import jakarta.validation.Validator; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validation; +import javax.validation.Validator; import java.util.Set; import java.util.regex.Pattern; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java index 407d01b0a1ba864d76d28940173e4ab39b9f18f7..d27a6431e84809ea07ed7d00caa3b77e3b5316a3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnum.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.framework.common.validation; import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import jakarta.validation.Constraint; -import jakarta.validation.Payload; +import javax.validation.Constraint; +import javax.validation.Payload; import java.lang.annotation.*; @Target({ diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java index b21a92948675f86647b608520c757242cf559819..b0551bd8f2c70bc0fb67c7afae20e57923cc87e1 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumCollectionValidator.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.common.validation; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; import java.util.Arrays; import java.util.Collection; import java.util.Collections; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java index e80eac4bdb3c4c550da2a98fd8753c1848b145da..bd7e287846843796e701ca6d0ffcc143656766b5 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/InEnumValidator.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.framework.common.validation; import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Mobile.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Mobile.java index bcb75f65ee784c081e3b93f5d1ba1424ea9d2e02..4c7cb10ba1a80255ee3c1a9346dd696049eb8ae2 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Mobile.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Mobile.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.common.validation; -import jakarta.validation.Constraint; -import jakarta.validation.Payload; +import javax.validation.Constraint; +import javax.validation.Payload; import java.lang.annotation.*; @Target({ diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/MobileValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/MobileValidator.java index f2def564b1e131f0a6e42b738aea8103ae07886c..0bddfcb213f81dab2723066a842d8e0726e46451 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/MobileValidator.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/MobileValidator.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; public class MobileValidator implements ConstraintValidator { 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 index fa534e1c6bfe90a7957a20ef5ead3f1ee33698d3..910601fd0f12efce8e07d749d28d443d60fc9f34 100644 --- 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 @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.common.validation; -import jakarta.validation.Constraint; -import jakarta.validation.Payload; +import javax.validation.Constraint; +import javax.validation.Payload; import java.lang.annotation.*; @Target({ 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 index 1406e07067bd8ee4b0a93e3c40d734cb32c9a5c1..d214cfeef4574913612019b32c2b6d9a690ccb64 100644 --- 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 @@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.PhoneUtil; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; public class TelephoneValidator implements ConstraintValidator { diff --git a/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java b/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java deleted file mode 100644 index 0e44645bc537be62d545e5b70400299c46decdbb..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-common/src/test/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtilsTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.framework.common.util.collection; - -import lombok.AllArgsConstructor; -import lombok.Data; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.function.BiFunction; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link CollectionUtils} 的单元测试 - */ -public class CollectionUtilsTest { - - @Data - @AllArgsConstructor - private static class Dog { - - private Integer id; - private String name; - private String code; - - } - - @Test - public void testDiffList() { - // 准备参数 - Collection oldList = Arrays.asList( - new Dog(1, "花花", "hh"), - new Dog(2, "旺财", "wc") - ); - Collection newList = Arrays.asList( - new Dog(null, "花花2", "hh"), - new Dog(null, "小白", "xb") - ); - BiFunction sameFunc = (oldObj, newObj) -> { - boolean same = oldObj.getCode().equals(newObj.getCode()); - // 如果相等的情况下,需要设置下 id,后续好更新 - if (same) { - newObj.setId(oldObj.getId()); - } - return same; - }; - - // 调用 - List> result = CollectionUtils.diffList(oldList, newList, sameFunc); - // 断言 - assertEquals(result.size(), 3); - // 断言 create - assertEquals(result.get(0).size(), 1); - assertEquals(result.get(0).get(0), new Dog(null, "小白", "xb")); - // 断言 update - assertEquals(result.get(1).size(), 1); - assertEquals(result.get(1).get(0), new Dog(1, "花花2", "hh")); - // 断言 delete - assertEquals(result.get(2).size(), 1); - assertEquals(result.get(2).get(0), new Dog(2, "旺财", "wc")); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml index 802ff1904eb1066a09f6ee82eed402be9a326b51..6c6e82856987e1c3dc668ffd81b262ce1c8cb292 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/pom.xml @@ -34,12 +34,6 @@ yudao-spring-boot-starter-mybatis - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java deleted file mode 100644 index ba97ede2fcbd9f23662873238ed200dfeddba4e4..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.aop; - -import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import org.aopalliance.intercept.MethodInvocation; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import java.lang.reflect.Method; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; - -/** - * {@link DataPermissionAnnotationInterceptor} 的单元测试 - * - * @author 芋道源码 - */ -public class DataPermissionAnnotationInterceptorTest extends BaseMockitoUnitTest { - - @InjectMocks - private DataPermissionAnnotationInterceptor interceptor; - - @Mock - private MethodInvocation methodInvocation; - - @BeforeEach - public void setUp() { - interceptor.getDataPermissionCache().clear(); - } - - @Test // 无 @DataPermission 注解 - public void testInvoke_none() throws Throwable { - // 参数 - mockMethodInvocation(TestNone.class); - - // 调用 - Object result = interceptor.invoke(methodInvocation); - // 断言 - assertEquals("none", result); - assertEquals(1, interceptor.getDataPermissionCache().size()); - assertTrue(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable()); - } - - @Test // 在 Method 上有 @DataPermission 注解 - public void testInvoke_method() throws Throwable { - // 参数 - mockMethodInvocation(TestMethod.class); - - // 调用 - Object result = interceptor.invoke(methodInvocation); - // 断言 - assertEquals("method", result); - assertEquals(1, interceptor.getDataPermissionCache().size()); - assertFalse(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable()); - } - - @Test // 在 Class 上有 @DataPermission 注解 - public void testInvoke_class() throws Throwable { - // 参数 - mockMethodInvocation(TestClass.class); - - // 调用 - Object result = interceptor.invoke(methodInvocation); - // 断言 - assertEquals("class", result); - assertEquals(1, interceptor.getDataPermissionCache().size()); - assertFalse(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable()); - } - - private void mockMethodInvocation(Class clazz) throws Throwable { - Object targetObject = clazz.newInstance(); - Method method = targetObject.getClass().getMethod("echo"); - when(methodInvocation.getThis()).thenReturn(targetObject); - when(methodInvocation.getMethod()).thenReturn(method); - when(methodInvocation.proceed()).then(invocationOnMock -> method.invoke(targetObject)); - } - - static class TestMethod { - - @DataPermission(enable = false) - public String echo() { - return "method"; - } - - } - - @DataPermission(enable = false) - static class TestClass { - - public String echo() { - return "class"; - } - - } - - static class TestNone { - - public String echo() { - return "none"; - } - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionContextHolderTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionContextHolderTest.java deleted file mode 100644 index 688b92d9f24fa39fb85689bf1e1e719f9a84787e..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionContextHolderTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.aop; - -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.mockito.Mockito.mock; - -/** - * {@link DataPermissionContextHolder} 的单元测试 - * - * @author 芋道源码 - */ -class DataPermissionContextHolderTest { - - @BeforeEach - public void setUp() { - DataPermissionContextHolder.clear(); - } - - @Test - public void testGet() { - // mock 方法 - DataPermission dataPermission01 = mock(DataPermission.class); - DataPermissionContextHolder.add(dataPermission01); - DataPermission dataPermission02 = mock(DataPermission.class); - DataPermissionContextHolder.add(dataPermission02); - - // 调用 - DataPermission result = DataPermissionContextHolder.get(); - // 断言 - assertSame(result, dataPermission02); - } - - @Test - public void testPush() { - // 调用 - DataPermission dataPermission01 = mock(DataPermission.class); - DataPermissionContextHolder.add(dataPermission01); - DataPermission dataPermission02 = mock(DataPermission.class); - DataPermissionContextHolder.add(dataPermission02); - // 断言 - DataPermission first = DataPermissionContextHolder.getAll().get(0); - DataPermission second = DataPermissionContextHolder.getAll().get(1); - assertSame(dataPermission01, first); - assertSame(dataPermission02, second); - } - - @Test - public void testRemove() { - // mock 方法 - DataPermission dataPermission01 = mock(DataPermission.class); - DataPermissionContextHolder.add(dataPermission01); - DataPermission dataPermission02 = mock(DataPermission.class); - DataPermissionContextHolder.add(dataPermission02); - - // 调用 - DataPermission result = DataPermissionContextHolder.remove(); - // 断言 - assertSame(result, dataPermission02); - assertEquals(1, DataPermissionContextHolder.getAll().size()); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java deleted file mode 100644 index c7a0d085e21bf13143109b61c737bbb8f23fc36d..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionRuleHandlerTest.java +++ /dev/null @@ -1,540 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.db; - -import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRule; -import cn.iocoder.yudao.framework.datapermission.core.rule.DataPermissionRuleFactory; -import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.LongValue; -import net.sf.jsqlparser.expression.operators.relational.EqualsTo; -import net.sf.jsqlparser.expression.operators.relational.ExpressionList; -import net.sf.jsqlparser.expression.operators.relational.InExpression; -import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; -import net.sf.jsqlparser.schema.Column; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import java.util.Arrays; -import java.util.Set; - -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -/** - * {@link DataPermissionRuleHandler} 的单元测试 - * 主要复用了 MyBatis Plus 的 TenantLineInnerInterceptorTest 的单元测试 - * 不过它的单元测试不是很规范,考虑到是复用的,所以暂时不进行修改~ - * - * @author 芋道源码 - */ -public class DataPermissionRuleHandlerTest extends BaseMockitoUnitTest { - - @InjectMocks - private DataPermissionRuleHandler handler; - - @Mock - private DataPermissionRuleFactory ruleFactory; - - private DataPermissionInterceptor interceptor; - - @BeforeEach - public void setUp() { - interceptor = new DataPermissionInterceptor(handler); - - // 租户的数据权限规则 - DataPermissionRule tenantRule = new DataPermissionRule() { - - private static final String COLUMN = "tenant_id"; - - @Override - public Set getTableNames() { - return asSet("entity", "entity1", "entity2", "entity3", "t1", "t2", "sys_dict_item", // 支持 MyBatis Plus 的单元测试 - "t_user", "t_role"); // 满足自己的单元测试 - } - - @Override - public Expression getExpression(String tableName, Alias tableAlias) { - Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN); - LongValue value = new LongValue(1L); - return new EqualsTo(column, value); - } - - }; - // 部门的数据权限规则 - DataPermissionRule deptRule = new DataPermissionRule() { - - private static final String COLUMN = "dept_id"; - - @Override - public Set getTableNames() { - return asSet("t_user"); // 满足自己的单元测试 - } - - @Override - public Expression getExpression(String tableName, Alias tableAlias) { - Column column = MyBatisUtils.buildColumn(tableName, tableAlias, COLUMN); - ExpressionList values = new ExpressionList<>(new LongValue(10L), - new LongValue(20L)); - return new InExpression(column, new ParenthesedExpressionList((values))); - } - - }; - // 设置到上下文 - when(ruleFactory.getDataPermissionRule(any())).thenReturn(Arrays.asList(tenantRule, deptRule)); - } - - @Test - void delete() { - assertSql("delete from entity where id = ?", - "DELETE FROM entity WHERE id = ? AND entity.tenant_id = 1"); - } - - @Test - void update() { - assertSql("update entity set name = ? where id = ?", - "UPDATE entity SET name = ? WHERE id = ? AND entity.tenant_id = 1"); - } - - @Test - void selectSingle() { - // 单表 - assertSql("select * from entity where id = ?", - "SELECT * FROM entity WHERE id = ? AND entity.tenant_id = 1"); - - assertSql("select * from entity where id = ? or name = ?", - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1"); - - assertSql("SELECT * FROM entity WHERE (id = ? OR name = ?)", - "SELECT * FROM entity WHERE (id = ? OR name = ?) AND entity.tenant_id = 1"); - - /* not */ - assertSql("SELECT * FROM entity WHERE not (id = ? OR name = ?)", - "SELECT * FROM entity WHERE NOT (id = ? OR name = ?) AND entity.tenant_id = 1"); - } - - @Test - void selectSubSelectIn() { - /* in */ - assertSql("SELECT * FROM entity e WHERE e.id IN (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE e.id IN (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - // 在最前 - assertSql("SELECT * FROM entity e WHERE e.id IN " + - "(select e1.id from entity1 e1 where e1.id = ?) and e.id = ?", - "SELECT * FROM entity e WHERE e.id IN " + - "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ? AND e.tenant_id = 1"); - // 在最后 - assertSql("SELECT * FROM entity e WHERE e.id = ? and e.id IN " + - "(select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE e.id = ? AND e.id IN " + - "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - // 在中间 - assertSql("SELECT * FROM entity e WHERE e.id = ? and e.id IN " + - "(select e1.id from entity1 e1 where e1.id = ?) and e.id = ?", - "SELECT * FROM entity e WHERE e.id = ? AND e.id IN " + - "(SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ? AND e.tenant_id = 1"); - } - - @Test - void selectSubSelectEq() { - /* = */ - assertSql("SELECT * FROM entity e WHERE e.id = (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - } - - @Test - void selectSubSelectInnerNotEq() { - /* inner not = */ - assertSql("SELECT * FROM entity e WHERE not (e.id = (select e1.id from entity1 e1 where e1.id = ?))", - "SELECT * FROM entity e WHERE NOT (e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1)) AND e.tenant_id = 1"); - - assertSql("SELECT * FROM entity e WHERE not (e.id = (select e1.id from entity1 e1 where e1.id = ?) and e.id = ?)", - "SELECT * FROM entity e WHERE NOT (e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.id = ?) AND e.tenant_id = 1"); - } - - @Test - void selectSubSelectExists() { - /* EXISTS */ - assertSql("SELECT * FROM entity e WHERE EXISTS (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE EXISTS (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - - - /* NOT EXISTS */ - assertSql("SELECT * FROM entity e WHERE NOT EXISTS (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE NOT EXISTS (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - } - - @Test - void selectSubSelect() { - /* >= */ - assertSql("SELECT * FROM entity e WHERE e.id >= (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE e.id >= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - - - /* <= */ - assertSql("SELECT * FROM entity e WHERE e.id <= (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE e.id <= (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - - - /* <> */ - assertSql("SELECT * FROM entity e WHERE e.id <> (select e1.id from entity1 e1 where e1.id = ?)", - "SELECT * FROM entity e WHERE e.id <> (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1"); - } - - @Test - void selectFromSelect() { - assertSql("SELECT * FROM (select e.id from entity e WHERE e.id = (select e1.id from entity1 e1 where e1.id = ?))", - "SELECT * FROM (SELECT e.id FROM entity e WHERE e.id = (SELECT e1.id FROM entity1 e1 WHERE e1.id = ? AND e1.tenant_id = 1) AND e.tenant_id = 1)"); - } - - @Test - void selectBodySubSelect() { - assertSql("select t1.col1,(select t2.col2 from t2 t2 where t1.col1=t2.col1) from t1 t1", - "SELECT t1.col1, (SELECT t2.col2 FROM t2 t2 WHERE t1.col1 = t2.col1 AND t2.tenant_id = 1) FROM t1 t1 WHERE t1.tenant_id = 1"); - } - - @Test - void selectLeftJoin() { - // left join - assertSql("SELECT * FROM entity e " + - "left join entity1 e1 on e1.id = e.id " + - "WHERE e.id = ? OR e.name = ?", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "left join entity1 e1 on e1.id = e.id " + - "WHERE (e.id = ? OR e.name = ?)", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "left join entity1 e1 on e1.id = e.id " + - "left join entity2 e2 on e1.id = e2.id", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " + - "WHERE e.tenant_id = 1"); - } - - @Test - void selectRightJoin() { - // right join - assertSql("SELECT * FROM entity e " + - "right join entity1 e1 on e1.id = e.id", - "SELECT * FROM entity e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + - "WHERE e1.tenant_id = 1"); - - assertSql("SELECT * FROM with_as_1 e " + - "right join entity1 e1 on e1.id = e.id", - "SELECT * FROM with_as_1 e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id " + - "WHERE e1.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "right join entity1 e1 on e1.id = e.id " + - "WHERE e.id = ? OR e.name = ?", - "SELECT * FROM entity e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "right join entity1 e1 on e1.id = e.id " + - "right join entity2 e2 on e1.id = e2.id ", - "SELECT * FROM entity e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + - "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1 " + - "WHERE e2.tenant_id = 1"); - } - - @Test - void selectMixJoin() { - assertSql("SELECT * FROM entity e " + - "right join entity1 e1 on e1.id = e.id " + - "left join entity2 e2 on e1.id = e2.id", - "SELECT * FROM entity e " + - "RIGHT JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 " + - "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1 " + - "WHERE e1.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "left join entity1 e1 on e1.id = e.id " + - "right join entity2 e2 on e1.id = e2.id", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 " + - "WHERE e2.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "left join entity1 e1 on e1.id = e.id " + - "inner join entity2 e2 on e1.id = e2.id", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "INNER JOIN entity2 e2 ON e1.id = e2.id AND e.tenant_id = 1 AND e2.tenant_id = 1"); - } - - - @Test - void selectJoinSubSelect() { - assertSql("select * from (select * from entity) e1 " + - "left join entity2 e2 on e1.id = e2.id", - "SELECT * FROM (SELECT * FROM entity WHERE entity.tenant_id = 1) e1 " + - "LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1"); - - assertSql("select * from entity1 e1 " + - "left join (select * from entity2) e2 " + - "on e1.id = e2.id", - "SELECT * FROM entity1 e1 " + - "LEFT JOIN (SELECT * FROM entity2 WHERE entity2.tenant_id = 1) e2 " + - "ON e1.id = e2.id " + - "WHERE e1.tenant_id = 1"); - } - - @Test - void selectSubJoin() { - - assertSql("select * FROM " + - "(entity1 e1 right JOIN entity2 e2 ON e1.id = e2.id)", - "SELECT * FROM " + - "(entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " + - "WHERE e2.tenant_id = 1"); - - assertSql("select * FROM " + - "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id)", - "SELECT * FROM " + - "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + - "WHERE e1.tenant_id = 1"); - - - assertSql("select * FROM " + - "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id) " + - "right join entity3 e3 on e1.id = e3.id", - "SELECT * FROM " + - "(entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + - "RIGHT JOIN entity3 e3 ON e1.id = e3.id AND e1.tenant_id = 1 " + - "WHERE e3.tenant_id = 1"); - - - assertSql("select * FROM entity e " + - "LEFT JOIN (entity1 e1 right join entity2 e2 ON e1.id = e2.id) " + - "on e.id = e2.id", - "SELECT * FROM entity e " + - "LEFT JOIN (entity1 e1 RIGHT JOIN entity2 e2 ON e1.id = e2.id AND e1.tenant_id = 1) " + - "ON e.id = e2.id AND e2.tenant_id = 1 " + - "WHERE e.tenant_id = 1"); - - assertSql("select * FROM entity e " + - "LEFT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " + - "on e.id = e2.id", - "SELECT * FROM entity e " + - "LEFT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + - "ON e.id = e2.id AND e1.tenant_id = 1 " + - "WHERE e.tenant_id = 1"); - - assertSql("select * FROM entity e " + - "RIGHT JOIN (entity1 e1 left join entity2 e2 ON e1.id = e2.id) " + - "on e.id = e2.id", - "SELECT * FROM entity e " + - "RIGHT JOIN (entity1 e1 LEFT JOIN entity2 e2 ON e1.id = e2.id AND e2.tenant_id = 1) " + - "ON e.id = e2.id AND e.tenant_id = 1 " + - "WHERE e1.tenant_id = 1"); - } - - - @Test - void selectLeftJoinMultipleTrailingOn() { - // 多个 on 尾缀的 - assertSql("SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 " + - "LEFT JOIN entity2 e2 ON e2.id = e1.id " + - "ON e1.id = e.id " + - "WHERE (e.id = ? OR e.NAME = ?)", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 " + - "LEFT JOIN entity2 e2 ON e2.id = e1.id AND e2.tenant_id = 1 " + - "ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.NAME = ?) AND e.tenant_id = 1"); - - assertSql("SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 " + - "LEFT JOIN with_as_A e2 ON e2.id = e1.id " + - "ON e1.id = e.id " + - "WHERE (e.id = ? OR e.NAME = ?)", - "SELECT * FROM entity e " + - "LEFT JOIN entity1 e1 " + - "LEFT JOIN with_as_A e2 ON e2.id = e1.id " + - "ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.NAME = ?) AND e.tenant_id = 1"); - } - - @Test - void selectInnerJoin() { - // inner join - assertSql("SELECT * FROM entity e " + - "inner join entity1 e1 on e1.id = e.id " + - "WHERE e.id = ? OR e.name = ?", - "SELECT * FROM entity e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " + - "WHERE e.id = ? OR e.name = ?"); - - assertSql("SELECT * FROM entity e " + - "inner join entity1 e1 on e1.id = e.id " + - "WHERE (e.id = ? OR e.name = ?)", - "SELECT * FROM entity e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?)"); - - // 隐式内连接 - assertSql("SELECT * FROM entity,entity1 " + - "WHERE entity.id = entity1.id", - "SELECT * FROM entity, entity1 " + - "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1"); - - // 隐式内连接 - assertSql("SELECT * FROM entity a, with_as_entity1 b " + - "WHERE a.id = b.id", - "SELECT * FROM entity a, with_as_entity1 b " + - "WHERE a.id = b.id AND a.tenant_id = 1"); - - assertSql("SELECT * FROM with_as_entity a, with_as_entity1 b " + - "WHERE a.id = b.id", - "SELECT * FROM with_as_entity a, with_as_entity1 b " + - "WHERE a.id = b.id"); - - // SubJoin with 隐式内连接 - assertSql("SELECT * FROM (entity,entity1) " + - "WHERE entity.id = entity1.id", - "SELECT * FROM (entity, entity1) " + - "WHERE entity.id = entity1.id " + - "AND entity.tenant_id = 1 AND entity1.tenant_id = 1"); - - assertSql("SELECT * FROM ((entity,entity1),entity2) " + - "WHERE entity.id = entity1.id and entity.id = entity2.id", - "SELECT * FROM ((entity, entity1), entity2) " + - "WHERE entity.id = entity1.id AND entity.id = entity2.id " + - "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1"); - - assertSql("SELECT * FROM (entity,(entity1,entity2)) " + - "WHERE entity.id = entity1.id and entity.id = entity2.id", - "SELECT * FROM (entity, (entity1, entity2)) " + - "WHERE entity.id = entity1.id AND entity.id = entity2.id " + - "AND entity.tenant_id = 1 AND entity1.tenant_id = 1 AND entity2.tenant_id = 1"); - - // 沙雕的括号写法 - assertSql("SELECT * FROM (((entity,entity1))) " + - "WHERE entity.id = entity1.id", - "SELECT * FROM (((entity, entity1))) " + - "WHERE entity.id = entity1.id " + - "AND entity.tenant_id = 1 AND entity1.tenant_id = 1"); - - } - - - @Test - void selectWithAs() { - assertSql("with with_as_A as (select * from entity) select * from with_as_A", - "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A"); - } - - - @Test - void selectIgnoreTable() { - assertSql(" SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)", - "SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id AND item.tenant_id = 1 WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)"); - } - - private void assertSql(String sql, String targetSql) { - assertEquals(targetSql, interceptor.parserSingle(sql, null)); - } - - // ========== 额外的测试 ========== - - @Test - public void testSelectSingle() { - // 单表 - assertSql("select * from t_user where id = ?", - "SELECT * FROM t_user WHERE id = ? AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); - - assertSql("select * from t_user where id = ? or name = ?", - "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); - - assertSql("SELECT * FROM t_user WHERE (id = ? OR name = ?)", - "SELECT * FROM t_user WHERE (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); - - /* not */ - assertSql("SELECT * FROM t_user WHERE not (id = ? OR name = ?)", - "SELECT * FROM t_user WHERE NOT (id = ? OR name = ?) AND t_user.tenant_id = 1 AND t_user.dept_id IN (10, 20)"); - } - - @Test - public void testSelectLeftJoin() { - // left join - assertSql("SELECT * FROM t_user e " + - "left join t_role e1 on e1.id = e.id " + - "WHERE e.id = ? OR e.name = ?", - "SELECT * FROM t_user e " + - "LEFT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); - - // 条件 e.id = ? OR e.name = ? 带括号 - assertSql("SELECT * FROM t_user e " + - "left join t_role e1 on e1.id = e.id " + - "WHERE (e.id = ? OR e.name = ?)", - "SELECT * FROM t_user e " + - "LEFT JOIN t_role e1 ON e1.id = e.id AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?) AND e.tenant_id = 1 AND e.dept_id IN (10, 20)"); - } - - @Test - public void testSelectRightJoin() { - // right join - assertSql("SELECT * FROM t_user e " + - "right join t_role e1 on e1.id = e.id " + - "WHERE e.id = ? OR e.name = ?", - "SELECT * FROM t_user e " + - "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " + - "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1"); - - // 条件 e.id = ? OR e.name = ? 带括号 - assertSql("SELECT * FROM t_user e " + - "right join t_role e1 on e1.id = e.id " + - "WHERE (e.id = ? OR e.name = ?)", - "SELECT * FROM t_user e " + - "RIGHT JOIN t_role e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) " + - "WHERE (e.id = ? OR e.name = ?) AND e1.tenant_id = 1"); - } - - @Test - public void testSelectInnerJoin() { - // inner join - assertSql("SELECT * FROM t_user e " + - "inner join entity1 e1 on e1.id = e.id " + - "WHERE e.id = ? OR e.name = ?", - "SELECT * FROM t_user e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " + - "WHERE e.id = ? OR e.name = ?"); - - // 条件 e.id = ? OR e.name = ? 带括号 - assertSql("SELECT * FROM t_user e " + - "inner join entity1 e1 on e1.id = e.id " + - "WHERE (e.id = ? OR e.name = ?)", - "SELECT * FROM t_user e " + - "INNER JOIN entity1 e1 ON e1.id = e.id AND e.tenant_id = 1 AND e.dept_id IN (10, 20) AND e1.tenant_id = 1 " + - "WHERE (e.id = ? OR e.name = ?)"); - - // 没有 On 的 inner join - assertSql("SELECT * FROM entity,entity1 " + - "WHERE entity.id = entity1.id", - "SELECT * FROM entity, entity1 " + - "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1"); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java deleted file mode 100644 index 17dddc929e6380eb0ccb533c05f142e557895653..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImplTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.rule; - -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Spy; -import org.springframework.core.annotation.AnnotationUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link DataPermissionRuleFactoryImpl} 单元测试 - * - * @author 芋道源码 - */ -class DataPermissionRuleFactoryImplTest extends BaseMockitoUnitTest { - - @InjectMocks - private DataPermissionRuleFactoryImpl dataPermissionRuleFactory; - - @Spy - private List rules = Arrays.asList(new DataPermissionRule01(), - new DataPermissionRule02()); - - @BeforeEach - public void setUp() { - DataPermissionContextHolder.clear(); - } - - @Test - public void testGetDataPermissionRule_02() { - // 准备参数 - String mappedStatementId = randomString(); - - // 调用 - List result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId); - // 断言 - assertSame(rules, result); - } - - @Test - public void testGetDataPermissionRule_03() { - // 准备参数 - String mappedStatementId = randomString(); - // mock 方法 - DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass03.class, DataPermission.class)); - - // 调用 - List result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId); - // 断言 - assertTrue(result.isEmpty()); - } - - @Test - public void testGetDataPermissionRule_04() { - // 准备参数 - String mappedStatementId = randomString(); - // mock 方法 - DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass04.class, DataPermission.class)); - - // 调用 - List result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId); - // 断言 - assertEquals(1, result.size()); - assertEquals(DataPermissionRule01.class, result.get(0).getClass()); - } - - @Test - public void testGetDataPermissionRule_05() { - // 准备参数 - String mappedStatementId = randomString(); - // mock 方法 - DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass05.class, DataPermission.class)); - - // 调用 - List result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId); - // 断言 - assertEquals(1, result.size()); - assertEquals(DataPermissionRule02.class, result.get(0).getClass()); - } - - @Test - public void testGetDataPermissionRule_06() { - // 准备参数 - String mappedStatementId = randomString(); - // mock 方法 - DataPermissionContextHolder.add(AnnotationUtils.findAnnotation(TestClass06.class, DataPermission.class)); - - // 调用 - List result = dataPermissionRuleFactory.getDataPermissionRule(mappedStatementId); - // 断言 - assertSame(rules, result); - } - - @DataPermission(enable = false) - static class TestClass03 {} - - @DataPermission(includeRules = DataPermissionRule01.class) - static class TestClass04 {} - - @DataPermission(excludeRules = DataPermissionRule01.class) - static class TestClass05 {} - - @DataPermission - static class TestClass06 {} - - static class DataPermissionRule01 implements DataPermissionRule { - - @Override - public Set getTableNames() { - return null; - } - - @Override - public Expression getExpression(String tableName, Alias tableAlias) { - return null; - } - - } - - static class DataPermissionRule02 implements DataPermissionRule { - - @Override - public Set getTableNames() { - return null; - } - - @Override - public Expression getExpression(String tableName, Alias tableAlias) { - return null; - } - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java deleted file mode 100644 index 7faae00877d69d85e40c21a91e74b8c3970ca1b1..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRuleTest.java +++ /dev/null @@ -1,238 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.rule.dept; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi; -import cn.iocoder.yudao.framework.common.biz.system.permission.dto.DeptDataPermissionRespDTO; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.util.collection.SetUtils; -import cn.iocoder.yudao.framework.security.core.LoginUser; -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import net.sf.jsqlparser.expression.Alias; -import net.sf.jsqlparser.expression.Expression; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedStatic; - -import java.util.Map; - -import static cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule.EXPRESSION_NULL; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.same; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.when; - -/** - * {@link DeptDataPermissionRule} 的单元测试 - * - * @author 芋道源码 - */ -class DeptDataPermissionRuleTest extends BaseMockitoUnitTest { - - @InjectMocks - private DeptDataPermissionRule rule; - - @Mock - private PermissionCommonApi permissionApi; - - @BeforeEach - @SuppressWarnings("unchecked") - public void setUp() { - // 清空 rule - rule.getTableNames().clear(); - ((Map) ReflectUtil.getFieldValue(rule, "deptColumns")).clear(); - ((Map) ReflectUtil.getFieldValue(rule, "deptColumns")).clear(); - } - - @Test // 无 LoginUser - public void testGetExpression_noLoginUser() { - // 准备参数 - String tableName = randomString(); - Alias tableAlias = new Alias(randomString()); - // mock 方法 - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertNull(expression); - } - - @Test // 无数据权限时 - public void testGetExpression_noDeptDataPermission() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法 - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(permissionApi 返回 null) - when(permissionApi.getDeptDataPermission(eq(loginUser.getId()))).thenReturn(null); - - // 调用 - NullPointerException exception = assertThrows(NullPointerException.class, - () -> rule.getExpression(tableName, tableAlias)); - // 断言 - assertEquals("LoginUser(1) Table(t_user/u) 未返回数据权限", exception.getMessage()); - } - } - - @Test // 全部数据权限 - public void testGetExpression_allDeptDataPermission() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法(LoginUser) - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(DeptDataPermissionRespDTO) - DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO().setAll(true); - when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertNull(expression); - assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); - } - } - - @Test // 即不能查看部门,又不能查看自己,则说明 100% 无权限 - public void testGetExpression_noDept_noSelf() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法(LoginUser) - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(DeptDataPermissionRespDTO) - DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO(); - when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertEquals("null = null", expression.toString()); - assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); - } - } - - @Test // 拼接 Dept 和 User 的条件(字段都不符合) - public void testGetExpression_noDeptColumn_noSelfColumn() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法(LoginUser) - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(DeptDataPermissionRespDTO) - DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() - .setDeptIds(SetUtils.asSet(10L, 20L)).setSelf(true); - when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertSame(EXPRESSION_NULL, expression); - assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); - } - } - - @Test // 拼接 Dept 和 User 的条件(self 符合) - public void testGetExpression_noDeptColumn_yesSelfColumn() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法(LoginUser) - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(DeptDataPermissionRespDTO) - DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() - .setSelf(true); - when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); - // 添加 user 字段配置 - rule.addUserColumn("t_user", "id"); - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertEquals("u.id = 1", expression.toString()); - assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); - } - } - - @Test // 拼接 Dept 和 User 的条件(dept 符合) - public void testGetExpression_yesDeptColumn_noSelfColumn() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法(LoginUser) - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(DeptDataPermissionRespDTO) - DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() - .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)); - when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); - // 添加 dept 字段配置 - rule.addDeptColumn("t_user", "dept_id"); - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertEquals("u.dept_id IN (10, 20)", expression.toString()); - assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); - } - } - - @Test // 拼接 Dept 和 User 的条件(dept + self 符合) - public void testGetExpression_yesDeptColumn_yesSelfColumn() { - try (MockedStatic securityFrameworkUtilsMock - = mockStatic(SecurityFrameworkUtils.class)) { - // 准备参数 - String tableName = "t_user"; - Alias tableAlias = new Alias("u"); - // mock 方法(LoginUser) - LoginUser loginUser = randomPojo(LoginUser.class, o -> o.setId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - securityFrameworkUtilsMock.when(SecurityFrameworkUtils::getLoginUser).thenReturn(loginUser); - // mock 方法(DeptDataPermissionRespDTO) - DeptDataPermissionRespDTO deptDataPermission = new DeptDataPermissionRespDTO() - .setDeptIds(CollUtil.newLinkedHashSet(10L, 20L)).setSelf(true); - when(permissionApi.getDeptDataPermission(same(1L))).thenReturn(deptDataPermission); - // 添加 user 字段配置 - rule.addUserColumn("t_user", "id"); - // 添加 dept 字段配置 - rule.addDeptColumn("t_user", "dept_id"); - - // 调用 - Expression expression = rule.getExpression(tableName, tableAlias); - // 断言 - assertEquals("(u.dept_id IN (10, 20) OR u.id = 1)", expression.toString()); - assertSame(deptDataPermission, loginUser.getContext(DeptDataPermissionRule.CONTEXT_KEY, DeptDataPermissionRespDTO.class)); - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtilsTest.java deleted file mode 100644 index 1cc57c2586e100cb9dc672ae2d2ff262f6aea619..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/util/DataPermissionUtilsTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.framework.datapermission.core.util; - -import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class DataPermissionUtilsTest { - - @Test - public void testExecuteIgnore() { - DataPermissionUtils.executeIgnore(() -> assertFalse(DataPermissionContextHolder.get().enable())); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml index bc800c85d0d2c2ff9f14334c4323e2c4db49af9b..46026d4bc5eaac25e301f3c2349e32f0c51a210f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/pom.xml @@ -43,12 +43,6 @@ provided - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java deleted file mode 100644 index cc23819c49fefa14d9492d71bd9fe58af9965973..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/AreaUtilsTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.framework.ip.core.utils; - - -import cn.iocoder.yudao.framework.ip.core.Area; -import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link AreaUtils} 的单元测试 - * - * @author 芋道源码 - */ -public class AreaUtilsTest { - - @Test - public void testGetArea() { - // 调用:北京 - Area area = AreaUtils.getArea(110100); - // 断言 - assertEquals(area.getId(), 110100); - assertEquals(area.getName(), "北京市"); - assertEquals(area.getType(), AreaTypeEnum.CITY.getType()); - assertEquals(area.getParent().getId(), 110000); - assertEquals(area.getChildren().size(), 16); - } - - @Test - public void testFormat() { - assertEquals(AreaUtils.format(110105), "北京市 北京市 朝阳区"); - assertEquals(AreaUtils.format(1), "中国"); - assertEquals(AreaUtils.format(2), "蒙古"); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java deleted file mode 100644 index 761a1aa63feadccb042cfedd6713bee096cf0b6c..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/test/java/cn/iocoder/yudao/framework/ip/core/utils/IPUtilsTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.framework.ip.core.utils; - -import cn.iocoder.yudao.framework.ip.core.Area; -import org.junit.jupiter.api.Test; -import org.lionsoul.ip2region.xdb.Searcher; - - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * {@link IPUtils} 的单元测试 - * - * @author wanglhup - */ -public class IPUtilsTest { - - @Test - public void testGetAreaId_string() { - // 120.202.4.0|120.202.4.255|420600 - Integer areaId = IPUtils.getAreaId("120.202.4.50"); - assertEquals(420600, areaId); - } - - @Test - public void testGetAreaId_long() throws Exception { - // 120.203.123.0|120.203.133.255|360900 - long ip = Searcher.checkIP("120.203.123.250"); - Integer areaId = IPUtils.getAreaId(ip); - assertEquals(360900, areaId); - } - - @Test - public void testGetArea_string() { - // 120.202.4.0|120.202.4.255|420600 - Area area = IPUtils.getArea("120.202.4.50"); - assertEquals("襄阳市", area.getName()); - } - - @Test - public void testGetArea_long() throws Exception { - // 120.203.123.0|120.203.133.255|360900 - long ip = Searcher.checkIP("120.203.123.252"); - Area area = IPUtils.getArea(ip); - assertEquals("宜春市", area.getName()); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-tenant/pom.xml index c1a537613ed3adfc8d3ab7c6420d1084e5e170cb..b831767fc6ca913f754aa331743bcacd369d35d3 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/pom.xml @@ -66,13 +66,6 @@ true - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - - com.google.guava 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 b79e09203d27b3a1f8debee56ef44262b461f447..e91a23617893d717013de935868235fa31b0fdea 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 @@ -22,7 +22,6 @@ import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; -import jakarta.annotation.Resource; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -44,7 +43,11 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.util.pattern.PathPattern; -import java.util.*; +import javax.annotation.Resource; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java index 5858ec73a63b20417356e4a3e3e9964de9d537de..b68aea77ca485ae056e1477746c00ad88a15a919 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java @@ -12,13 +12,13 @@ import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.util.AntPathMatcher; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Objects; import java.util.Set; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantContextWebFilter.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantContextWebFilter.java index 41b7b4d7104a8a4977f4d53ffeb03f810ffb59b0..8e37727d9d2ca54c82c9e6f51dd39b7e340ab768 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantContextWebFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantContextWebFilter.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantVisitContextInterceptor.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantVisitContextInterceptor.java index 9ac70d83132c94ffe831e6b1251c2c239e5af753..c0a760ed200a8fde8cb0ba0f151715175fcc2903 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantVisitContextInterceptor.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/web/TenantVisitContextInterceptor.java @@ -8,12 +8,13 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.tenant.config.TenantProperties; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerInterceptor; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; @RequiredArgsConstructor diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java index de330fdc058e52e88bda7d998302b081d6622355..059d8f97febb8b270ea3d487622dcd073f17effc 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/org/springframework/messaging/handler/invocation/InvocableHandlerMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,6 @@ package org.springframework.messaging.handler.invocation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.Arrays; - import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import org.springframework.core.DefaultParameterNameDiscoverer; @@ -32,6 +27,11 @@ import org.springframework.messaging.Message; import org.springframework.messaging.handler.HandlerMethod; import org.springframework.util.ObjectUtils; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Arrays; + import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; /** @@ -50,12 +50,10 @@ public class InvocableHandlerMethod extends HandlerMethod { private static final Object[] EMPTY_ARGS = new Object[0]; - private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); - /** * Create an instance from a {@code HandlerMethod}. */ @@ -83,7 +81,6 @@ public class InvocableHandlerMethod extends HandlerMethod { super(bean, methodName, parameterTypes); } - /** * Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values. */ @@ -94,13 +91,12 @@ public class InvocableHandlerMethod extends HandlerMethod { /** * Set the ParameterNameDiscoverer for resolving parameter names when needed * (e.g. default request attribute name). - *

Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}. + *

Default is a {@link DefaultParameterNameDiscoverer}. */ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; } - /** * Invoke the method after resolving its argument values in the context of the given message. *

Argument values are commonly resolved through @@ -204,21 +200,20 @@ public class InvocableHandlerMethod extends HandlerMethod { } catch (IllegalArgumentException ex) { assertTargetBean(getBridgedMethod(), getBean(), args); - String text = (ex.getMessage() == null || ex.getCause() instanceof NullPointerException) ? - "Illegal argument": ex.getMessage(); + String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument"); throw new IllegalStateException(formatInvokeError(text, args), ex); } catch (InvocationTargetException ex) { // Unwrap for HandlerExceptionResolvers ... Throwable targetException = ex.getTargetException(); - if (targetException instanceof RuntimeException runtimeException) { - throw runtimeException; + if (targetException instanceof RuntimeException) { + throw (RuntimeException) targetException; } - else if (targetException instanceof Error error) { - throw error; + else if (targetException instanceof Error) { + throw (Error) targetException; } - else if (targetException instanceof Exception exception) { - throw exception; + else if (targetException instanceof Exception) { + throw (Exception) targetException; } else { throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException); @@ -230,8 +225,7 @@ public class InvocableHandlerMethod extends HandlerMethod { return new AsyncResultMethodParameter(returnValue); } - - private class AsyncResultMethodParameter extends AnnotatedMethodParameter { + private class AsyncResultMethodParameter extends HandlerMethodParameter { @Nullable private final Object returnValue; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml index b1218183cb3c7554a7abac651657b118845bdb60..0249c8841abcd18b39cc1435337113d84ce4020e 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -62,13 +62,6 @@ yudao-spring-boot-starter-biz-ip true - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java index de7498775ce27ca24e4f88d23e3a53a0cbb1b00b..4e52edf443ca7048c7ab9600607eab0df16f6cbe 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java @@ -1,13 +1,8 @@ package cn.iocoder.yudao.framework.dict.validation; -import jakarta.validation.Constraint; -import jakarta.validation.Payload; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; @Target({ ElementType.METHOD, diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java index a7184b066aed7064f3328cacc44dfeb3aed6da11..7d34b583be09e49a9bec7936eb0b34757b049238 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.dict.validation; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; import java.util.Collection; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java index b67f017750251f0bccd41012ffc4ab9f1e7244d9..d46238040a4ae7f1a607ec0f6df11553bdbf6871 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.dict.validation; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; -import jakarta.validation.ConstraintValidator; -import jakarta.validation.ConstraintValidatorContext; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; import java.util.List; public class InDictValidator implements ConstraintValidator { diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index f05d3e51e5448e15b45dffb4abeb15bc4a27ec6e..3eaafec18f3b4ac61f04941384611f1f2c574020 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -5,9 +5,9 @@ import cn.idev.excel.converters.longconverter.LongStringConverter; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtilsTest.java deleted file mode 100644 index fa0d172c966968edda36838fa58755867b4840c9..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/dict/core/util/DictFrameworkUtilsTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package cn.iocoder.yudao.framework.dict.core.util; - -import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi; -import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO; -import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; - -import java.util.List; - -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -/** - * {@link DictFrameworkUtils} 的单元测试 - */ -public class DictFrameworkUtilsTest extends BaseMockitoUnitTest { - - @Mock - private DictDataCommonApi dictDataApi; - - @BeforeEach - public void setUp() { - DictFrameworkUtils.init(dictDataApi); - DictFrameworkUtils.clearCache(); - } - - @Test - public void testParseDictDataLabel() { - // mock 数据 - List dictDatas = List.of( - randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("猫")), - randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel("狗")) - ); - // mock 方法 - when(dictDataApi.getDictDataList(eq("animal"))).thenReturn(dictDatas); - - // 断言返回值 - assertEquals("狗", DictFrameworkUtils.parseDictDataLabel("animal", "dog")); - } - - @Test - public void testParseDictDataValue() { - // mock 数据 - List dictDatas = List.of( - randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("猫")), - randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel("狗")) - ); - // mock 方法 - when(dictDataApi.getDictDataList(eq("animal"))).thenReturn(dictDatas); - - // 断言返回值 - assertEquals("dog", DictFrameworkUtils.parseDictDataValue("animal", "狗")); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/handler/JobHandlerInvoker.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/handler/JobHandlerInvoker.java index d9b299056c0898fc647a6551b77c85b980b298b5..736126fec6486edca768396c7a45bfb7dddbcef3 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/handler/JobHandlerInvoker.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/handler/JobHandlerInvoker.java @@ -13,8 +13,9 @@ import org.quartz.PersistJobDataAfterExecution; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; -import jakarta.annotation.Resource; +import javax.annotation.Resource; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage; diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/service/JobLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/service/JobLogFrameworkService.java index cd99cadba9c45ee816485d3844b3eb20d3243106..418dbfcd62bc567cc42b4b012fa35e74a39a4c5c 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/service/JobLogFrameworkService.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/core/service/JobLogFrameworkService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.quartz.core.service; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; /** diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java index 596b5167570a4c02bcca48d631443a14cd90350e..2f8aa704054f8844e19f424a4c39a7fd98b06bbc 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java @@ -18,7 +18,7 @@ import org.springframework.context.annotation.Bean; @ConditionalOnClass(name = { "org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer", // 来自 apm-toolkit-opentracing.jar // "io.opentracing.Tracer", // 来自 opentracing-api.jar - "jakarta.servlet.Filter" + "javax.servlet.Filter" }) @EnableConfigurationProperties(TracerProperties.class) @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java index e8d7ca1b159a0db37cb490b962ad375bce124d93..91ac30fd598d1fcd71abe9bd72f1d04599c115d7 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/core/filter/TraceFilter.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.tracer.core.filter; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 3272059d85e94fc63bde30e68d80feaa9dbcfa74..3f6c7ed4b59836c9ee5930dae316291066eb9ba5 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -71,25 +71,19 @@ com.alibaba - druid-spring-boot-3-starter + druid-spring-boot-starter com.baomidou - mybatis-plus-spring-boot3-starter + mybatis-plus-boot-starter com.baomidou - mybatis-plus-jsqlparser + mybatis-plus-jsqlparser-4.9 com.baomidou - dynamic-datasource-spring-boot3-starter - - - org.springframework.boot - spring-boot-starter-undertow - - + dynamic-datasource-spring-boot-starter diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java index 879a19aae373eaa791209aaa5899f6f3a3991ae5..7032b48376d01cec7494cc38e9cf3119b8644937 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/config/YudaoDataSourceAutoConfiguration.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.datasource.config; import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter; -import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties; +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/core/filter/DruidAdRemoveFilter.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/core/filter/DruidAdRemoveFilter.java index 18a86a8f48a2ae9b0bf583f482cd089d4c8c487f..78e8a3e64a1fa05c9fdc50e28c0792bb347c2d6d 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/core/filter/DruidAdRemoveFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/datasource/core/filter/DruidAdRemoveFilter.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.datasource.core.filter; import com.alibaba.druid.util.Utils; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java index 56f51d91df241e0213ec314ac5188b3826eff8ed..89b35f9266b269ae5bcd67ec85a43928a87f6fbe 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java @@ -53,14 +53,14 @@ public class MyBatisUtils { if (CollUtil.isEmpty(sortingFields)) { return; } - if (wrapper instanceof QueryWrapper) { + if (wrapper instanceof QueryWrapper) { QueryWrapper query = (QueryWrapper) wrapper; for (SortingField sortingField : sortingFields) { query.orderBy(true, SortingField.ORDER_ASC.equals(sortingField.getOrder()), StrUtil.toUnderlineCase(sortingField.getField())); } - } else if (wrapper instanceof LambdaQueryWrapper) { + } else if (wrapper instanceof LambdaQueryWrapper) { // LambdaQueryWrapper 不直接支持字符串字段排序,使用 last 方法拼接 ORDER BY LambdaQueryWrapper lambdaQuery = (LambdaQueryWrapper) wrapper; StringBuilder orderBy = new StringBuilder(); diff --git a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml index 7e7279eb84dbdc5fd21223039e1578627dddd91f..7d387eb8e645884b966045dfcd9ef7de960de2e1 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml @@ -35,13 +35,6 @@ lock4j-redisson-spring-boot-starter true - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java index 665d327e900478da58180242f62bc0a76fa253e8..50b4a2c1948b90fe655d6a0849f361942537a417 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/idempotent/core/keyresolver/impl/ExpressionIdempotentKeyResolver.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent; import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; @@ -21,8 +21,7 @@ import java.lang.reflect.Method; */ public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver { - private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); - + private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); private final ExpressionParser expressionParser = new SpelExpressionParser(); @Override diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/ApiSignatureAspect.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/ApiSignatureAspect.java index e568346aa32768c9251d7824ddf97adee811ba03..d2d2308426fd41cbf0a9d5640ae13a5d666bd2f5 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/ApiSignatureAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/ApiSignatureAspect.java @@ -11,13 +11,13 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature; import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO; -import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; +import javax.servlet.http.HttpServletRequest; import java.util.Map; import java.util.Objects; import java.util.SortedMap; diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/ApiSignatureTest.java b/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/ApiSignatureTest.java deleted file mode 100644 index 442374061223040f49eab926cbfd68a86ede8842..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/ApiSignatureTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package cn.iocoder.yudao.framework.signature.core; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.crypto.digest.DigestUtil; -import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature; -import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect; -import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO; -import jakarta.servlet.http.HttpServletRequest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.concurrent.TimeUnit; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -/** - * {@link ApiSignatureTest} 的单元测试 - */ -@ExtendWith(MockitoExtension.class) -public class ApiSignatureTest { - - @InjectMocks - private ApiSignatureAspect apiSignatureAspect; - - @Mock - private ApiSignatureRedisDAO signatureRedisDAO; - - @Test - public void testSignatureGet() throws IOException { - // 搞一个签名 - Long timestamp = System.currentTimeMillis(); - String nonce = IdUtil.randomUUID(); - String appId = "xxxxxx"; - String appSecret = "yyyyyy"; - String signString = "k1=v1&v1=k1testappId=xxxxxx&nonce=" + nonce + "×tamp=" + timestamp + "yyyyyy"; - String sign = DigestUtil.sha256Hex(signString); - - // 准备参数 - ApiSignature apiSignature = mock(ApiSignature.class); - when(apiSignature.appId()).thenReturn("appId"); - when(apiSignature.timestamp()).thenReturn("timestamp"); - when(apiSignature.nonce()).thenReturn("nonce"); - when(apiSignature.sign()).thenReturn("sign"); - when(apiSignature.timeout()).thenReturn(60); - when(apiSignature.timeUnit()).thenReturn(TimeUnit.SECONDS); - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getHeader(eq("appId"))).thenReturn(appId); - when(request.getHeader(eq("timestamp"))).thenReturn(String.valueOf(timestamp)); - when(request.getHeader(eq("nonce"))).thenReturn(nonce); - when(request.getHeader(eq("sign"))).thenReturn(sign); - when(request.getParameterMap()).thenReturn(MapUtil.builder() - .put("v1", new String[]{"k1"}).put("k1", new String[]{"v1"}).build()); - when(request.getContentType()).thenReturn("application/json"); - when(request.getReader()).thenReturn(new BufferedReader(new StringReader("test"))); - // mock 方法 - when(signatureRedisDAO.getAppSecret(eq(appId))).thenReturn(appSecret); - when(signatureRedisDAO.setNonce(eq(appId), eq(nonce), eq(120), eq(TimeUnit.SECONDS))).thenReturn(true); - - // 调用 - boolean result = apiSignatureAspect.verifySignature(apiSignature, request); - // 断言结果 - assertTrue(result); - } - -} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml index 8f4e580a05d332baac2f23b9e82cf4a2ee0e1d68..3e059bac301e373b0861d9249fb5a215c07d181c 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml @@ -26,6 +26,10 @@ org.redisson redisson-spring-boot-starter + + org.redisson + redisson-spring-data-27 + org.springframework.boot diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java index 01eeb049d5cf3f1c9305cab4c1c0b9bfeb777799..ff02c933718c648d692e0a17f6a3d802268847be 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoRedisAutoConfiguration.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.redis.config; import cn.hutool.core.util.ReflectUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.redisson.spring.starter.RedissonAutoConfigurationV2; +import org.redisson.spring.starter.RedissonAutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.RedisConnectionFactory; @@ -13,7 +13,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; /** * Redis 配置类 */ -@AutoConfiguration(before = RedissonAutoConfigurationV2.class) // 目的:使用自己定义的 RedisTemplate Bean +@AutoConfiguration(before = RedissonAutoConfiguration.class) // 目的:使用自己定义的 RedisTemplate Bean public class YudaoRedisAutoConfiguration { /** diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java index 7000f6ede343042e423c6418ede099c2d3cf3f82..798a7ea8e8b1b6987b40c94980bf6c9f9490f666 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java @@ -8,10 +8,10 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import com.mzt.logapi.beans.LogRecord; import com.mzt.logapi.service.ILogRecordService; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; import java.util.List; /** diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java index 1b6bf68aae01cf380eaf1191bcfdbd65f065ebe1..337400f68b912c515eaa459e7ff49cbed1512cfd 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.framework.security.config; import cn.iocoder.yudao.framework.web.config.WebProperties; -import jakarta.annotation.Resource; import org.springframework.core.Ordered; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; +import javax.annotation.Resource; + /** * 自定义的 URL 的安全配置 * 目的:每个 Maven Module 可以自定义规则! 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 936e447f1470a2ee20136beba96227eb3c9da10b..3d19f32a65c2b4b8505fe6265c56cc94c7456992 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 @@ -4,8 +4,8 @@ import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.util.Collections; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java index 8874b15593e744f59d5b9f743617743c785f1b80..b3793bc0e578f69a7d3ccbbb87e5458b63cf1887 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPoint import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService; import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkServiceImpl; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; -import jakarta.annotation.Resource; +import javax.annotation.Resource; import org.springframework.beans.factory.config.MethodInvokingFactoryBean; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; 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 0c7b31521a37d829cdaf1cfc667b297653641d72..f5bb27968300aadb826528dab0d23f82fa9d6788 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 @@ -5,9 +5,6 @@ import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter import cn.iocoder.yudao.framework.web.config.WebProperties; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.servlet.DispatcherType; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.context.ApplicationContext; @@ -31,6 +28,9 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.util.pattern.PathPattern; +import javax.annotation.Resource; +import javax.annotation.security.PermitAll; +import javax.servlet.DispatcherType; import java.util.HashSet; import java.util.List; import java.util.Map; 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 8aaea2e654e354836b2d480ef33cdd3920d31788..8035a7aa85727f8569a8dc8588b1e53ea296ebae 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 @@ -12,14 +12,14 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.security.access.AccessDeniedException; import org.springframework.web.filter.OncePerRequestFilter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java index 0ec5262bcaae765232bfa07df0b690beb727866a..33f3f14f4e02f285245ac967e88537aeaeef4077 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AccessDeniedHandlerImpl.java @@ -8,14 +8,16 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.access.ExceptionTranslationFilter; +import org.springframework.stereotype.Component; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED; /** * 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。 diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java index 9d9caa6aae9ee353babc10ea826d750b4c9f09f3..0a451e0762757208558a75627484f735302197b3 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AuthenticationEntryPointImpl.java @@ -8,9 +8,9 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.ExceptionTranslationFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED; 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 4f8024474bbc216a6239f580a8a7be33181f7ab0..f2f1e4848be9d94243fd9b4f11a6508f4025ebfc 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 @@ -13,7 +13,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.util.StringUtils; -import jakarta.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequest; import java.util.Collections; /** diff --git a/yudao-framework/yudao-spring-boot-starter-test/pom.xml b/yudao-framework/yudao-spring-boot-starter-test/pom.xml deleted file mode 100644 index 04576fee6c2225e0cb1b0d73fa9a172a93c661c0..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - cn.iocoder.boot - yudao-framework - ${revision} - - 4.0.0 - yudao-spring-boot-starter-test - jar - - ${project.artifactId} - 测试组件,用于单元测试、集成测试 - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mybatis - - - - cn.iocoder.boot - yudao-spring-boot-starter-redis - - - - - org.mockito - mockito-inline - - - org.springframework.boot - spring-boot-starter-test - - - - com.h2database - h2 - - - - com.github.fppt - jedis-mock - - - - uk.co.jemos.podam - podam - - - diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/config/RedisTestConfiguration.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/config/RedisTestConfiguration.java deleted file mode 100644 index 46222911e95cea49a62d60cd6ed416fa55679517..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/config/RedisTestConfiguration.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.framework.test.config; - -import com.github.fppt.jedismock.RedisServer; -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; - -import java.io.IOException; - -/** - * Redis 测试 Configuration,主要实现内嵌 Redis 的启动 - * - * @author 芋道源码 - */ -@Configuration(proxyBeanMethods = false) -@Lazy(false) // 禁止延迟加载 -@EnableConfigurationProperties(RedisProperties.class) -public class RedisTestConfiguration { - - /** - * 创建模拟的 Redis Server 服务器 - */ - @Bean - public RedisServer redisServer(RedisProperties properties) throws IOException { - RedisServer redisServer = new RedisServer(properties.getPort()); - // 一次执行多个单元测试时,貌似创建多个 spring 容器,导致不进行 stop。这样,就导致端口被占用,无法启动。。。 - try { - redisServer.start(); - } catch (Exception ignore) {} - return redisServer; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/config/SqlInitializationTestConfiguration.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/config/SqlInitializationTestConfiguration.java deleted file mode 100644 index abaec9d84f64ca7b9b2dbaffa624cf493d358e8a..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/config/SqlInitializationTestConfiguration.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.framework.test.config; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; -import org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer; -import org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer; -import org.springframework.boot.sql.init.DatabaseInitializationSettings; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; - -import javax.sql.DataSource; - -/** - * SQL 初始化的测试 Configuration - * - * 为什么不使用 org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration 呢? - * 因为我们在单元测试会使用 spring.main.lazy-initialization 为 true,开启延迟加载。此时,会导致 DataSourceInitializationConfiguration 初始化 - * 不过呢,当前类的实现代码,基本是复制 DataSourceInitializationConfiguration 的哈! - * - * @author 芋道源码 - */ -@Configuration(proxyBeanMethods = false) -@ConditionalOnMissingBean(AbstractScriptDatabaseInitializer.class) -@ConditionalOnSingleCandidate(DataSource.class) -@ConditionalOnClass(name = "org.springframework.jdbc.datasource.init.DatabasePopulator") -@Lazy(value = false) // 禁止延迟加载 -@EnableConfigurationProperties(SqlInitializationProperties.class) -public class SqlInitializationTestConfiguration { - - @Bean - public DataSourceScriptDatabaseInitializer dataSourceScriptDatabaseInitializer(DataSource dataSource, - SqlInitializationProperties initializationProperties) { - DatabaseInitializationSettings settings = createFrom(initializationProperties); - return new DataSourceScriptDatabaseInitializer(dataSource, settings); - } - - static DatabaseInitializationSettings createFrom(SqlInitializationProperties properties) { - DatabaseInitializationSettings settings = new DatabaseInitializationSettings(); - settings.setSchemaLocations(properties.getSchemaLocations()); - settings.setDataLocations(properties.getDataLocations()); - settings.setContinueOnError(properties.isContinueOnError()); - settings.setSeparator(properties.getSeparator()); - settings.setEncoding(properties.getEncoding()); - settings.setMode(properties.getMode()); - return settings; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java deleted file mode 100644 index 46a6927d61860aeb33d6e8dd6c67d82cc884ec44..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbAndRedisUnitTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.framework.test.core.ut; - -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; -import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; -import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; -import cn.iocoder.yudao.framework.test.config.RedisTestConfiguration; -import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration; -import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure; -import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; -import org.redisson.spring.starter.RedissonAutoConfiguration; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; - -/** - * 依赖内存 DB + Redis 的单元测试 - * - * 相比 {@link BaseDbUnitTest} 来说,额外增加了内存 Redis - * - * @author 芋道源码 - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbAndRedisUnitTest.Application.class) -@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 -@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB -public class BaseDbAndRedisUnitTest { - - @Import({ - // DB 配置类 - YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 - DataSourceAutoConfiguration.class, // Spring DB 自动配置类 - DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 - DruidDataSourceAutoConfigure.class, // Druid 自动配置类 - SqlInitializationTestConfiguration.class, // SQL 初始化 - // MyBatis 配置类 - YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 - MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 - - // Redis 配置类 - RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer - YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类 - RedisAutoConfiguration.class, // Spring Redis 自动配置类 - RedissonAutoConfiguration.class, // Redisson 自动配置类 - - // 其它配置类 - SpringUtil.class - }) - public static class Application { - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java deleted file mode 100644 index 98b06f95f3500f75ddbb7e39651b176f36540e52..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseDbUnitTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.framework.test.core.ut; - -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; -import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; -import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration; -import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure; -import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; -import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.jdbc.Sql; - -/** - * 依赖内存 DB 的单元测试 - * - * 注意,Service 层同样适用。对于 Service 层的单元测试,我们针对自己模块的 Mapper 走的是 H2 内存数据库,针对别的模块的 Service 走的是 Mock 方法 - * - * @author 芋道源码 - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseDbUnitTest.Application.class) -@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 -@Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) // 每个单元测试结束后,清理 DB -public class BaseDbUnitTest { - - @Import({ - // DB 配置类 - YudaoDataSourceAutoConfiguration.class, // 自己的 DB 配置类 - DataSourceAutoConfiguration.class, // Spring DB 自动配置类 - DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 - DruidDataSourceAutoConfigure.class, // Druid 自动配置类 - SqlInitializationTestConfiguration.class, // SQL 初始化 - // MyBatis 配置类 - YudaoMybatisAutoConfiguration.class, // 自己的 MyBatis 配置类 - MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 - MybatisPlusJoinAutoConfiguration.class, // MyBatis 的Join配置类 - - // 其它配置类 - SpringUtil.class - }) - public static class Application { - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseMockitoUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseMockitoUnitTest.java deleted file mode 100644 index 26048695c5a331556b6816f7ffd7bae953138129..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseMockitoUnitTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package cn.iocoder.yudao.framework.test.core.ut; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; - -/** - * 纯 Mockito 的单元测试 - * - * @author 芋道源码 - */ -@ExtendWith(MockitoExtension.class) -public class BaseMockitoUnitTest { -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java deleted file mode 100644 index ff6315a2dd222cbde38ca4a94aa2feb8ed1481fb..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/BaseRedisUnitTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.framework.test.core.ut; - -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; -import cn.iocoder.yudao.framework.test.config.RedisTestConfiguration; -import org.redisson.spring.starter.RedissonAutoConfiguration; -import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.ActiveProfiles; - -/** - * 依赖内存 Redis 的单元测试 - * - * 相比 {@link BaseDbUnitTest} 来说,从内存 DB 改成了内存 Redis - * - * @author 芋道源码 - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = BaseRedisUnitTest.Application.class) -@ActiveProfiles("unit-test") // 设置使用 application-unit-test 配置文件 -public class BaseRedisUnitTest { - - @Import({ - // Redis 配置类 - RedisTestConfiguration.class, // Redis 测试配置类,用于启动 RedisServer - RedisAutoConfiguration.class, // Spring Redis 自动配置类 - YudaoRedisAutoConfiguration.class, // 自己的 Redis 配置类 - RedissonAutoConfiguration.class, // Redisson 自动配置类 - - // 其它配置类 - SpringUtil.class - }) - public static class Application { - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/package-info.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/package-info.java deleted file mode 100644 index bda7aad2524dc40cdc03233caba81794ae1d7243..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/ut/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 提供单元测试 Unit Test 的基类 - */ -package cn.iocoder.yudao.framework.test.core.ut; diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java deleted file mode 100644 index e98f4980fcdf6cded420031a3c351e1f82a0a7bf..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -package cn.iocoder.yudao.framework.test.core.util; - -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ReflectUtil; -import cn.iocoder.yudao.framework.common.exception.ErrorCode; -import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.function.Executable; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Objects; - -import static org.junit.jupiter.api.Assertions.assertThrows; - -/** - * 单元测试,assert 断言工具类 - * - * @author 芋道源码 - */ -public class AssertUtils { - - /** - * 比对两个对象的属性是否一致 - * - * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略 - * - * @param expected 期望对象 - * @param actual 实际对象 - * @param ignoreFields 忽略的属性数组 - */ - public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) { - Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); - Arrays.stream(expectedFields).forEach(expectedField -> { - // 忽略 jacoco 自动生成的 $jacocoData 属性的情况 - if (expectedField.isSynthetic()) { - return; - } - // 如果是忽略的属性,则不进行比对 - if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { - return; - } - // 忽略不存在的属性 - Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); - if (actualField == null) { - return; - } - // 比对 - Assertions.assertEquals( - ReflectUtil.getFieldValue(expected, expectedField), - ReflectUtil.getFieldValue(actual, actualField), - String.format("Field(%s) 不匹配", expectedField.getName()) - ); - }); - } - - /** - * 比对两个对象的属性是否一致 - * - * 注意,如果 expected 存在的属性,actual 不存在的时候,会进行忽略 - * - * @param expected 期望对象 - * @param actual 实际对象 - * @param ignoreFields 忽略的属性数组 - * @return 是否一致 - */ - public static boolean isPojoEquals(Object expected, Object actual, String... ignoreFields) { - Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); - return Arrays.stream(expectedFields).allMatch(expectedField -> { - // 如果是忽略的属性,则不进行比对 - if (ArrayUtil.contains(ignoreFields, expectedField.getName())) { - return true; - } - // 忽略不存在的属性 - Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); - if (actualField == null) { - return true; - } - return Objects.equals(ReflectUtil.getFieldValue(expected, expectedField), - ReflectUtil.getFieldValue(actual, actualField)); - }); - } - - /** - * 执行方法,校验抛出的 Service 是否符合条件 - * - * @param executable 业务异常 - * @param errorCode 错误码对象 - * @param messageParams 消息参数 - */ - public static void assertServiceException(Executable executable, ErrorCode errorCode, Object... messageParams) { - // 调用方法 - ServiceException serviceException = assertThrows(ServiceException.class, executable); - // 校验错误码 - Assertions.assertEquals(errorCode.getCode(), serviceException.getCode(), "错误码不匹配"); - String message = ServiceExceptionUtil.doFormat(errorCode.getCode(), errorCode.getMsg(), messageParams); - Assertions.assertEquals(message, serviceException.getMessage(), "错误提示不匹配"); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java deleted file mode 100644 index 1cafbcd4586703ba88047848ac538d4daf9005b2..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java +++ /dev/null @@ -1,146 +0,0 @@ -package cn.iocoder.yudao.framework.test.core.util; - -import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import uk.co.jemos.podam.api.PodamFactory; -import uk.co.jemos.podam.api.PodamFactoryImpl; - -import java.lang.reflect.Type; -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * 随机工具类 - * - * @author 芋道源码 - */ -public class RandomUtils { - - private static final int RANDOM_STRING_LENGTH = 10; - - private static final int TINYINT_MAX = 127; - - private static final int RANDOM_DATE_MAX = 30; - - private static final int RANDOM_COLLECTION_LENGTH = 5; - - private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl(); - - static { - // 字符串 - PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class, - (dataProviderStrategy, attributeMetadata, map) -> randomString()); - // Integer - PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Integer.class, (dataProviderStrategy, attributeMetadata, map) -> { - // 如果是 status 的字段,返回 0 或 1 - if ("status".equals(attributeMetadata.getAttributeName())) { - return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); - } - // 如果是 type、status 结尾的字段,返回 tinyint 范围 - if (StrUtil.endWithAnyIgnoreCase(attributeMetadata.getAttributeName(), - "type", "status", "category", "scope", "result")) { - return RandomUtil.randomInt(0, TINYINT_MAX + 1); - } - return RandomUtil.randomInt(); - }); - // LocalDateTime - PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class, - (dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime()); - // Boolean - PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { - // 如果是 deleted 的字段,返回非删除 - if ("deleted".equals(attributeMetadata.getAttributeName())) { - return false; - } - return RandomUtil.randomBoolean(); - }); - } - - public static String randomString() { - return RandomUtil.randomString(RANDOM_STRING_LENGTH); - } - - public static Long randomLongId() { - return RandomUtil.randomLong(0, Long.MAX_VALUE); - } - - public static Integer randomInteger() { - return RandomUtil.randomInt(0, Integer.MAX_VALUE); - } - - public static Date randomDate() { - return RandomUtil.randomDay(0, RANDOM_DATE_MAX); - } - - public static LocalDateTime randomLocalDateTime() { - // 设置 Nano 为零的原因,避免 MySQL、H2 存储不到时间戳 - return LocalDateTimeUtil.of(randomDate()).withNano(0); - } - - public static Short randomShort() { - return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); - } - - public static Set randomSet(Class clazz) { - return Stream.iterate(0, i -> i).limit(RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH)) - .map(i -> randomPojo(clazz)).collect(Collectors.toSet()); - } - - public static Integer randomCommonStatus() { - return RandomUtil.randomEle(CommonStatusEnum.values()).getStatus(); - } - - public static String randomEmail() { - return randomString() + "@qq.com"; - } - - public static String randomMobile() { - return "13800138" + RandomUtil.randomNumbers(3); - } - - public static String randomURL() { - return "https://www.iocoder.cn/" + randomString(); - } - - @SafeVarargs - public static T randomPojo(Class clazz, Consumer... consumers) { - T pojo = PODAM_FACTORY.manufacturePojo(clazz); - // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 - if (ArrayUtil.isNotEmpty(consumers)) { - Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo)); - } - return pojo; - } - - @SafeVarargs - public static T randomPojo(Class clazz, Type type, Consumer... consumers) { - T pojo = PODAM_FACTORY.manufacturePojo(clazz, type); - // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 - if (ArrayUtil.isNotEmpty(consumers)) { - Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo)); - } - return pojo; - } - - @SafeVarargs - public static List randomPojoList(Class clazz, Consumer... consumers) { - int size = RandomUtil.randomInt(1, RANDOM_COLLECTION_LENGTH); - return randomPojoList(clazz, size, consumers); - } - - @SafeVarargs - public static List randomPojoList(Class clazz, int size, Consumer... consumers) { - return Stream.iterate(0, i -> i).limit(size).map(o -> randomPojo(clazz, consumers)) - .collect(Collectors.toList()); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/package-info.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/package-info.java deleted file mode 100644 index 3a17f5190037e5621e4dc2e6c575952cbfc8995a..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 测试组件,用于单元测试、集成测试等等 - */ -package cn.iocoder.yudao.framework.test; diff --git "a/yudao-framework/yudao-spring-boot-starter-test/\343\200\212\350\212\213\351\201\223 Spring Boot \345\215\225\345\205\203\346\265\213\350\257\225 Test \345\205\245\351\227\250\343\200\213.md" "b/yudao-framework/yudao-spring-boot-starter-test/\343\200\212\350\212\213\351\201\223 Spring Boot \345\215\225\345\205\203\346\265\213\350\257\225 Test \345\205\245\351\227\250\343\200\213.md" deleted file mode 100644 index c6d0e9a9059953bb981c41feec0621069ee34ec6..0000000000000000000000000000000000000000 --- "a/yudao-framework/yudao-spring-boot-starter-test/\343\200\212\350\212\213\351\201\223 Spring Boot \345\215\225\345\205\203\346\265\213\350\257\225 Test \345\205\245\351\227\250\343\200\213.md" +++ /dev/null @@ -1 +0,0 @@ - diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml index d909688741b79da53fbbb28495e1d602d12acbc6..dadd9f6ab7dbdfdde53367e95223c7ccf84c7dc3 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml @@ -40,11 +40,11 @@ com.github.xiaoymin - knife4j-openapi3-jakarta-spring-boot-starter + knife4j-openapi3-spring-boot-starter org.springdoc - springdoc-openapi-starter-webmvc-ui + springdoc-openapi-ui diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java index 156004be3e7bd9bc6aa66c7d2621022ab65b3228..a0305bbf9da84831864826054dd5d23a7da35a9f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiAccessLogCommonApi; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; -import jakarta.servlet.Filter; +import javax.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 1094ebdad7b157149baf923583ee06358497038d..4267048c614ded1087fdc277089b2d41cbc4f294 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -22,14 +22,14 @@ import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.method.HandlerMethod; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; @@ -162,7 +162,8 @@ public class ApiAccessLogFilter extends ApiRequestFilter { // ========== 解析 @ApiAccessLog、@Swagger 注解 ========== private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) { - RequestMethod requestMethod = RequestMethod.resolve(request.getMethod()); + RequestMethod requestMethod = ArrayUtil.firstMatch(method -> + StrUtil.equalsAnyIgnoreCase(method.name(), request.getMethod()), RequestMethod.values()); if (requestMethod == null) { return OperateTypeEnum.OTHER; } @@ -237,7 +238,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { return; } // 情况三:Object,遍历处理 - Iterator> iterator = node.properties().iterator(); + Iterator> iterator = node.fields(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); if (ArrayUtil.contains(sanitizeKeys, entry.getKey()) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java index 7d6b456461efab799960f0dcffc793ade16d552f..3629fc40446ddc07c21ab90aed91ae0ea9900f52 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java @@ -6,13 +6,13 @@ import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StopWatch; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.util.List; import java.util.Map; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java index 7b563291805dde565a0fa1f487e5d7988f300d2e..1e56d094b7b99d0cd0bb8a3a42ac5068ec1c203a 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.desensitize.core.slider.handler; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; @@ -47,7 +48,7 @@ public abstract class AbstractSliderDesensitizationHandler * @return 构建后的替换符 */ private String buildReplacerByLength(String replacer, int length) { - return replacer.repeat(length); + return StrUtil.repeat(replacer, length); } /** diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/config/ApiEncryptProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/config/ApiEncryptProperties.java index 135eb85bb035f9a0dc62730b8fd162f174c98f6d..3b2a5a16c5aacdc904a49c826ee5c5e9ea0e9b86 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/config/ApiEncryptProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/config/ApiEncryptProperties.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.framework.encrypt.config; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; 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; + /** * HTTP API 加解密配置 * diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiDecryptRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiDecryptRequestWrapper.java index b9f015a7ec8d4021ee06cf9d4839d840fe24ff66..ea3386e605de666e40aef4adb6428033a7b02605 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiDecryptRequestWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiDecryptRequestWrapper.java @@ -5,11 +5,11 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.asymmetric.AsymmetricDecryptor; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.symmetric.SymmetricDecryptor; -import jakarta.servlet.ReadListener; -import jakarta.servlet.ServletInputStream; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletRequestWrapper; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptFilter.java index 126a76a01ff0d50ad773823076772b1ddcbe91fb..262b1ea93d611a3760a7bde76aa16a1a0cd76a6b 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptFilter.java @@ -14,10 +14,6 @@ import cn.iocoder.yudao.framework.encrypt.core.annotation.ApiEncrypt; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpMethod; import org.springframework.web.method.HandlerMethod; @@ -25,6 +21,10 @@ import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.util.ServletRequestPathUtils; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptResponseWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptResponseWrapper.java index fed38917b9d060b5d4e2e4e12c6089b31b8598d0..fc49442c314f360512903ae1805253f4f9b00805 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptResponseWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptResponseWrapper.java @@ -4,11 +4,11 @@ import cn.hutool.crypto.asymmetric.AsymmetricEncryptor; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.symmetric.SymmetricEncryptor; import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties; -import jakarta.servlet.ServletOutputStream; -import jakarta.servlet.WriteListener; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.servlet.http.HttpServletResponseWrapper; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java index f8996f75be7730fe5c7bfcf6277f6ce6c16b8378..18faf7fe8a7c272afb9fd931702caad3c04a15cb 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java @@ -10,8 +10,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.models.OpenAPI; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; +import org.springdoc.core.SpringDocConfigProperties; import org.springdoc.core.customizers.GlobalOpenApiCustomizer; -import org.springdoc.core.properties.SpringDocConfigProperties; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.Configuration; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java index 5374d3aca2dc224255004fdfd24f5a32529dc877..13a15688104cd01cd41cc5b526024d7647efab07 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/SwaggerProperties.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.swagger.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; -import jakarta.validation.constraints.NotEmpty; +import javax.validation.constraints.NotEmpty; /** * Swagger 配置属性 diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java index dec79d8eb6b7e903bcd83a5429a83cbe89b608e2..60fbebfabb9c1fecc5c51cae9eef8897db654052 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java @@ -10,14 +10,10 @@ import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springdoc.core.*; import org.springdoc.core.customizers.OpenApiBuilderCustomizer; import org.springdoc.core.customizers.ServerBaseUrlCustomizer; -import org.springdoc.core.models.GroupedOpenApi; -import org.springdoc.core.properties.SpringDocConfigProperties; import org.springdoc.core.providers.JavadocProvider; -import org.springdoc.core.service.OpenAPIService; -import org.springdoc.core.service.SecurityService; -import org.springdoc.core.utils.PropertyResolverUtils; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java index 8091e9afab7a4ee07c4b1fbd75139df692fb50b9..03f4d70b6b28d2d3e8db8f5cfa302cb84d4e2781 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java @@ -7,9 +7,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; @ConfigurationProperties(prefix = "yudao.web") @Validated diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 9126c7e8eadfb452d1fe2802bef32c7b11dd5d79..65defd131866e139d0ed0934e89e42b276f39939 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -7,8 +7,6 @@ import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import jakarta.annotation.Resource; -import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -27,6 +25,9 @@ import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import javax.annotation.Resource; +import javax.servlet.Filter; + @AutoConfiguration @EnableConfigurationProperties(WebProperties.class) public class YudaoWebAutoConfiguration implements WebMvcConfigurer { diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/ApiRequestFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/ApiRequestFilter.java index 7b064e8d6e75046ec83ddd36770eb54066cc6ad6..42cb6a665812aba3359b2009190eae34372ce81f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/ApiRequestFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/ApiRequestFilter.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.web.config.WebProperties; import lombok.RequiredArgsConstructor; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequest; /** * 过滤 /admin-api、/app-api 等 API 请求的过滤器 diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java index 49958fc096530b64f0f3bc1a91412974e7ef1fff..6ddca049e0faf534a4cb607478fb5e289d837a17 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java @@ -4,10 +4,10 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java index b5f38d96fd961187493b9871e70b73888fed6592..414aca83a4679ce83193612fbe744a9034172720 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.framework.web.core.filter; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import jakarta.servlet.ReadListener; -import jakarta.servlet.ServletInputStream; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletRequestWrapper; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java index eece3046a056553063ba1ff268f56dfb160a4489..8e37247d26a45f31025968dae640a451f69bfd27 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/DemoFilter.java @@ -6,9 +6,9 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.DEMO_DENY; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index b99925e651507e780f3d5a2f61b919ab496ad9fa..156d7e04aa1bf6a414e8990d55ec67b42a2caaeb 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -17,10 +17,6 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import com.google.common.util.concurrent.UncheckedExecutionException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; -import jakarta.validation.ValidationException; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -38,8 +34,11 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.multipart.MaxUploadSizeExceededException; import org.springframework.web.servlet.NoHandlerFoundException; -import org.springframework.web.servlet.resource.NoResourceFoundException; +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.ValidationException; import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -100,9 +99,6 @@ public class GlobalExceptionHandler { if (ex instanceof NoHandlerFoundException) { return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex); } - if (ex instanceof NoResourceFoundException) { - return noResourceFoundExceptionHandler(request, (NoResourceFoundException) ex); - } if (ex instanceof HttpRequestMethodNotSupportedException) { return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); } @@ -236,15 +232,6 @@ public class GlobalExceptionHandler { return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL())); } - /** - * 处理 SpringMVC 请求地址不存在 - */ - @ExceptionHandler(NoResourceFoundException.class) - private CommonResult noResourceFoundExceptionHandler(HttpServletRequest req, NoResourceFoundException ex) { - log.warn("[noResourceFoundExceptionHandler]", ex); - return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getResourcePath())); - } - /** * 处理 SpringMVC 请求方法不正确 * diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java index 248e8a4155dd4a6810aebc16e545e81f95b7496d..ea713a5ca7844b960d86a3056b3df7a7a5dab0fb 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java @@ -5,12 +5,13 @@ import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.web.config.WebProperties; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; + /** * 专属于 web 包的工具类 * diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java index d33086a4259cfaf4fca271837b8cf93c9b0b9830..5f2ce6e3d374f7cdb47d803843802ba03f8a00cc 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java @@ -6,10 +6,10 @@ import lombok.AllArgsConstructor; import org.springframework.util.PathMatcher; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java index 427eb9baac5f8379a131c1d2c6f67cd48611f613..1466a97cc1f85c3264a0c6343de63cf1c4901b7b 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.framework.xss.core.filter; import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import java.util.LinkedHashMap; import java.util.Map; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java index 047b19d38c89981778e67ff1b75616673b1cde6a..003244378b404f2e1833d426f3e7d04a2a0368cd 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java @@ -7,11 +7,11 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StringDeserializer; -import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.util.PathMatcher; +import javax.servlet.http.HttpServletRequest; import java.io.IOException; /** diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java deleted file mode 100644 index dd214f0c3e4f0718e1517d204a8d56bf67e6fada..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package cn.iocoder.yudao.framework.desensitize.core; - -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; -import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.EmailDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.RegexDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.*; -import lombok.Data; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** - * {@link DesensitizeTest} 的单元测试 - */ -@ExtendWith(MockitoExtension.class) -public class DesensitizeTest { - - @Test - public void test() { - // 准备参数 - DesensitizeDemo desensitizeDemo = new DesensitizeDemo(); - desensitizeDemo.setNickname("芋道源码"); - desensitizeDemo.setBankCard("9988002866797031"); - desensitizeDemo.setCarLicense("粤A66666"); - desensitizeDemo.setFixedPhone("01086551122"); - desensitizeDemo.setIdCard("530321199204074611"); - desensitizeDemo.setPassword("123456"); - desensitizeDemo.setPhoneNumber("13248765917"); - desensitizeDemo.setSlider1("ABCDEFG"); - desensitizeDemo.setSlider2("ABCDEFG"); - desensitizeDemo.setSlider3("ABCDEFG"); - desensitizeDemo.setEmail("1@email.com"); - desensitizeDemo.setRegex("你好,我是芋道源码"); - desensitizeDemo.setAddress("北京市海淀区上地十街10号"); - desensitizeDemo.setOrigin("芋道源码"); - - // 调用 - DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class); - // 断言 - assertNotNull(d); - assertEquals("芋***", d.getNickname()); - assertEquals("998800********31", d.getBankCard()); - assertEquals("粤A6***6", d.getCarLicense()); - assertEquals("0108*****22", d.getFixedPhone()); - assertEquals("530321**********11", d.getIdCard()); - assertEquals("******", d.getPassword()); - assertEquals("132****5917", d.getPhoneNumber()); - assertEquals("#######", d.getSlider1()); - assertEquals("ABC*EFG", d.getSlider2()); - assertEquals("*******", d.getSlider3()); - assertEquals("1****@email.com", d.getEmail()); - assertEquals("你好,我是*", d.getRegex()); - assertEquals("北京市海淀区上地十街10号*", d.getAddress()); - assertEquals("芋道源码", d.getOrigin()); - } - - @Data - public static class DesensitizeDemo { - - @ChineseNameDesensitize - private String nickname; - @BankCardDesensitize - private String bankCard; - @CarLicenseDesensitize - private String carLicense; - @FixedPhoneDesensitize - private String fixedPhone; - @IdCardDesensitize - private String idCard; - @PasswordDesensitize - private String password; - @MobileDesensitize - private String phoneNumber; - @SliderDesensitize(prefixKeep = 6, suffixKeep = 1, replacer = "#") - private String slider1; - @SliderDesensitize(prefixKeep = 3, suffixKeep = 3) - private String slider2; - @SliderDesensitize(prefixKeep = 10) - private String slider3; - @EmailDesensitize - private String email; - @RegexDesensitize(regex = "芋道源码", replacer = "*") - private String regex; - @Address - private String address; - private String origin; - - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java deleted file mode 100644 index 13012098175e9f7c580102107c97809cf14f3b11..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.framework.desensitize.core.annotation; - -import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; -import cn.iocoder.yudao.framework.desensitize.core.handler.AddressHandler; -import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; -import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 地址 - * - * 用于 {@link DesensitizeTest} 测试使用 - * - * @author gaibu - */ -@Documented -@Target({ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -@JacksonAnnotationsInside -@DesensitizeBy(handler = AddressHandler.class) -public @interface Address { - - String replacer() default "*"; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java deleted file mode 100644 index 7a8455f8d1258384fa719083e8ba28739182f69c..0000000000000000000000000000000000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.desensitize.core.handler; - -import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; -import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; -import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; - -/** - * {@link Address} 的脱敏处理器 - * - * 用于 {@link DesensitizeTest} 测试使用 - */ -public class AddressHandler implements DesensitizationHandler

{ - - @Override - public String desensitize(String origin, Address annotation) { - return origin + annotation.replacer(); - } - -} 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 index f1d84f7a0dcfda4eb106d6734c201c39a2bd6ffd..aa618fb04e100682de1ccde8947a9c8acda8487b 100644 --- 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 @@ -4,8 +4,8 @@ import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; /** * WebSocket 配置项 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 index f260dfc201a8c408be54f168b4524299b45ceb20..dd0a0ecf120c17e25e45c54be748017cd8769125 100644 --- 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 @@ -5,6 +5,7 @@ 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.AuthorizeHttpRequestsConfigurer; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; /** * WebSocket 的权限自定义 diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml deleted file mode 100644 index 06c9cc0ca9aa38d846f2595c1836a5827e09444b..0000000000000000000000000000000000000000 --- a/yudao-module-ai/pom.xml +++ /dev/null @@ -1,245 +0,0 @@ - - - - cn.iocoder.boot - yudao - ${revision} - - 4.0.0 - jar - yudao-module-ai - - ${project.artifactId} - - ai 模块下,接入 LLM 大模型,支持聊天、绘图、音乐、写作、思维导图等功能。 - 目前已接入各种模型,不限于: - 国内:通义千问、文心一言、讯飞星火、智谱 GLM、DeepSeek - 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno - - - 1.0.1 - 1.0.0.3 - 1.0.2 - - - - - cn.iocoder.boot - yudao-module-system - ${revision} - - - cn.iocoder.boot - yudao-module-infra - ${revision} - - - - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-tenant - - - - - cn.iocoder.boot - yudao-spring-boot-starter-security - - - - - cn.iocoder.boot - yudao-spring-boot-starter-mybatis - - - - - cn.iocoder.boot - yudao-spring-boot-starter-job - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - - - - - cn.iocoder.boot - yudao-spring-boot-starter-excel - - - - - org.springframework.ai - spring-ai-starter-model-openai - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-azure-openai - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-anthropic - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-deepseek - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-ollama - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-stability-ai - ${spring-ai.version} - - - - org.springframework.ai - spring-ai-starter-model-zhipuai - ${spring-ai.version} - - - org.springframework.ai - spring-ai-starter-model-minimax - ${spring-ai.version} - - - - - com.alibaba.cloud.ai - spring-ai-alibaba-starter-dashscope - ${alibaba-ai.version} - - - - - org.springaicommunity - qianfan-spring-boot-starter - 1.0.0 - - - - org.springaicommunity - moonshot-spring-boot-starter - 1.0.0 - - - - - - org.springframework.ai - spring-ai-starter-vector-store-qdrant - ${spring-ai.version} - - - - - org.springframework.ai - spring-ai-starter-vector-store-redis - ${spring-ai.version} - - - cn.iocoder.boot - yudao-spring-boot-starter-redis - - - - - org.springframework.ai - spring-ai-starter-vector-store-milvus - ${spring-ai.version} - - - - org.slf4j - slf4j-reload4j - - - - - - - org.springframework.ai - spring-ai-tika-document-reader - ${spring-ai.version} - - - - spring-cloud-function-context - org.springframework.cloud - - - spring-cloud-function-core - org.springframework.cloud - - - - - - - - - org.springframework.ai - spring-ai-starter-mcp-server-webmvc - ${spring-ai.version} - - - - org.springframework.ai - spring-ai-starter-mcp-client - ${spring-ai.version} - - - - - dev.tinyflow - tinyflow-java-core - ${tinyflow.version} - - - com.jfinal - enjoy - - - - com.agentsflex - agents-flex-store-elasticsearch - - - - org.codehaus.groovy - groovy-all - - - - org.slf4j - slf4j-simple - - - org.apache.logging.log4j - log4j-slf4j-impl - - - org.slf4j - slf4j-reload4j - - - - - - \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java deleted file mode 100644 index ddd426d2833dba56522efe7adff4917f7fdb7269..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ /dev/null @@ -1,118 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjUtil; -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.ai.controller.admin.chat.vo.conversation.AiChatConversationCreateMyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; -import com.fhs.core.trans.anno.TransMethodResult; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -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.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 聊天对话") -@RestController -@RequestMapping("/ai/chat/conversation") -@Validated -public class AiChatConversationController { - - @Resource - private AiChatConversationService chatConversationService; - @Resource - private AiChatMessageService chatMessageService; - - @PostMapping("/create-my") - @Operation(summary = "创建【我的】聊天对话") - public CommonResult createChatConversationMy(@RequestBody @Valid AiChatConversationCreateMyReqVO createReqVO) { - return success(chatConversationService.createChatConversationMy(createReqVO, getLoginUserId())); - } - - @PutMapping("/update-my") - @Operation(summary = "更新【我的】聊天对话") - public CommonResult updateChatConversationMy(@RequestBody @Valid AiChatConversationUpdateMyReqVO updateReqVO) { - chatConversationService.updateChatConversationMy(updateReqVO, getLoginUserId()); - return success(true); - } - - @GetMapping("/my-list") - @Operation(summary = "获得【我的】聊天对话列表") - @TransMethodResult - public CommonResult> getChatConversationMyList() { - List list = chatConversationService.getChatConversationListByUserId(getLoginUserId()); - return success(BeanUtils.toBean(list, AiChatConversationRespVO.class)); - } - - @GetMapping("/get-my") - @Operation(summary = "获得【我的】聊天对话") - @Parameter(name = "id", required = true, description = "对话编号", example = "1024") - @TransMethodResult - public CommonResult getChatConversationMy(@RequestParam("id") Long id) { - AiChatConversationDO conversation = chatConversationService.getChatConversation(id); - if (conversation != null && ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { - conversation = null; - } - return success(BeanUtils.toBean(conversation, AiChatConversationRespVO.class)); - } - - @DeleteMapping("/delete-my") - @Operation(summary = "删除聊天对话") - @Parameter(name = "id", required = true, description = "对话编号", example = "1024") - public CommonResult deleteChatConversationMy(@RequestParam("id") Long id) { - chatConversationService.deleteChatConversationMy(id, getLoginUserId()); - return success(true); - } - - @DeleteMapping("/delete-by-unpinned") - @Operation(summary = "删除未置顶的聊天对话") - public CommonResult deleteChatConversationMyByUnpinned() { - chatConversationService.deleteChatConversationMyByUnpinned(getLoginUserId()); - return success(true); - } - - // ========== 对话管理 ========== - - @GetMapping("/page") - @Operation(summary = "获得对话分页", description = "用于【对话管理】菜单") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") - @TransMethodResult - public CommonResult> getChatConversationPage(AiChatConversationPageReqVO pageReqVO) { - PageResult pageResult = chatConversationService.getChatConversationPage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - // 拼接关联数据 - Map messageCountMap = chatMessageService.getChatMessageCountMap( - convertList(pageResult.getList(), AiChatConversationDO::getId)); - return success(BeanUtils.toBean(pageResult, AiChatConversationRespVO.class, - conversation -> conversation.setMessageCount(messageCountMap.getOrDefault(conversation.getId(), 0)))); - } - - @Operation(summary = "管理员删除对话") - @DeleteMapping("/delete-by-admin") - @Parameter(name = "id", required = true, description = "对话编号", example = "1024") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:delete')") - public CommonResult deleteChatConversationByAdmin(@RequestParam("id") Long id) { - chatConversationService.deleteChatConversationByAdmin(id); - return success(true); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http deleted file mode 100644 index 017714e097a15986e193e3235d941da25f4202d2..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.http +++ /dev/null @@ -1,66 +0,0 @@ -### 发送消息(段式) -POST {{baseUrl}}/ai/chat/message/send -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581724", - "content": "你是 OpenAI 么?" -} - -### 发送消息(流式) -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581724", - "content": "1+1=?" -} - -### 发送消息(流式)【带文件】 -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581797", - "content": "图片里有什么?", - "attachmentUrls": ["http://test.yudao.iocoder.cn/1755531278.jpeg"] -} - -### 发送消息(流式)【追问带文件】 -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581799", - "content": "说下图片里,有哪些字?", - "useContext": true -} - -### 发送消息(流式)【联网搜索】 -POST {{baseUrl}}/ai/chat/message/send-stream -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "conversationId": "1781604279872581799", - "content": "今天是周几?", - "useSearch": true -} - -### 获得指定对话的消息列表 -GET {{baseUrl}}/ai/chat/message/list-by-conversation-id?conversationId=1781604279872581799 -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -### 删除消息 -DELETE {{baseUrl}}/ai/chat/message/delete?id=50 -Authorization: {{token}} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java deleted file mode 100644 index bfd1e41caf32ddd837dc04cce410607ae49cd285..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java +++ /dev/null @@ -1,157 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjUtil; -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.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; -import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; - -import java.util.Collections; -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.*; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - 聊天消息") -@RestController -@RequestMapping("/ai/chat/message") -@Slf4j -public class AiChatMessageController { - - @Resource - private AiChatMessageService chatMessageService; - @Resource - private AiChatConversationService chatConversationService; - @Resource - private AiChatRoleService chatRoleService; - @Resource - private AiKnowledgeSegmentService knowledgeSegmentService; - @Resource - private AiKnowledgeDocumentService knowledgeDocumentService; - - @Operation(summary = "发送消息(段式)", description = "一次性返回,响应较慢") - @PostMapping("/send") - public CommonResult sendMessage(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) { - return success(chatMessageService.sendMessage(sendReqVO, getLoginUserId())); - } - - @Operation(summary = "发送消息(流式)", description = "流式返回,响应较快") - @PostMapping(value = "/send-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - public Flux> sendChatMessageStream(@Valid @RequestBody AiChatMessageSendReqVO sendReqVO) { - return chatMessageService.sendChatMessageStream(sendReqVO, getLoginUserId()); - } - - @Operation(summary = "获得指定对话的消息列表") - @GetMapping("/list-by-conversation-id") - @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") - public CommonResult> getChatMessageListByConversationId( - @RequestParam("conversationId") Long conversationId) { - AiChatConversationDO conversation = chatConversationService.getChatConversation(conversationId); - if (conversation == null || ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { - return success(Collections.emptyList()); - } - // 1. 获取消息列表 - List messageList = chatMessageService.getChatMessageListByConversationId(conversationId); - if (CollUtil.isEmpty(messageList)) { - return success(Collections.emptyList()); - } - - // 2. 拼接数据,主要是知识库段落信息 - Map segmentMap = knowledgeSegmentService.getKnowledgeSegmentMap(convertListByFlatMap(messageList, - message -> CollUtil.isEmpty(message.getSegmentIds()) ? null : message.getSegmentIds().stream())); - Map documentMap = knowledgeDocumentService.getKnowledgeDocumentMap( - convertList(segmentMap.values(), AiKnowledgeSegmentDO::getDocumentId)); - List messageVOList = BeanUtils.toBean(messageList, AiChatMessageRespVO.class); - for (int i = 0; i < messageList.size(); i++) { - AiChatMessageDO message = messageList.get(i); - if (CollUtil.isEmpty(message.getSegmentIds())) { - continue; - } - // 设置知识库段落信息 - messageVOList.get(i).setSegments(convertList(message.getSegmentIds(), segmentId -> { - AiKnowledgeSegmentDO segment = segmentMap.get(segmentId); - if (segment == null) { - return null; - } - AiKnowledgeDocumentDO document = documentMap.get(segment.getDocumentId()); - if (document == null) { - return null; - } - return new AiChatMessageRespVO.KnowledgeSegment().setId(segment.getId()).setContent(segment.getContent()) - .setDocumentId(segment.getDocumentId()).setDocumentName(document.getName()); - })); - } - return success(messageVOList); - } - - @Operation(summary = "删除消息") - @DeleteMapping("/delete") - @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - public CommonResult deleteChatMessage(@RequestParam("id") Long id) { - chatMessageService.deleteChatMessage(id, getLoginUserId()); - return success(true); - } - - @Operation(summary = "删除指定对话的消息") - @DeleteMapping("/delete-by-conversation-id") - @Parameter(name = "conversationId", required = true, description = "对话编号", example = "1024") - public CommonResult deleteChatMessageByConversationId(@RequestParam("conversationId") Long conversationId) { - chatMessageService.deleteChatMessageByConversationId(conversationId, getLoginUserId()); - return success(true); - } - - // ========== 对话管理 ========== - - @GetMapping("/page") - @Operation(summary = "获得消息分页", description = "用于【对话管理】菜单") - @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") - public CommonResult> getChatMessagePage(AiChatMessagePageReqVO pageReqVO) { - PageResult pageResult = chatMessageService.getChatMessagePage(pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty()); - } - // 拼接数据 - Map roleMap = chatRoleService.getChatRoleMap( - convertSet(pageResult.getList(), AiChatMessageDO::getRoleId)); - return success(BeanUtils.toBean(pageResult, AiChatMessageRespVO.class, - respVO -> MapUtils.findAndThen(roleMap, respVO.getRoleId(), - role -> respVO.setRoleName(role.getName())))); - } - - @Operation(summary = "管理员删除消息") - @DeleteMapping("/delete-by-admin") - @Parameter(name = "id", required = true, description = "消息编号", example = "1024") - @PreAuthorize("@ss.hasPermission('ai:chat-message:delete')") - public CommonResult deleteChatMessageByAdmin(@RequestParam("id") Long id) { - chatMessageService.deleteChatMessageByAdmin(id); - return success(true); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java deleted file mode 100644 index 84595bea23ae797e785f67c0bf4db92375f20efb..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationCreateMyReqVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天对话创建【我的】 Request VO") -@Data -public class AiChatConversationCreateMyReqVO { - - @Schema(description = "聊天角色编号", example = "666") - private Long roleId; - - @Schema(description = "知识库编号", example = "1204") - private Long knowledgeId; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java deleted file mode 100644 index 967e866ea72540db307b9c9266a5a1ce84e3f60e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationPageReqVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -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 = "管理后台 - AI 聊天对话的分页 Request VO") -@Data -public class AiChatConversationPageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "1024") - private Long userId; - - @Schema(description = "对话标题", example = "你好") - private String title; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java deleted file mode 100644 index 7da37ebc9be913295aa7fc47c469e06c8b344450..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationRespVO.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import com.fhs.core.trans.anno.Trans; -import com.fhs.core.trans.constant.TransType; -import com.fhs.core.trans.vo.VO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 聊天对话 Response VO") -@Data -public class AiChatConversationRespVO implements VO { - - @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") - private Long userId; - - @Schema(description = "对话标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个标题") - private String title; - - @Schema(description = "是否置顶", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean pinned; - - @Schema(description = "角色编号", example = "1") - @Trans(type = TransType.SIMPLE, target = AiChatRoleDO.class, fields = {"name", "avatar"}, refs = {"roleName", "roleAvatar"}) - private Long roleId; - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = "name", ref = "modelName") - private Long modelId; - - @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "ERNIE-Bot-turbo-0922") - private String model; - - @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - private String modelName; - - @Schema(description = "角色设定", example = "一个快乐的程序员") - private String systemMessage; - - @Schema(description = "温度参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer maxContexts; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - - // ========== 关联 role 信息 ========== - - @Schema(description = "角色头像", example = "https://www.iocoder.cn/1.png") - private String roleAvatar; - - @Schema(description = "角色名字", example = "小黄") - private String roleName; - - // ========== 仅在【对话管理】时加载 ========== - - @Schema(description = "消息数量", example = "20") - private Integer messageCount; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java deleted file mode 100644 index 2b57572c4e038424b50c4786d0486c41f4f138d1..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/conversation/AiChatConversationUpdateMyReqVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 聊天对话更新【我的】 Request VO") -@Data -public class AiChatConversationUpdateMyReqVO { - - @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "对话编号不能为空") - private Long id; - - @Schema(description = "对话标题", example = "我是一个标题") - private String title; - - @Schema(description = "是否置顶", example = "true") - private Boolean pinned; - - @Schema(description = "模型编号", example = "1") - private Long modelId; - - @Schema(description = "知识库编号", example = "1") - private Long knowledgeId; - - @Schema(description = "角色设定", example = "一个快乐的程序员") - private String systemMessage; - - @Schema(description = "温度参数", example = "0.8") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", example = "10") - private Integer maxContexts; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java deleted file mode 100644 index 7ccb6aa0b62423880d364d361202ca9022b5c292..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessagePageReqVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -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 = "管理后台 - AI 聊天消息的分页 Request VO") -@Data -public class AiChatMessagePageReqVO extends PageParam { - - @Schema(description = "对话编号", example = "2048") - private Long conversationId; - - @Schema(description = "用户编号", example = "1024") - private Long userId; - - @Schema(description = "消息内容", example = "你好") - private String content; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java deleted file mode 100644 index b0f13e3c2effebea822400cc9dfe85e14867c824..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java +++ /dev/null @@ -1,85 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天消息 Response VO") -@Data -public class AiChatMessageRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") - private Long conversationId; - - @Schema(description = "回复消息编号", example = "1024") - private Long replyId; - - @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") - private String type; // 参见 MessageType 枚举类 - - @Schema(description = "用户编号", example = "4096") - private Long userId; - - @Schema(description = "角色编号", example = "888") - private Long roleId; - - @Schema(description = "模型标志", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo") - private String model; - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123") - private Long modelId; - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") - private String content; - - @Schema(description = "推理内容", example = "要达到这个目标,你需要...") - private String reasoningContent; - - @Schema(description = "是否携带上下文", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean useContext; - - @Schema(description = "知识库段落编号数组", example = "[1,2,3]") - private List segmentIds; - - @Schema(description = "知识库段落数组") - private List segments; - - @Schema(description = "联网搜索的网页内容数组") - private List webSearchPages; - - @Schema(description = "附件 URL 数组", example = "https://www.iocoder.cn/1.png") - private List attachmentUrls; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-05-12 12:51") - private LocalDateTime createTime; - - // ========== 仅在【对话管理】时加载 ========== - - @Schema(description = "角色名字", example = "小黄") - private String roleName; - - @Schema(description = "知识库段落", example = "Java 开发手册") - @Data - public static class KnowledgeSegment { - - @Schema(description = "段落编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - private String content; - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long documentId; - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品使用手册") - private String documentName; - - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java deleted file mode 100644 index 06ce0d10d64ced71e2dc23250d682819fd8ee784..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天消息发送 Request VO") -@Data -public class AiChatMessageSendReqVO { - - @Schema(description = "聊天对话编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "聊天对话编号不能为空") - private Long conversationId; - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "帮我写个 Java 算法") - @NotEmpty(message = "聊天内容不能为空") - private String content; - - @Schema(description = "是否携带上下文", example = "true") - private Boolean useContext; - - @Schema(description = "是否联网搜索", example = "true") - private Boolean useSearch; - - @Schema(description = "附件 URL 数组", example = "https://www.iocoder.cn/1.png") - private List attachmentUrls; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java deleted file mode 100644 index 520712b9b4670612a1409d1da54acc009be73ef9..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message; - -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天消息发送 Response VO") -@Data -public class AiChatMessageSendRespVO { - - @Schema(description = "发送消息", requiredMode = Schema.RequiredMode.REQUIRED) - private Message send; - - @Schema(description = "接收消息", requiredMode = Schema.RequiredMode.REQUIRED) - private Message receive; - - @Schema(description = "消息") - @Data - public static class Message { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Long id; - - @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "role") - private String type; // 参见 MessageType 枚举类 - - @Schema(description = "聊天内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,你好啊") - private String content; - - @Schema(description = "推理内容", example = "要达到这个目标,你需要...") - private String reasoningContent; - - @Schema(description = "知识库段落编号数组", example = "[1,2,3]") - private List segmentIds; - - @Schema(description = "知识库段落数组") - private List segments; - - @Schema(description = "联网搜索的网页内容数组") - private List webSearchPages; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http deleted file mode 100644 index 9047610c0fe7dc53eebbb94cb362ebe4315539bd..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.http +++ /dev/null @@ -1,42 +0,0 @@ -### 生成图片:OpenAI(DALL) -POST {{baseUrl}}/ai/image/draw -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "OpenAI", - "prompt": "可爱的小喵星人", - "model": "dall-e-3", - "height": "1024", - "width": "1024", - "options": { - "style": "vivid" - } -} - -### 生成图片:StableDiffusion -POST {{baseUrl}}/ai/image/draw -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "StableDiffusion", - "prompt": "中国长城", - "model": "stable-diffusion-v1-6", - "height": "1024", - "width": "1024", - "style": "vivid" -} - -### 生成图片:生成图片(Midjourney) -POST {{baseUrl}}/ai/image/midjourney/imagine -Content-Type: application/json -Authorization: {{token}} - -{ - "prompt": "中国旗袍", - "model": "midjourney", - "width": "1", - "height": "1", - "version": "6.0" -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java deleted file mode 100644 index 1d9503f364c8b17f0d48f5a30ae1f7c84a1865ad..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/AiImageController.java +++ /dev/null @@ -1,139 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -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.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.*; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyActionReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney.AiMidjourneyImagineReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import cn.iocoder.yudao.module.ai.service.image.AiImageService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 绘画") -@RestController -@RequestMapping("/ai/image") -@Slf4j -public class AiImageController { - - @Resource - private AiImageService imageService; - - @GetMapping("/my-page") - @Operation(summary = "获取【我的】绘图分页") - public CommonResult> getImagePageMy(@Validated AiImagePageReqVO pageReqVO) { - PageResult pageResult = imageService.getImagePageMy(getLoginUserId(), pageReqVO); - return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); - } - - @GetMapping("/public-page") - @Operation(summary = "获取公开的绘图分页") - public CommonResult> getImagePagePublic(AiImagePublicPageReqVO pageReqVO) { - PageResult pageResult = imageService.getImagePagePublic(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); - } - - @GetMapping("/get-my") - @Operation(summary = "获取【我的】绘图记录") - @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult getImageMy(@RequestParam("id") Long id) { - AiImageDO image = imageService.getImage(id); - if (image == null || ObjUtil.notEqual(getLoginUserId(), image.getUserId())) { - return success(null); - } - return success(BeanUtils.toBean(image, AiImageRespVO.class)); - } - - @GetMapping("/my-list-by-ids") - @Operation(summary = "获取【我的】绘图记录列表") - @Parameter(name = "ids", required = true, description = "绘画编号数组", example = "1024,2048") - public CommonResult> getImageListMyByIds(@RequestParam("ids") List ids) { - List imageList = imageService.getImageList(ids); - imageList.removeIf(item -> !ObjUtil.equal(getLoginUserId(), item.getUserId())); - return success(BeanUtils.toBean(imageList, AiImageRespVO.class)); - } - - @Operation(summary = "生成图片") - @PostMapping("/draw") - public CommonResult drawImage(@Valid @RequestBody AiImageDrawReqVO drawReqVO) { - return success(imageService.drawImage(getLoginUserId(), drawReqVO)); - } - - @Operation(summary = "删除【我的】绘画记录") - @DeleteMapping("/delete-my") - @Parameter(name = "id", required = true, description = "绘画编号", example = "1024") - public CommonResult deleteImageMy(@RequestParam("id") Long id) { - imageService.deleteImageMy(id, getLoginUserId()); - return success(true); - } - - // ================ midjourney 专属 ================ - - @Operation(summary = "【Midjourney】生成图片") - @PostMapping("/midjourney/imagine") - public CommonResult midjourneyImagine(@Valid @RequestBody AiMidjourneyImagineReqVO reqVO) { - Long imageId = imageService.midjourneyImagine(getLoginUserId(), reqVO); - return success(imageId); - } - - @Operation(summary = "【Midjourney】通知图片进展", description = "由 Midjourney Proxy 回调") - @PostMapping("/midjourney/notify") // 必须是 POST 方法,否则会报错 - @PermitAll - @TenantIgnore - public CommonResult midjourneyNotify(@Valid @RequestBody MidjourneyApi.Notify notify) { - imageService.midjourneyNotify(notify); - return success(true); - } - - @Operation(summary = "【Midjourney】Action 操作(二次生成图片)", description = "例如说:放大、缩小、U1、U2 等") - @PostMapping("/midjourney/action") - public CommonResult midjourneyAction(@Valid @RequestBody AiMidjourneyActionReqVO reqVO) { - Long imageId = imageService.midjourneyAction(getLoginUserId(), reqVO); - return success(imageId); - } - - // ================ 绘图管理 ================ - - @GetMapping("/page") - @Operation(summary = "获得绘画分页") - @PreAuthorize("@ss.hasPermission('ai:image:query')") - public CommonResult> getImagePage(@Valid AiImagePageReqVO pageReqVO) { - PageResult pageResult = imageService.getImagePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiImageRespVO.class)); - } - - @PutMapping("/update") - @Operation(summary = "更新绘画") - @PreAuthorize("@ss.hasPermission('ai:image:update')") - public CommonResult updateImage(@Valid @RequestBody AiImageUpdateReqVO updateReqVO) { - imageService.updateImage(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除绘画") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:image:delete')") - public CommonResult deleteImage(@RequestParam("id") Long id) { - imageService.deleteImage(id); - return success(true); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java deleted file mode 100644 index 02225ea496b42e16d43de3896718a6fe3f17c343..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageDrawReqVO.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import lombok.Data; -import org.springframework.ai.openai.OpenAiImageOptions; -import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; - -import java.util.Map; - -@Schema(description = "管理后台 - AI 绘画 Request VO") -@Data -public class AiImageDrawReqVO { - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "模型编号不能为空") - private Long modelId; - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "画一个长城") - @NotEmpty(message = "提示词不能为空") - @Size(max = 1200, message = "提示词最大 1200") - private String prompt; - - /** - * 1. dall-e-2 模型:256x256、512x512、1024x1024 - * 2. dall-e-3 模型:1024x1024, 1792x1024, 或 1024x1792 - */ - @Schema(description = "图片高度") - @NotNull(message = "图片高度不能为空") - private Integer height; - - @Schema(description = "图片宽度") - @NotNull(message = "图片宽度不能为空") - private Integer width; - - // ========== 各平台绘画的拓展参数 ========== - - /** - * 绘制参数,不同 platform 的不同参数 - * - * 1. {@link OpenAiImageOptions} - * 2. {@link StabilityAiImageOptions} - */ - @Schema(description = "绘制参数") - private Map options; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java deleted file mode 100644 index 3b48686b9c31f1cdb2275b1c1dfdb7e395cbba9c..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePageReqVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -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 = "管理后台 - AI 绘画分页 Request VO") -@Data -public class AiImagePageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "28987") - private Long userId; - - @Schema(description = "平台", example = "OpenAI") - private String platform; - - @Schema(description = "提示词", example = "1") - private String prompt; - - @Schema(description = "绘画状态", example = "1") - private Integer status; - - @Schema(description = "是否发布", example = "1") - private Boolean publicStatus; - - @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-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePublicPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePublicPageReqVO.java deleted file mode 100644 index e7ff80a982782fbae3f0d3f2da605c114437ba79..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImagePublicPageReqVO.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘画公开的分页 Request VO") -@Data -public class AiImagePublicPageReqVO extends PageParam { - - @Schema(description = "提示词") - private String prompt; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java deleted file mode 100644 index fa3a957fe9b4e9bf8b6545703f3b42fa17adc64d..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageRespVO.java +++ /dev/null @@ -1,60 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; - -@Schema(description = "管理后台 - AI 绘画 Response VO") -@Data -public class AiImageRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long userId; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - private String platform; // 参见 AiPlatformEnum 枚举 - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "stable-diffusion-v1-6") - private String model; - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "南极的小企鹅") - private String prompt; - - @Schema(description = "图片宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer width; - - @Schema(description = "图片高度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer height; - - @Schema(description = "绘画状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer status; - - @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED, example = "public") - private Boolean publicStatus; - - @Schema(description = "图片地址", example = "https://www.iocoder.cn/1.png") - private String picUrl; - - @Schema(description = "绘画错误信息", example = "图片错误信息") - private String errorMessage; - - @Schema(description = "绘制参数") - private Map options; - - @Schema(description = "mj buttons 按钮") - private List buttons; - - @Schema(description = "完成时间") - private LocalDateTime finishTime; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdateReqVO.java deleted file mode 100644 index 45df01015b0a601dcc9434d0f3720e7abd84d2f5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/AiImageUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘画修改 Request VO") -@Data -public class AiImageUpdateReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "是否发布", example = "true") - private Boolean publicStatus; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java deleted file mode 100644 index 28803a051c28a0d303153e88afc96016c290c67d..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyActionReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘图操作(Midjourney) Request VO") -@Data -public class AiMidjourneyActionReqVO { - - @Schema(description = "图片编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "图片编号不能为空") - private Long id; - - @Schema(description = "操作按钮编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MJ::JOB::variation::4::06aa3e66-0e97-49cc-8201-e0295d883de4") - @NotEmpty(message = "操作按钮编号不能为空") - private String customId; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java deleted file mode 100644 index efb5906157b54aa7a867ef1bd737ce0b0b102d83..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/image/vo/midjourney/AiMidjourneyImagineReqVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.image.vo.midjourney; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 绘画生成(Midjourney) Request VO") -@Data -public class AiMidjourneyImagineReqVO { - - @Schema(description = "提示词", requiredMode = Schema.RequiredMode.REQUIRED, example = "中国神龙") - @NotEmpty(message = "提示词不能为空!") - private String prompt; - - @Schema(description = "模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "模型编号不能为空") - private Long modelId; - - @Schema(description = "图片宽度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "图片宽度不能为空") - private Integer width; - - @Schema(description = "图片高度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "图片高度不能为空") - private Integer height; - - @Schema(description = "版本号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6.0") - @NotEmpty(message = "版本号不能为空") - private String version; - - @Schema(description = "参考图", example = "https://www.iocoder.cn/x.png") - private String referImageUrl; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.http deleted file mode 100644 index a0f127865ac13eb2da5d356f51ef9782e490ccbb..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.http +++ /dev/null @@ -1,35 +0,0 @@ -### 创建知识库 -POST {{baseUrl}}/ai/knowledge/create -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "name": "测试标题", - "description": "测试描述", - "embeddingModelId": 30, - "topK": 3, - "similarityThreshold": 0.5, - "status": 0 -} - -### 更新知识库 -PUT {{baseUrl}}/ai/knowledge/update -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "id": 1, - "name": "测试标题(更新)", - "description": "测试描述", - "embeddingModelId": 30, - "topK": 5, - "similarityThreshold": 0.6, - "status": 0 -} - -### 获取知识库分页 -GET {{baseUrl}}/ai/knowledge/page?pageNo=1&pageSize=10 -Authorization: {{token}} -tenant-id: {{adminTenantId}} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java deleted file mode 100644 index b9daa9513582a867a83fa3e8497cf38efb2285a5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java +++ /dev/null @@ -1,84 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge; - -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.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI 知识库") -@RestController -@RequestMapping("/ai/knowledge") -@Validated -public class AiKnowledgeController { - - @Resource - private AiKnowledgeService knowledgeService; - - @GetMapping("/page") - @Operation(summary = "获取知识库分页") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgePage(@Valid AiKnowledgePageReqVO pageReqVO) { - PageResult pageResult = knowledgeService.getKnowledgePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiKnowledgeRespVO.class)); - } - - @GetMapping("/get") - @Operation(summary = "获得知识库") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult getKnowledge(@RequestParam("id") Long id) { - AiKnowledgeDO knowledge = knowledgeService.getKnowledge(id); - return success(BeanUtils.toBean(knowledge, AiKnowledgeRespVO.class)); - } - - @PostMapping("/create") - @Operation(summary = "创建知识库") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult createKnowledge(@RequestBody @Valid AiKnowledgeSaveReqVO createReqVO) { - return success(knowledgeService.createKnowledge(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新知识库") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledge(@RequestBody @Valid AiKnowledgeSaveReqVO updateReqVO) { - knowledgeService.updateKnowledge(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除知识库") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:knowledge:delete')") - public CommonResult deleteKnowledge(@RequestParam("id") Long id) { - knowledgeService.deleteKnowledge(id); - return success(true); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得知识库的精简列表") - public CommonResult> getKnowledgeSimpleList() { - List list = knowledgeService.getKnowledgeSimpleListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(convertList(list, knowledge -> new AiKnowledgeRespVO() - .setId(knowledge.getId()).setName(knowledge.getName()))); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.http deleted file mode 100644 index 1c858ed3ebcc66e04353a0cee7e0b22dbb42d074..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.http +++ /dev/null @@ -1,35 +0,0 @@ -### 创建知识文档 -POST {{baseUrl}}/ai/knowledge/document/create -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -{ - "knowledgeId": 2, - "name": "测试文档", - "url": "https://static.iocoder.cn/README.md", - "segmentMaxTokens": 800 -} - -### 批量创建知识文档 -POST {{baseUrl}}/ai/knowledge/document/create-list -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -{ - "knowledgeId": 1, - "list": [ - { - "name": "测试文档1", - "url": "https://static.iocoder.cn/README.md", - "segmentMaxTokens": 800 - }, - { - "name": "测试文档2", - "url": "https://static.iocoder.cn/README_yudao.md", - "segmentMaxTokens": 400 - } - ] -} - diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java deleted file mode 100644 index 68fe49a8a70675ddac5723b60a302111b92e5825..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeDocumentController.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge; - -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.ai.controller.admin.knowledge.vo.document.*; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgeDocumentCreateReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - AI 知识库文档") -@RestController -@RequestMapping("/ai/knowledge/document") -@Validated -public class AiKnowledgeDocumentController { - - @Resource - private AiKnowledgeDocumentService documentService; - - @GetMapping("/page") - @Operation(summary = "获取文档分页") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgeDocumentPage( - @Valid AiKnowledgeDocumentPageReqVO pageReqVO) { - PageResult pageResult = documentService.getKnowledgeDocumentPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiKnowledgeDocumentRespVO.class)); - } - - @GetMapping("/get") - @Operation(summary = "获取文档详情") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult getKnowledgeDocument(@RequestParam("id") Long id) { - AiKnowledgeDocumentDO document = documentService.getKnowledgeDocument(id); - return success(BeanUtils.toBean(document, AiKnowledgeDocumentRespVO.class)); - } - - @PostMapping("/create") - @Operation(summary = "新建文档(单个)") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult createKnowledgeDocument(@RequestBody @Valid AiKnowledgeDocumentCreateReqVO reqVO) { - Long id = documentService.createKnowledgeDocument(reqVO); - return success(id); - } - - @PostMapping("/create-list") - @Operation(summary = "新建文档(多个)") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult> createKnowledgeDocumentList( - @RequestBody @Valid AiKnowledgeDocumentCreateListReqVO reqVO) { - List ids = documentService.createKnowledgeDocumentList(reqVO); - return success(ids); - } - - @PutMapping("/update") - @Operation(summary = "更新文档") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeDocument(@Valid @RequestBody AiKnowledgeDocumentUpdateReqVO reqVO) { - documentService.updateKnowledgeDocument(reqVO); - return success(true); - } - - @PutMapping("/update-status") - @Operation(summary = "更新文档状态") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeDocumentStatus( - @Valid @RequestBody AiKnowledgeDocumentUpdateStatusReqVO reqVO) { - documentService.updateKnowledgeDocumentStatus(reqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除文档") - @PreAuthorize("@ss.hasPermission('ai:knowledge:delete')") - public CommonResult deleteKnowledgeDocument(@RequestParam("id") Long id) { - documentService.deleteKnowledgeDocument(id); - return success(true); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.http deleted file mode 100644 index 09018da3dcbf6f13ab34f7a230497a603e9f99c4..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.http +++ /dev/null @@ -1,17 +0,0 @@ -### 切片内容 -GET {{baseUrl}}/ai/knowledge/segment/split?url=https://static.iocoder.cn/README_yudao.md&segmentMaxTokens=800 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -### 搜索段落内容 -GET {{baseUrl}}/ai/knowledge/segment/search?knowledgeId=2&content=如何使用这个产品&topK=5&similarityThreshold=0.1 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} - -### 获取文档处理列表 -GET {{baseUrl}}/ai/knowledge/segment/get-process-list?documentIds=1,2,3 -Content-Type: application/json -Authorization: Bearer {{token}} -tenant-id: {{adminTenantId}} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java deleted file mode 100644 index 34f324491bf8d2a7c7cdbdef16aee1adc6c85462..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeSegmentController.java +++ /dev/null @@ -1,130 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge; - -import cn.hutool.core.collection.CollUtil; -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.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; -import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeSegmentService; -import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchReqBO; -import cn.iocoder.yudao.module.ai.service.knowledge.bo.AiKnowledgeSegmentSearchRespBO; -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.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.hibernate.validator.constraints.URL; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.Collections; -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.convertSet; - -@Tag(name = "管理后台 - AI 知识库段落") -@RestController -@RequestMapping("/ai/knowledge/segment") -@Validated -public class AiKnowledgeSegmentController { - - @Resource - private AiKnowledgeSegmentService segmentService; - @Resource - private AiKnowledgeDocumentService documentService; - - @GetMapping("/get") - @Operation(summary = "获取段落详情") - @Parameter(name = "id", description = "段落编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult getKnowledgeSegment(@RequestParam("id") Long id) { - AiKnowledgeSegmentDO segment = segmentService.getKnowledgeSegment(id); - return success(BeanUtils.toBean(segment, AiKnowledgeSegmentRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获取段落分页") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgeSegmentPage( - @Valid AiKnowledgeSegmentPageReqVO pageReqVO) { - PageResult pageResult = segmentService.getKnowledgeSegmentPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiKnowledgeSegmentRespVO.class)); - } - - @PostMapping("/create") - @Operation(summary = "创建段落") - @PreAuthorize("@ss.hasPermission('ai:knowledge:create')") - public CommonResult createKnowledgeSegment(@Valid @RequestBody AiKnowledgeSegmentSaveReqVO createReqVO) { - return success(segmentService.createKnowledgeSegment(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新段落内容") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeSegment(@Valid @RequestBody AiKnowledgeSegmentSaveReqVO reqVO) { - segmentService.updateKnowledgeSegment(reqVO); - return success(true); - } - - @PutMapping("/update-status") - @Operation(summary = "启禁用段落内容") - @PreAuthorize("@ss.hasPermission('ai:knowledge:update')") - public CommonResult updateKnowledgeSegmentStatus( - @Valid @RequestBody AiKnowledgeSegmentUpdateStatusReqVO reqVO) { - segmentService.updateKnowledgeSegmentStatus(reqVO); - return success(true); - } - - @GetMapping("/split") - @Operation(summary = "切片内容") - @Parameters({ - @Parameter(name = "url", description = "文档 URL", required = true), - @Parameter(name = "segmentMaxTokens", description = "分段的最大 Token 数", required = true) - }) - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> splitContent( - @RequestParam("url") @URL String url, - @RequestParam(value = "segmentMaxTokens") Integer segmentMaxTokens) { - List segments = segmentService.splitContent(url, segmentMaxTokens); - return success(BeanUtils.toBean(segments, AiKnowledgeSegmentRespVO.class)); - } - - @GetMapping("/get-process-list") - @Operation(summary = "获取文档处理列表") - @Parameter(name = "documentIds", description = "文档编号列表", required = true, example = "1,2,3") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> getKnowledgeSegmentProcessList( - @RequestParam("documentIds") List documentIds) { - List list = segmentService.getKnowledgeSegmentProcessList(documentIds); - return success(list); - } - - @GetMapping("/search") - @Operation(summary = "搜索段落内容") - @PreAuthorize("@ss.hasPermission('ai:knowledge:query')") - public CommonResult> searchKnowledgeSegment( - @Valid AiKnowledgeSegmentSearchReqVO reqVO) { - // 1. 搜索段落 - List segments = segmentService - .searchKnowledgeSegment(BeanUtils.toBean(reqVO, AiKnowledgeSegmentSearchReqBO.class)); - if (CollUtil.isEmpty(segments)) { - return success(Collections.emptyList()); - } - - // 2. 拼接 VO - Map documentMap = documentService.getKnowledgeDocumentMap(convertSet( - segments, AiKnowledgeSegmentSearchRespBO::getDocumentId)); - return success(BeanUtils.toBean(segments, AiKnowledgeSegmentSearchRespVO.class, - segment -> MapUtils.findAndThen(documentMap, segment.getDocumentId(), - document -> segment.setDocumentName(document.getName())))); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentCreateListReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentCreateListReqVO.java deleted file mode 100644 index 6545c0bc1cd6c3d0400d4f27e6c291d32f83d112..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentCreateListReqVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import java.util.List; - -@Schema(description = "管理后台 - AI 知识库文档批量创建 Request VO") -@Data -public class AiKnowledgeDocumentCreateListReqVO { - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204") - @NotNull(message = "知识库编号不能为空") - private Long knowledgeId; - - @Schema(description = "分段的最大 Token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "800") - @NotNull(message = "分段的最大 Token 数不能为空") - private Integer segmentMaxTokens; - - @Schema(description = "文档列表", requiredMode = Schema.RequiredMode.REQUIRED) - @NotEmpty(message = "文档列表不能为空") - private List list; - - @Schema(description = "文档") - @Data - public static class Document { - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆") - @NotBlank(message = "文档名称不能为空") - private String name; - - @Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") - @URL(message = "文档 URL 格式不正确") - private String url; - - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java deleted file mode 100644 index 15bb603c213b3cf6fc4c332d0d3ffc74bc4367a5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentPageReqVO.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档的分页 Request VO") -@Data -public class AiKnowledgeDocumentPageReqVO extends PageParam { - - @Schema(description = "知识库编号", example = "1") - private Long knowledgeId; - - @Schema(description = "文档名称", example = "Java 开发手册") - private String name; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java deleted file mode 100644 index 7aef94a3f4f03ee786000954835cba7abd7ce9c9..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentRespVO.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 知识库文档 Response VO") -@Data -public class AiKnowledgeDocumentRespVO { - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long knowledgeId; - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - private String name; - - @Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") - private String url; - - @Schema(description = "文档内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 是一门面向对象的语言.....") - private String content; - - @Schema(description = "文档内容长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") - private Integer contentLength; - - @Schema(description = "文档 Token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer tokens; - - @Schema(description = "分片最大 Token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "512") - private Integer segmentMaxTokens; - - @Schema(description = "召回次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer retrievalCount; - - @Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java deleted file mode 100644 index e6dbe5cbd741249655c1e62a0435581f59323ff5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档更新 Request VO") -@Data -public class AiKnowledgeDocumentUpdateReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "名称", example = "Java 开发手册") - private String name; - - @Schema(description = "分片最大 Token 数", example = "1000") - private Integer segmentMaxTokens; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateStatusReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateStatusReqVO.java deleted file mode 100644 index 93d393ab4a995a3a085df9661f7d100a79909dab..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/document/AiKnowledgeDocumentUpdateStatusReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.document; - -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 jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档更新状态 Request VO") -@Data -public class AiKnowledgeDocumentUpdateStatusReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "状态不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java deleted file mode 100644 index 1d2e49307aa61a5964f9b648dd19508dfe6d520a..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeDocumentCreateReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - - -@Schema(description = "管理后台 - AI 知识库文档的创建 Request VO") -@Data -public class AiKnowledgeDocumentCreateReqVO { - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1204") - @NotNull(message = "知识库编号不能为空") - private Long knowledgeId; - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "三方登陆") - @NotBlank(message = "文档名称不能为空") - private String name; - - @Schema(description = "文档 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://doc.iocoder.cn") - @URL(message = "文档 URL 格式不正确") - private String url; - - @Schema(description = "分段的最大 Token 数", requiredMode = Schema.RequiredMode.REQUIRED, example = "800") - @NotNull(message = "分段的最大 Token 数不能为空") - private Integer segmentMaxTokens; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgePageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgePageReqVO.java deleted file mode 100644 index dc7943cf25ab33fbed6e8029957c32f9421a28c7..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgePageReqVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -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 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 = "管理后台 - AI 知识库的分页 Request VO") -@Data -public class AiKnowledgePageReqVO extends PageParam { - - @Schema(description = "知识库名称", example = "芋艿") - private String name; - - @Schema(description = "是否启用", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java deleted file mode 100644 index 5e83b85a72aa3e525f177d8d7f69873024347277..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeRespVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 知识库 Response VO") -@Data -public class AiKnowledgeRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南") - private String name; - - @Schema(description = "知识库描述", example = "帮助你快速构建系统") - private String description; - - @Schema(description = "向量模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "14") - private Long embeddingModelId; - - @Schema(description = "向量模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "qwen-72b-chat") - private String embeddingModel; - - @Schema(description = "topK", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") - private Integer topK; - - @Schema(description = "相似度阈值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.7") - private Double similarityThreshold; - - @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-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeSaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeSaveReqVO.java deleted file mode 100644 index 774b7234a7464ad5ecdb5cc1b07b06b1fbf063de..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/knowledge/AiKnowledgeSaveReqVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.knowledge; - -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 jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库新增/修改 Request VO") -@Data -public class AiKnowledgeSaveReqVO { - - @Schema(description = "对话编号", example = "1204") - private Long id; - - @Schema(description = "知识库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "ruoyi-vue-pro 用户指南") - @NotBlank(message = "知识库名称不能为空") - private String name; - - @Schema(description = "知识库描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "存储 ruoyi-vue-pro 操作文档") - private String description; - - @Schema(description = "向量模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "向量模型不能为空") - private Long embeddingModelId; - - @Schema(description = "topK", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") - @NotNull(message = "topK 不能为空") - private Integer topK; - - @Schema(description = "相似性阈值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.5") - @NotNull(message = "相似性阈值不能为空") - private Double similarityThreshold; - - @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "是否启用不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java deleted file mode 100644 index f53d5be07617abb7904d7316e7f995b7cdda0b0b..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -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; - -@Schema(description = "管理后台 - AI 知识库分段的分页 Request VO") -@Data -public class AiKnowledgeSegmentPageReqVO extends PageParam { - - @Schema(description = "文档编号", example = "1") - private Integer documentId; - - @Schema(description = "分段内容关键字", example = "Java 开发") - private String content; - - @Schema(description = "分段状态", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentProcessRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentProcessRespVO.java deleted file mode 100644 index a6b95265b76092b276961d783d81b8b8a96a727f..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentProcessRespVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库段落向量进度 Response VO") -@Data -public class AiKnowledgeSegmentProcessRespVO { - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long documentId; - - @Schema(description = "总段落数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Long count; - - @Schema(description = "已向量化段落数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") - private Long embeddingCount; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java deleted file mode 100644 index 24c452621affe9d7bea704055dd814fa55ae00a9..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentRespVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库文档分片 Response VO") -@Data -public class AiKnowledgeSegmentRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "文档编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long documentId; - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long knowledgeId; - - @Schema(description = "向量库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1858496a-1dde-4edf-a43e-0aed08f37f8c") - private String vectorId; - - @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - private String content; - - @Schema(description = "切片内容长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer contentLength; - - @Schema(description = "token 数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - private Integer tokens; - - @Schema(description = "召回次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") - private Integer retrievalCount; - - @Schema(description = "文档状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private Long createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSaveReqVO.java deleted file mode 100644 index 0c5dad11dbf7fc376a72b0af86bd38cf50834c3d..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSaveReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -@Schema(description = "管理后台 - AI 新增/修改知识库段落 request VO") -@Data -public class AiKnowledgeSegmentSaveReqVO { - - @Schema(description = "编号", example = "24790") - private Long id; - - @Schema(description = "知识库文档编号", example = "1024") - private Long documentId; - - @Schema(description = "切片内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发手册") - @NotEmpty(message = "切片内容不能为空") - private String content; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchReqVO.java deleted file mode 100644 index 3b3cd984b9fb52d88d7bc2e473fb0aa331926c83..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchReqVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - AI 知识库段落搜索 Request VO") -@Data -public class AiKnowledgeSegmentSearchReqVO { - - @Schema(description = "知识库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "知识库编号不能为空") - private Long knowledgeId; - - @Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "如何使用这个产品") - @NotEmpty(message = "内容不能为空") - private String content; - - @Schema(description = "最大返回数量", example = "5") - private Integer topK; - - @Schema(description = "相似度阈值", example = "0.7") - private Double similarityThreshold; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchRespVO.java deleted file mode 100644 index 50bbc5c8678abf35f27df8616fff420a47adf387..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentSearchRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - AI 知识库段落搜索 Response VO") -@Data -public class AiKnowledgeSegmentSearchRespVO extends AiKnowledgeSegmentRespVO { - - @Schema(description = "文档名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品使用手册") - private String documentName; - - @Schema(description = "相似度分数", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.95") - private Double score; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java deleted file mode 100644 index 2516c7dfb28f341c6712e47c913d01cf4240b98e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentUpdateStatusReqVO.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment; - -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 jakarta.validation.constraints.NotNull; -import lombok.Data; - - -@Schema(description = "管理后台 - AI 知识库段落的更新状态 Request VO") -@Data -public class AiKnowledgeSegmentUpdateStatusReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "是否启用不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java deleted file mode 100644 index db015e5149425f636ce48e070be903ef1fa37973..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/AiMindMapController.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap; - -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.ai.controller.admin.mindmap.vo.AiMindMapGenerateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo.AiMindMapRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; -import cn.iocoder.yudao.module.ai.service.mindmap.AiMindMapService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 思维导图") -@RestController -@RequestMapping("/ai/mind-map") -public class AiMindMapController { - - @Resource - private AiMindMapService mindMapService; - - @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @Operation(summary = "导图生成(流式)", description = "流式返回,响应较快") - public Flux> generateMindMap(@RequestBody @Valid AiMindMapGenerateReqVO generateReqVO) { - return mindMapService.generateMindMap(generateReqVO, getLoginUserId()); - } - - // ================ 导图管理 ================ - - @DeleteMapping("/delete") - @Operation(summary = "删除思维导图") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:mind-map:delete')") - public CommonResult deleteMindMap(@RequestParam("id") Long id) { - mindMapService.deleteMindMap(id); - return success(true); - } - - @GetMapping("/page") - @Operation(summary = "获得思维导图分页") - @PreAuthorize("@ss.hasPermission('ai:mind-map:query')") - public CommonResult> getMindMapPage(@Valid AiMindMapPageReqVO pageReqVO) { - PageResult pageResult = mindMapService.getMindMapPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiMindMapRespVO.class)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java deleted file mode 100644 index 08404bb0f1c4db45e56894c651bf85cc6dc01fe9..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapGenerateReqVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -@Schema(description = "管理后台 - AI 思维导图生成 Request VO") -@Data -public class AiMindMapGenerateReqVO { - - @Schema(description = "思维导图内容提示", example = "Java 学习路线") - @NotBlank(message = "思维导图内容提示不能为空") - private String prompt; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java deleted file mode 100644 index f7769b4e6b65cef5647f3843bc9bffc31c0c91ab..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapPageReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap.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 = "管理后台 - AI 思维导图分页 Request VO") -@Data -public class AiMindMapPageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "4325") - private Long userId; - - @Schema(description = "生成内容提示", example = "Java 学习路线") - private String prompt; - - @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-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java deleted file mode 100644 index f65e809e91050502d50f766cf798a3344ba243cc..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/mindmap/vo/AiMindMapRespVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.mindmap.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 思维导图 Response VO") -@Data -public class AiMindMapRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3373") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4325") - private Long userId; - - @Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 学习路线") - private String prompt; - - @Schema(description = "生成的思维导图内容") - private String generatedContent; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - private String platform; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java deleted file mode 100644 index c109b033ca0a1e55e5c7b26b0509700b4809321a..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiApiKeyController.java +++ /dev/null @@ -1,83 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -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.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeySaveReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; -import cn.iocoder.yudao.module.ai.service.model.AiApiKeyService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI API 密钥") -@RestController -@RequestMapping("/ai/api-key") -@Validated -public class AiApiKeyController { - - @Resource - private AiApiKeyService apiKeyService; - - @PostMapping("/create") - @Operation(summary = "创建 API 密钥") - @PreAuthorize("@ss.hasPermission('ai:api-key:create')") - public CommonResult createApiKey(@Valid @RequestBody AiApiKeySaveReqVO createReqVO) { - return success(apiKeyService.createApiKey(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新 API 密钥") - @PreAuthorize("@ss.hasPermission('ai:api-key:update')") - public CommonResult updateApiKey(@Valid @RequestBody AiApiKeySaveReqVO updateReqVO) { - apiKeyService.updateApiKey(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除 API 密钥") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:api-key:delete')") - public CommonResult deleteApiKey(@RequestParam("id") Long id) { - apiKeyService.deleteApiKey(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得 API 密钥") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:api-key:query')") - public CommonResult getApiKey(@RequestParam("id") Long id) { - AiApiKeyDO apiKey = apiKeyService.getApiKey(id); - return success(BeanUtils.toBean(apiKey, AiApiKeyRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得 API 密钥分页") - @PreAuthorize("@ss.hasPermission('ai:api-key:query')") - public CommonResult> getApiKeyPage(@Valid AiApiKeyPageReqVO pageReqVO) { - PageResult pageResult = apiKeyService.getApiKeyPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiApiKeyRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得 API 密钥分页列表") - public CommonResult> getApiKeySimpleList() { - List list = apiKeyService.getApiKeyList(); - return success(convertList(list, key -> new AiModelRespVO().setId(key.getId()).setName(key.getName()))); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java deleted file mode 100644 index 804e2115276127b7b51b510c1b30308b5e837b5a..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ /dev/null @@ -1,128 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -import cn.hutool.core.util.ObjUtil; -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.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveMyReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; -import com.fhs.core.trans.anno.TransMethodResult; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 聊天角色") -@RestController -@RequestMapping("/ai/chat-role") -@Validated -public class AiChatRoleController { - - @Resource - private AiChatRoleService chatRoleService; - - @GetMapping("/my-page") - @Operation(summary = "获得【我的】聊天角色分页") - @TransMethodResult - public CommonResult> getChatRoleMyPage(@Valid AiChatRolePageReqVO pageReqVO) { - PageResult pageResult = chatRoleService.getChatRoleMyPage(pageReqVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); - } - - @GetMapping("/get-my") - @Operation(summary = "获得【我的】聊天角色") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @TransMethodResult - public CommonResult getChatRoleMy(@RequestParam("id") Long id) { - AiChatRoleDO chatRole = chatRoleService.getChatRole(id); - if (ObjUtil.notEqual(chatRole.getUserId(), getLoginUserId())) { - return success(null); - } - return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); - } - - @PostMapping("/create-my") - @Operation(summary = "创建【我的】聊天角色") - public CommonResult createChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO createReqVO) { - return success(chatRoleService.createChatRoleMy(createReqVO, getLoginUserId())); - } - - @PutMapping("/update-my") - @Operation(summary = "更新【我的】聊天角色") - public CommonResult updateChatRoleMy(@Valid @RequestBody AiChatRoleSaveMyReqVO updateReqVO) { - chatRoleService.updateChatRoleMy(updateReqVO, getLoginUserId()); - return success(true); - } - - @DeleteMapping("/delete-my") - @Operation(summary = "删除【我的】聊天角色") - @Parameter(name = "id", description = "编号", required = true) - public CommonResult deleteChatRoleMy(@RequestParam("id") Long id) { - chatRoleService.deleteChatRoleMy(id, getLoginUserId()); - return success(true); - } - - @GetMapping("/category-list") - @Operation(summary = "获得聊天角色的分类列表") - public CommonResult> getChatRoleCategoryList() { - return success(chatRoleService.getChatRoleCategoryList()); - } - - // ========== 角色管理 ========== - - @PostMapping("/create") - @Operation(summary = "创建聊天角色") - @PreAuthorize("@ss.hasPermission('ai:chat-role:create')") - public CommonResult createChatRole(@Valid @RequestBody AiChatRoleSaveReqVO createReqVO) { - return success(chatRoleService.createChatRole(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新聊天角色") - @PreAuthorize("@ss.hasPermission('ai:chat-role:update')") - public CommonResult updateChatRole(@Valid @RequestBody AiChatRoleSaveReqVO updateReqVO) { - chatRoleService.updateChatRole(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除聊天角色") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:chat-role:delete')") - public CommonResult deleteChatRole(@RequestParam("id") Long id) { - chatRoleService.deleteChatRole(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得聊天角色") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") - @TransMethodResult - public CommonResult getChatRole(@RequestParam("id") Long id) { - AiChatRoleDO chatRole = chatRoleService.getChatRole(id); - return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得聊天角色分页") - @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") - public CommonResult> getChatRolePage(@Valid AiChatRolePageReqVO pageReqVO) { - PageResult pageResult = chatRoleService.getChatRolePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java deleted file mode 100644 index 86dd4d0a61d5a32c515b10a816999eff75fccba2..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiModelController.java +++ /dev/null @@ -1,89 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -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.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.service.model.AiModelService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI 模型") -@RestController -@RequestMapping("/ai/model") -@Validated -public class AiModelController { - - @Resource - private AiModelService modelService; - - @PostMapping("/create") - @Operation(summary = "创建模型") - @PreAuthorize("@ss.hasPermission('ai:model:create')") - public CommonResult createModel(@Valid @RequestBody AiModelSaveReqVO createReqVO) { - return success(modelService.createModel(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新模型") - @PreAuthorize("@ss.hasPermission('ai:model:update')") - public CommonResult updateModel(@Valid @RequestBody AiModelSaveReqVO updateReqVO) { - modelService.updateModel(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除模型") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:model:delete')") - public CommonResult deleteModel(@RequestParam("id") Long id) { - modelService.deleteModel(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得模型") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:model:query')") - public CommonResult getModel(@RequestParam("id") Long id) { - AiModelDO model = modelService.getModel(id); - return success(BeanUtils.toBean(model, AiModelRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得模型分页") - @PreAuthorize("@ss.hasPermission('ai:model:query')") - public CommonResult> getModelPage(@Valid AiModelPageReqVO pageReqVO) { - PageResult pageResult = modelService.getModelPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiModelRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得模型列表") - @Parameter(name = "type", description = "类型", required = true, example = "1") - @Parameter(name = "platform", description = "平台", example = "midjourney") - public CommonResult> getModelSimpleList( - @RequestParam("type") Integer type, - @RequestParam(value = "platform", required = false) String platform) { - List list = modelService.getModelListByStatusAndType( - CommonStatusEnum.ENABLE.getStatus(), type, platform); - return success(convertList(list, model -> new AiModelRespVO().setId(model.getId()) - .setName(model.getName()).setModel(model.getModel()).setPlatform(model.getPlatform()))); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiToolController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiToolController.java deleted file mode 100644 index e98f87e0b569410c57fe38e06435c3a391892ad7..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiToolController.java +++ /dev/null @@ -1,84 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model; - -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.object.BeanUtils; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolRespVO; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool.AiToolSaveReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO; -import cn.iocoder.yudao.module.ai.service.model.AiToolService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; - -@Tag(name = "管理后台 - AI 工具") -@RestController -@RequestMapping("/ai/tool") -@Validated -public class AiToolController { - - @Resource - private AiToolService toolService; - - @PostMapping("/create") - @Operation(summary = "创建工具") - @PreAuthorize("@ss.hasPermission('ai:tool:create')") - public CommonResult createTool(@Valid @RequestBody AiToolSaveReqVO createReqVO) { - return success(toolService.createTool(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新工具") - @PreAuthorize("@ss.hasPermission('ai:tool:update')") - public CommonResult updateTool(@Valid @RequestBody AiToolSaveReqVO updateReqVO) { - toolService.updateTool(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除工具") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:tool:delete')") - public CommonResult deleteTool(@RequestParam("id") Long id) { - toolService.deleteTool(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得工具") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:tool:query')") - public CommonResult getTool(@RequestParam("id") Long id) { - AiToolDO tool = toolService.getTool(id); - return success(BeanUtils.toBean(tool, AiToolRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得工具分页") - @PreAuthorize("@ss.hasPermission('ai:tool:query')") - public CommonResult> getToolPage(@Valid AiToolPageReqVO pageReqVO) { - PageResult pageResult = toolService.getToolPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiToolRespVO.class)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得工具列表") - public CommonResult> getToolSimpleList() { - List list = toolService.getToolListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(convertList(list, tool -> new AiToolRespVO() - .setId(tool.getId()).setName(tool.getName()))); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java deleted file mode 100644 index 06369624474450ea8d7f2fb58f541e8572d20233..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyPageReqVO.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; - -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 = "管理后台 - AI API 密钥分页 Request VO") -@Data -public class AiApiKeyPageReqVO extends PageParam { - - @Schema(description = "名称", example = "文心一言") - private String name; - - @Schema(description = "平台", example = "OpenAI") - private String platform; - - @Schema(description = "状态", example = "1") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java deleted file mode 100644 index 55d6d802b5398353630c549df91618dccc91f61f..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeyRespVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -@Schema(description = "管理后台 - AI API 密钥 Response VO") -@Data -public class AiApiKeyRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23538") - private Long id; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "文心一言") - private String name; - - @Schema(description = "密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "ABC") - private String apiKey; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - private String platform; - - @Schema(description = "自定义 API 地址", example = "https://aip.baidubce.com") - private String url; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java deleted file mode 100644 index 8fbc8fde785e551baf2056c9f6825576e5e52a49..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/apikey/AiApiKeySaveReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import jakarta.validation.constraints.*; - -@Schema(description = "管理后台 - AI API 密钥新增/修改 Request VO") -@Data -public class AiApiKeySaveReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23538") - private Long id; - - @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "文心一言") - @NotEmpty(message = "名称不能为空") - private String name; - - @Schema(description = "密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "ABC") - @NotEmpty(message = "密钥不能为空") - private String apiKey; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - @NotEmpty(message = "平台不能为空") - private String platform; - - @Schema(description = "自定义 API 地址", example = "https://aip.baidubce.com") - private String url; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "状态不能为空") - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java deleted file mode 100644 index 0a9d08de5946591b51ddf9b2f6b58cb7187eac12..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRolePageReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import lombok.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; - -@Schema(description = "管理后台 - AI 聊天角色分页 Request VO") -@Data -public class AiChatRolePageReqVO extends PageParam { - - @Schema(description = "角色名称", example = "李四") - private String name; - - @Schema(description = "角色类别", example = "创作") - private String category; - - @Schema(description = "是否公开", example = "1") - private Boolean publicStatus; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java deleted file mode 100644 index 2ef9565cc26af276fbb94d1f3def8e850cee8cd4..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleRespVO.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.fhs.core.trans.anno.Trans; -import com.fhs.core.trans.constant.TransType; -import com.fhs.core.trans.vo.VO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天角色 Response VO") -@Data -public class AiChatRoleRespVO implements VO { - - @Schema(description = "角色编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32746") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9442") - private Long userId; - - @Schema(description = "模型编号", example = "17640") - @Trans(type = TransType.SIMPLE, target = AiModelDO.class, fields = { "name", "model" }, refs = { "modelName", "model" }) - private Long modelId; - @Schema(description = "模型名字", example = "张三") - private String modelName; - @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - private String name; - - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - private String avatar; - - @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") - private String category; - - @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer sort; - - @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - private String description; - - @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED) - private String systemMessage; - - @Schema(description = "引用的知识库编号列表", example = "1,2,3") - private List knowledgeIds; - - @Schema(description = "引用的工具编号列表", example = "1,2,3") - private List toolIds; - - @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") - private List mcpClientNames; - - @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Boolean publicStatus; - - @Schema(description = "状态", example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java deleted file mode 100644 index bd4a05723caef97285e609a821da17051c409e4e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveMyReqVO.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天角色新增/修改【我的】 Request VO") -@Data -public class AiChatRoleSaveMyReqVO { - - @Schema(description = "角色编号", example = "32746") - private Long id; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotEmpty(message = "角色名称不能为空") - private String name; - - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - @NotEmpty(message = "角色头像不能为空") - @URL(message = "角色头像必须是 URL 格式") - private String avatar; - - @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - @NotEmpty(message = "角色描述不能为空") - private String description; - - @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") - @NotEmpty(message = "角色设定不能为空") - private String systemMessage; - - @Schema(description = "引用的知识库编号列表", example = "1,2,3") - private List knowledgeIds; - - @Schema(description = "引用的工具编号列表", example = "1,2,3") - private List toolIds; - - @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") - private List mcpClientNames; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java deleted file mode 100644 index 8f2913dd52ddaf54e737cc5ef76edc794c4800e1..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/chatRole/AiChatRoleSaveReqVO.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole; - -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.*; -import jakarta.validation.constraints.*; -import org.hibernate.validator.constraints.URL; - -import java.util.List; - -@Schema(description = "管理后台 - AI 聊天角色新增/修改 Request VO") -@Data -public class AiChatRoleSaveReqVO { - - @Schema(description = "角色编号", example = "32746") - private Long id; - - @Schema(description = "模型编号", example = "17640") - private Long modelId; - - @Schema(description = "角色名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - @NotEmpty(message = "角色名称不能为空") - private String name; - - @Schema(description = "角色头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") - @NotEmpty(message = "角色头像不能为空") - @URL(message = "角色头像必须是 URL 格式") - private String avatar; - - @Schema(description = "角色类别", requiredMode = Schema.RequiredMode.REQUIRED, example = "创作") - @NotEmpty(message = "角色类别不能为空") - private String category; - - @Schema(description = "角色排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "角色排序不能为空") - private Integer sort; - - @Schema(description = "角色描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - @NotEmpty(message = "角色描述不能为空") - private String description; - - @Schema(description = "角色设定", requiredMode = Schema.RequiredMode.REQUIRED, example = "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题") - @NotEmpty(message = "角色设定不能为空") - private String systemMessage; - - @Schema(description = "引用的知识库编号列表", example = "1,2,3") - private List knowledgeIds; - - @Schema(description = "引用的工具编号列表", example = "1,2,3") - private List toolIds; - - @Schema(description = "引用的 MCP Client 名字列表", example = "filesystem") - private List mcpClientNames; - - @Schema(description = "是否公开", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "是否公开不能为空") - private Boolean publicStatus; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "状态不能为空") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java deleted file mode 100644 index af8d1121a427ace58a52895b5429e9e6c03205d5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelPageReqVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import lombok.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; - -@Schema(description = "管理后台 - API 模型分页 Request VO") -@Data -public class AiModelPageReqVO extends PageParam { - - @Schema(description = "模型名字", example = "张三") - private String name; - - @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "模型平台", example = "OpenAI") - private String platform; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java deleted file mode 100644 index b50b70a0876f828950211168cc6b7f1a99b19316..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelRespVO.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 模型 Response VO") -@Data -public class AiModelRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2630") - private Long id; - - @Schema(description = "API 秘钥编号", example = "22042") - private Long keyId; - - @Schema(description = "模型名字", example = "张三") - private String name; - - @Schema(description = "模型标识", example = "gpt-3.5-turbo-0125") - private String model; - - @Schema(description = "模型平台", example = "OpenAI") - private String platform; - - @Schema(description = "模型类型", example = "1") - private Integer type; - - @Schema(description = "排序", example = "1") - private Integer sort; - - @Schema(description = "状态", example = "2") - private Integer status; - - @Schema(description = "温度参数", example = "1") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", example = "8192") - private Integer maxContexts; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java deleted file mode 100644 index 95ed6bf3c2a7c6d6058daa82e955bb6c79c6b03d..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/model/AiModelSaveReqVO.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiModelTypeEnum; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -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 jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - API 模型新增/修改 Request VO") -@Data -public class AiModelSaveReqVO { - - @Schema(description = "编号", example = "2630") - private Long id; - - @Schema(description = "API 秘钥编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22042") - @NotNull(message = "API 秘钥编号不能为空") - private Long keyId; - - @Schema(description = "模型名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - @NotEmpty(message = "模型名字不能为空") - private String name; - - @Schema(description = "模型标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "gpt-3.5-turbo-0125") - @NotEmpty(message = "模型标识不能为空") - private String model; - - @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "OpenAI") - @NotEmpty(message = "模型平台不能为空") - @InEnum(AiPlatformEnum.class) - private String platform; - - @Schema(description = "模型类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "模型类型不能为空") - @InEnum(AiModelTypeEnum.class) - private Integer type; - - @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "排序不能为空") - private Integer sort; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @InEnum(CommonStatusEnum.class) - @NotNull(message = "状态不能为空") - private Integer status; - - @Schema(description = "温度参数", example = "1") - private Double temperature; - - @Schema(description = "单条回复的最大 Token 数量", example = "4096") - private Integer maxTokens; - - @Schema(description = "上下文的最大 Message 数量", example = "8192") - private Integer maxContexts; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolPageReqVO.java deleted file mode 100644 index dc8b04c507f598df923d1c0e09f668affe24e32b..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolPageReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool; - -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; -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 = "管理后台 - AI 工具分页 Request VO") -@Data -public class AiToolPageReqVO extends PageParam { - - @Schema(description = "工具名称", example = "王五") - private String name; - - @Schema(description = "工具描述", example = "你猜") - private String description; - - @Schema(description = "状态", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - - @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-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolRespVO.java deleted file mode 100644 index 6d5a02e6874850623677f70620acc2292b5c36dd..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolRespVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 工具 Response VO") -@Data -public class AiToolRespVO { - - @Schema(description = "工具编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19661") - private Long id; - - @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") - private String name; - - @Schema(description = "工具描述", example = "你猜") - private String description; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolSaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolSaveReqVO.java deleted file mode 100644 index c85cfc33e78566ce8719bd5e6d59d6cfe64c9ca2..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/vo/tool/AiToolSaveReqVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.model.vo.tool; - -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 jakarta.validation.constraints.NotEmpty; -import lombok.Data; - -@Schema(description = "管理后台 - AI 工具新增/修改 Request VO") -@Data -public class AiToolSaveReqVO { - - @Schema(description = "工具编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19661") - private Long id; - - @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") - @NotEmpty(message = "工具名称不能为空") - private String name; - - @Schema(description = "工具描述", example = "你猜") - private String description; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http deleted file mode 100644 index ae68c82ea67e531bc9aa523ab652f064f67a3390..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.http +++ /dev/null @@ -1,26 +0,0 @@ -### 生成音乐:Suno + 歌词模式 -POST {{baseUrl}}/ai/music/generate -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "Suno", - "generateMode": 2, - "prompt": "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。", - "model": "chirp-v3.5", - "tags": ["Happy"], - "title": "Happy Song" -} - -### 生成音乐:Suno + 描述模式 -POST {{baseUrl}}/ai/music/generate -Content-Type: application/json -Authorization: {{token}} - -{ - "platform": "Suno", - "generateMode": 1, - "model": "chirp-v3.5", - "prompt": "happy music", - "makeInstrumental": false -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java deleted file mode 100644 index 6c09e4b30b5ea9195a8347cfbcfe22d8175c6e70..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/AiMusicController.java +++ /dev/null @@ -1,98 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music; - -import cn.hutool.core.util.ObjUtil; -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.ai.controller.admin.music.vo.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; -import cn.iocoder.yudao.module.ai.service.music.AiMusicService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 音乐") -@RestController -@RequestMapping("/ai/music") -public class AiMusicController { - - @Resource - private AiMusicService musicService; - - @GetMapping("/my-page") - @Operation(summary = "获得【我的】音乐分页") - public CommonResult> getMusicMyPage(@Valid AiMusicPageReqVO pageReqVO) { - PageResult pageResult = musicService.getMusicMyPage(pageReqVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, AiMusicRespVO.class)); - } - - @PostMapping("/generate") - @Operation(summary = "音乐生成") - public CommonResult> generateMusic(@RequestBody @Valid AiSunoGenerateReqVO reqVO) { - return success(musicService.generateMusic(getLoginUserId(), reqVO)); - } - - @Operation(summary = "删除【我的】音乐记录") - @DeleteMapping("/delete-my") - @Parameter(name = "id", required = true, description = "音乐编号", example = "1024") - public CommonResult deleteMusicMy(@RequestParam("id") Long id) { - musicService.deleteMusicMy(id, getLoginUserId()); - return success(true); - } - - @GetMapping("/get-my") - @Operation(summary = "获取【我的】音乐") - @Parameter(name = "id", required = true, description = "音乐编号", example = "1024") - public CommonResult getMusicMy(@RequestParam("id") Long id) { - AiMusicDO music = musicService.getMusic(id); - if (music == null || ObjUtil.notEqual(getLoginUserId(), music.getUserId())) { - return success(null); - } - return success(BeanUtils.toBean(music, AiMusicRespVO.class)); - } - - @PostMapping("/update-my") - @Operation(summary = "修改【我的】音乐 目前只支持修改标题") - @Parameter(name = "title", required = true, description = "音乐名称", example = "夜空中最亮的星") - public CommonResult updateMy(AiMusicUpdateMyReqVO updateReqVO) { - musicService.updateMyMusic(updateReqVO, getLoginUserId()); - return success(true); - } - - // ================ 音乐管理 ================ - - @GetMapping("/page") - @Operation(summary = "获得音乐分页") - @PreAuthorize("@ss.hasPermission('ai:music:query')") - public CommonResult> getMusicPage(@Valid AiMusicPageReqVO pageReqVO) { - PageResult pageResult = musicService.getMusicPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiMusicRespVO.class)); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除音乐") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:music:delete')") - public CommonResult deleteMusic(@RequestParam("id") Long id) { - musicService.deleteMusic(id); - return success(true); - } - - @PutMapping("/update") - @Operation(summary = "更新音乐") - @PreAuthorize("@ss.hasPermission('ai:music:update')") - public CommonResult updateMusic(@Valid @RequestBody AiMusicUpdateReqVO updateReqVO) { - musicService.updateMusic(updateReqVO); - return success(true); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java deleted file mode 100644 index e60366faf2bde663f95582ecd338d077227f50cb..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicPageReqVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; -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 = "管理后台 - AI 音乐分页 Request VO") -@Data -public class AiMusicPageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "12212") - private Long userId; - - @Schema(description = "音乐名称", example = "夜空中最亮的星") - private String title; - - @Schema(description = "音乐状态", example = "20") - @InEnum(AiMusicStatusEnum.class) - private Integer status; - - @Schema(description = "生成模式", example = "1") - @InEnum(AiMusicGenerateModeEnum.class) - private Integer generateMode; - - @Schema(description = "是否发布", example = "true") - private Boolean publicStatus; - - @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-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicRespVO.java deleted file mode 100644 index 05044a4e7c24486d7524df9026fb8e858ae34675..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicRespVO.java +++ /dev/null @@ -1,70 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - AI 音乐 Response VO") -@Data -public class AiMusicRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "24790") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12212") - private Long userId; - - @Schema(description = "音乐名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "夜空中最亮的星") - private String title; - - @Schema(description = "歌词", example = "oh~卖糕的") - private String lyric; - - @Schema(description = "图片地址", example = "https://www.iocoder.cn") - private String imageUrl; - - @Schema(description = "音频地址", example = "https://www.iocoder.cn") - private String audioUrl; - - @Schema(description = "视频地址", example = "https://www.iocoder.cn") - private String videoUrl; - - @Schema(description = "音乐状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") - private Integer status; - - @Schema(description = "描述词", example = "一首轻快的歌曲") - private String gptDescriptionPrompt; - - @Schema(description = "提示词", example = "创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。") - private String prompt; - - @Schema(description = "模型平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "Suno") - private String platform; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "chirp-v3.5") - private String model; - - @Schema(description = "生成模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer generateMode; - - @Schema(description = "音乐风格标签") - private List tags; - - @Schema(description = "音乐时长", example = "[\"pop\",\"jazz\",\"punk\"]") - private Double duration; - - @Schema(description = "是否发布", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean publicStatus; - - @Schema(description = "任务编号", example = "11369") - private String taskId; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateMyReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateMyReqVO.java deleted file mode 100644 index 457670115628c6070131aab30bd97c578ede9586..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateMyReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 修改我的音乐 Request VO") -@Data -public class AiMusicUpdateMyReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "音乐名称", example = "夜空中最亮的星") - private String title; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateReqVO.java deleted file mode 100644 index 447bc9765e9304fab7cc1741b5ac19649e9e6986..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiMusicUpdateReqVO.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 音乐修改 Request VO") -@Data -public class AiMusicUpdateReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15583") - @NotNull(message = "编号不能为空") - private Long id; - - @Schema(description = "是否发布", example = "true") - private Boolean publicStatus; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java deleted file mode 100644 index f72d2b54a53388296943ebca5e9f084eb40c634d..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/music/vo/AiSunoGenerateReqVO.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.music.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.util.List; - -@Schema(description = "管理后台 - AI 音乐生成 Request VO") -@Data -public class AiSunoGenerateReqVO { - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "Suno") - @NotBlank(message = "平台不能为空") - private String platform; // 参见 AiPlatformEnum 枚举 - - /** - * 1. 描述模式:描述词 + 是否纯音乐 + 模型 - * 2. 歌词模式:歌词 + 音乐风格 + 标题 + 模型 - */ - @Schema(description = "生成模式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "生成模式不能为空") - private Integer generateMode; // 参见 AiMusicGenerateModeEnum 枚举 - - @Schema(description = "用于生成音乐音频的歌词提示", - example = """ - 1.描述模式:创作一首带有轻松吉他旋律的流行歌曲,[verse] 描述夏日海滩的宁静,[chorus] 节奏加快,表达对自由的向往。 - 2.歌词模式: - [Verse] - 阳光下奔跑 多么欢快 - 假期就要来 心都飞起来 - 朋友在一旁 笑声又灿烂 - 无忧无虑的 每一天甜蜜 - [Chorus] - 马上放假了 快来庆祝 - 一起去旅行 快去冒险 - 日子太短暂 别再等待 - 马上放假了 梦想起飞 - """) - private String prompt; - - @Schema(description = "是否纯音乐", example = "true") - private Boolean makeInstrumental; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "chirp-v3.5") - @NotEmpty(message = "模型不能为空") - private String model; - - @Schema(description = "音乐风格", example = "[\"pop\",\"jazz\",\"punk\"]") - private List tags; - - @Schema(description = "音乐/歌曲名称", example = "夜空中最亮的星") - private String title; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.http b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.http deleted file mode 100644 index 8dc1b0c0f74a03d8eca2d831d522dd573b9f4f92..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.http +++ /dev/null @@ -1,12 +0,0 @@ -### 测试 AI 工作流 -POST {{baseUrl}}/ai/workflow/test -Content-Type: application/json -Authorization: {{token}} -tenant-id: {{adminTenantId}} - -{ - "id": 4, - "params": { - "message": "1 + 1 = ?" - } -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java deleted file mode 100644 index d558d9045434f39ca639ccf290a0d56eb352e746..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/AiWorkflowController.java +++ /dev/null @@ -1,77 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow; - -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.ai.controller.admin.workflow.vo.*; -import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; -import cn.iocoder.yudao.module.ai.service.workflow.AiWorkflowService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - -@Tag(name = "管理后台 - AI 工作流") -@RestController -@RequestMapping("/ai/workflow") -@Slf4j -public class AiWorkflowController { - - @Resource - private AiWorkflowService workflowService; - - @PostMapping("/create") - @Operation(summary = "创建 AI 工作流") - @PreAuthorize("@ss.hasPermission('ai:workflow:create')") - public CommonResult createWorkflow(@Valid @RequestBody AiWorkflowSaveReqVO createReqVO) { - return success(workflowService.createWorkflow(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新 AI 工作流") - @PreAuthorize("@ss.hasPermission('ai:workflow:update')") - public CommonResult updateWorkflow(@Valid @RequestBody AiWorkflowSaveReqVO updateReqVO) { - workflowService.updateWorkflow(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除 AI 工作流") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:workflow:delete')") - public CommonResult deleteWorkflow(@RequestParam("id") Long id) { - workflowService.deleteWorkflow(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得 AI 工作流") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('ai:workflow:query')") - public CommonResult getWorkflow(@RequestParam("id") Long id) { - AiWorkflowDO workflow = workflowService.getWorkflow(id); - return success(BeanUtils.toBean(workflow, AiWorkflowRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得 AI 工作流分页") - @PreAuthorize("@ss.hasPermission('ai:workflow:query')") - public CommonResult> getWorkflowPage(@Valid AiWorkflowPageReqVO pageReqVO) { - PageResult pageResult = workflowService.getWorkflowPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiWorkflowRespVO.class)); - } - - @PostMapping("/test") - @Operation(summary = "测试 AI 工作流") - @PreAuthorize("@ss.hasPermission('ai:workflow:test')") - public CommonResult testWorkflow(@Valid @RequestBody AiWorkflowTestReqVO testReqVO) { - return success(workflowService.testWorkflow(testReqVO)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java deleted file mode 100644 index e55b85ea907b0228d2e86cf95fdb2631f9369778..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowPageReqVO.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -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 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 = "管理后台 - AI 工作流分页 Request VO") -@Data -public class AiWorkflowPageReqVO extends PageParam { - - @Schema(description = "名称", example = "工作流") - private String name; - - @Schema(description = "标识", example = "FLOW") - private String code; - - @Schema(description = "状态", example = "1") - @InEnum(CommonStatusEnum.class) - private Integer status; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java deleted file mode 100644 index e3a28ad648f28c7e1a8966ae61285b91ea4965b1..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowRespVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 工作流 Response VO") -@Data -public class AiWorkflowRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long id; - - @Schema(description = "工作流标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") - private String code; - - @Schema(description = "工作流名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") - private String name; - - @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") - private String remark; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer status; - - @Schema(description = "工作流模型 JSON", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - private String graph; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式") - private LocalDateTime createTime; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java deleted file mode 100644 index 0a63c377321d3d73f3fef0805b9b098a375a7c2b..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowSaveReqVO.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 工作流新增/修改 Request VO") -@Data -public class AiWorkflowSaveReqVO { - - @Schema(description = "编号", example = "1") - private Long id; - - @Schema(description = "工作流标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") - @NotEmpty(message = "工作流标识不能为空") - private String code; - - @Schema(description = "工作流名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "工作流") - @NotEmpty(message = "工作流名称不能为空") - private String name; - - @Schema(description = "备注", example = "FLOW") - private String remark; - - @Schema(description = "工作流模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - @NotEmpty(message = "工作流模型不能为空") - private String graph; - - @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOW") - @NotNull(message = "状态不能为空") - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java deleted file mode 100644 index 37b455cc03366f3e8447711e8005d1750b650be6..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.workflow.vo; - -import cn.hutool.core.util.StrUtil; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.AssertTrue; -import lombok.Data; - -import java.util.Map; - -@Schema(description = "管理后台 - AI 工作流测试 Request VO") -@Data -public class AiWorkflowTestReqVO { - - @Schema(description = "工作流编号", example = "1024") - private Long id; - - @Schema(description = "工作流模型", example = "{}") - private String graph; - - @Schema(description = "参数", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - private Map params; - - @AssertTrue(message = "工作流或模型,必须传递一个") - public boolean isGraphValid() { - return id != null || StrUtil.isNotEmpty(graph); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/AiWriteController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/AiWriteController.java deleted file mode 100644 index 7ef208b9aaa5f98630e9f121cafa86ae99ace079..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/AiWriteController.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write; - -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.ai.controller.admin.write.vo.AiWriteGenerateReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWritePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; -import cn.iocoder.yudao.module.ai.service.write.AiWriteService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; -import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; - -@Tag(name = "管理后台 - AI 写作") -@RestController -@RequestMapping("/ai/write") -public class AiWriteController { - - @Resource - private AiWriteService writeService; - - @PostMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) - @Operation(summary = "写作生成(流式)", description = "流式返回,响应较快") - public Flux> generateWriteContent(@RequestBody @Valid AiWriteGenerateReqVO generateReqVO) { - return writeService.generateWriteContent(generateReqVO, getLoginUserId()); - } - - // ================ 写作管理 ================ - - @DeleteMapping("/delete") - @Operation(summary = "删除写作") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('ai:write:delete')") - public CommonResult deleteWrite(@RequestParam("id") Long id) { - writeService.deleteWrite(id); - return success(true); - } - - @GetMapping("/page") - @Operation(summary = "获得写作分页") - @PreAuthorize("@ss.hasPermission('ai:write:query')") - public CommonResult> getWritePage(@Valid AiWritePageReqVO pageReqVO) { - PageResult pageResult = writeService.getWritePage(pageReqVO); - return success(BeanUtils.toBean(pageResult, AiWriteRespVO.class)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteGenerateReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteGenerateReqVO.java deleted file mode 100644 index 21c60420da434229fbb004004eecc942bd7adba3..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteGenerateReqVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write.vo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -@Schema(description = "管理后台 - AI 写作生成 Request VO") -@Data -public class AiWriteGenerateReqVO { - - @Schema(description = "写作类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @InEnum(value = AiWriteTypeEnum.class, message = "写作类型必须是 {value}") - private Integer type; - - @Schema(description = "写作内容提示", example = "1.撰写:田忌赛马;2.回复:不批") - private String prompt; - - @Schema(description = "原文", example = "领导我要辞职") - private String originalContent; - - @Schema(description = "长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "长度不能为空") - private Integer length; - - @Schema(description = "格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "格式不能为空") - private Integer format; - - @Schema(description = "语气", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "语气不能为空") - private Integer tone; - - @Schema(description = "语言", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "语言不能为空") - private Integer language; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWritePageReqVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWritePageReqVO.java deleted file mode 100644 index 04f99ae13c7a78ea6d2d9eb8f7452fbffa7ca7c3..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWritePageReqVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write.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 = "管理后台 - AI 写作分页 Request VO") -@Data -public class AiWritePageReqVO extends PageParam { - - @Schema(description = "用户编号", example = "28404") - private Long userId; - - @Schema(description = "写作类型", example = "1") - private Integer type; - - @Schema(description = "平台", example = "TongYi") - private String platform; - - @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-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteRespVO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteRespVO.java deleted file mode 100644 index 4160de9ad2e2caa05d3a185febce3089f6b29438..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/write/vo/AiWriteRespVO.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.ai.controller.admin.write.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - AI 写作 Response VO") -@Data -public class AiWriteRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5311") - private Long id; - - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28404") - private Long userId; - - @Schema(description = "写作类型", example = "1") - private Integer type; - - @Schema(description = "平台", requiredMode = Schema.RequiredMode.REQUIRED, example = "TongYi") - private String platform; - - @Schema(description = "模型", requiredMode = Schema.RequiredMode.REQUIRED, example = "qwen") - private String model; - - @Schema(description = "生成内容提示", requiredMode = Schema.RequiredMode.REQUIRED, example = "撰写:田忌赛马") - private String prompt; - - @Schema(description = "生成的内容", example = "你非常不错") - private String generatedContent; - - @Schema(description = "原文", example = "真的么?") - private String originalContent; - - @Schema(description = "长度提示词", example = "1") - private Integer length; - - @Schema(description = "格式提示词", example = "2") - private Integer format; - - @Schema(description = "语气提示词", example = "3") - private Integer tone; - - @Schema(description = "语言提示词", example = "4") - private Integer language; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java deleted file mode 100644 index 05b1ce233cf5897eb426ba3f1dff247f998b10b3..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/app/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * TODO 芋艿:站位,无特殊作用 - */ -package cn.iocoder.yudao.module.ai.controller.app; \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java deleted file mode 100644 index 68dfddfa3edc9f7eedfcdc7336fe703e288cc087..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 RESTful API 给前端: - * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 - * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 - */ -package cn.iocoder.yudao.module.ai.controller; diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java deleted file mode 100644 index 23aec276dbd875624728121066c0e73b9d597f5a..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatConversationDO.java +++ /dev/null @@ -1,100 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.chat; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.time.LocalDateTime; - -/** - * AI Chat 对话 DO - * - * 用户每次发起 Chat 聊天时,会创建一个 {@link AiChatConversationDO} 对象,将它的消息关联在一起 - * - * @author fansili - * @since 2024/4/14 17:35 - */ -@TableName("ai_chat_conversation") -@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiChatConversationDO extends BaseDO { - - public static final String TITLE_DEFAULT = "新对话"; - - /** - * ID 编号,自增 - */ - @TableId - private Long id; - - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 对话标题 - * - * 默认由系统自动生成,可用户手动修改 - */ - private String title; - /** - * 是否置顶 - */ - private Boolean pinned; - /** - * 置顶时间 - */ - private LocalDateTime pinnedTime; - - /** - * 角色编号 - * - * 关联 {@link AiChatRoleDO#getId()} - */ - private Long roleId; - - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} 字段 - */ - private Long modelId; - /** - * 模型标志 - * - * 冗余 {@link AiModelDO#getModel()} 字段 - */ - private String model; - - // ========== 对话配置 ========== - - /** - * 角色设定 - */ - private String systemMessage; - /** - * 温度参数 - * - * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 - */ - private Double temperature; - /** - * 单条回复的最大 Token 数量 - */ - private Integer maxTokens; - /** - * 上下文的最大 Message 数量 - */ - private Integer maxContexts; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java deleted file mode 100644 index 722cc6ecf086318d5d1be8a11209a348e59cd72a..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java +++ /dev/null @@ -1,126 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.chat; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; -import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchResponse; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.ai.chat.messages.MessageType; - -import java.util.List; - -/** - * AI Chat 消息 DO - * - * @since 2024/4/14 17:35 - * @since 2024/4/14 17:35 - */ -@TableName(value = "ai_chat_message", autoResultMap = true) -@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiChatMessageDO extends BaseDO { - - /** - * 编号,作为每条聊天记录的唯一标识符 - */ - @TableId - private Long id; - - /** - * 对话编号 - * - * 关联 {@link AiChatConversationDO#getId()} 字段 - */ - private Long conversationId; - /** - * 回复消息编号 - * - * 关联 {@link #id} 字段 - * - * 大模型回复的消息编号,用于“问答”的关联 - */ - private Long replyId; - - /** - * 消息类型 - * - * 也等价于 OpenAPI 的 role 字段 - * - * 枚举 {@link MessageType} - */ - private String type; - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - /** - * 角色编号 - * - * 关联 {@link AiChatRoleDO#getId()} 字段 - */ - private Long roleId; - - /** - * 模型标志 - * - * 冗余 {@link AiModelDO#getModel()} - */ - private String model; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} 字段 - */ - private Long modelId; - - /** - * 聊天内容 - */ - private String content; - /** - * 推理内容 - */ - private String reasoningContent; - - /** - * 是否携带上下文 - */ - private Boolean useContext; - - /** - * 知识库段落编号数组 - * - * 关联 {@link AiKnowledgeSegmentDO#getId()} 字段 - */ - @TableField(typeHandler = LongListTypeHandler.class) - private List segmentIds; - - /** - * 联网搜索的网页内容数组 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List webSearchPages; - - /** - * 附件 URL 数组 - */ - @TableField(typeHandler = StringListTypeHandler.class) - private List attachmentUrls; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java deleted file mode 100644 index 72acf72df56cbd012ba5ada4d3014758b96ea8e3..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/image/AiImageDO.java +++ /dev/null @@ -1,127 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.image; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.Data; -import org.springframework.ai.openai.OpenAiImageOptions; -import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; - -/** - * AI 绘画 DO - * - * @author fansili - */ -@TableName(value = "ai_image", autoResultMap = true) -@KeySequence("ai_image_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiImageDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - * - * 关联 {@link AdminUserRespDTO#getId()} - */ - private Long userId; - - /** - * 提示词 - */ - private String prompt; - - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long modelId; - /** - * 模型标识 - * - * 冗余 {@link AiModelDO#getModel()} - */ - private String model; - - /** - * 图片宽度 - */ - private Integer width; - /** - * 图片高度 - */ - private Integer height; - - /** - * 生成状态 - * - * 枚举 {@link AiImageStatusEnum} - */ - private Integer status; - - /** - * 完成时间 - */ - private LocalDateTime finishTime; - - /** - * 绘画错误信息 - */ - private String errorMessage; - - /** - * 图片地址 - */ - private String picUrl; - /** - * 是否公开 - */ - private Boolean publicStatus; - - /** - * 绘制参数,不同 platform 的不同参数 - * - * 1. {@link OpenAiImageOptions} - * 2. {@link StabilityAiImageOptions} - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private Map options; - - /** - * mj buttons 按钮 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List buttons; - - /** - * 任务编号 - * - * 1. midjourney proxy:关联的 task id - */ - private String taskId; - -} - diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java deleted file mode 100644 index e1327a50efc147bd54f197229753bff217da32f8..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDO.java +++ /dev/null @@ -1,64 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 知识库 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_knowledge", autoResultMap = true) -@KeySequence("ai_knowledge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiKnowledgeDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 知识库名称 - */ - private String name; - /** - * 知识库描述 - */ - private String description; - - /** - * 向量模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long embeddingModelId; - /** - * 模型标识 - * - * 冗余 {@link AiModelDO#getModel()} - */ - private String embeddingModel; - - /** - * topK - */ - private Integer topK; - /** - * 相似度阈值 - */ - private Double similarityThreshold; - - /** - * 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java deleted file mode 100644 index ac014e926b59cb63d0d5ddb0d77536e7d0050221..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeDocumentDO.java +++ /dev/null @@ -1,69 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -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.Data; - -/** - * AI 知识库-文档 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_knowledge_document") -@KeySequence("ai_knowledge_document_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiKnowledgeDocumentDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 知识库编号 - *

- * 关联 {@link AiKnowledgeDO#getId()} - */ - private Long knowledgeId; - /** - * 文档名称 - */ - private String name; - /** - * 文件 URL - */ - private String url; - /** - * 内容 - */ - private String content; - /** - * 文档长度 - */ - private Integer contentLength; - - /** - * 文档 token 数量 - */ - private Integer tokens; - /** - * 分片最大 Token 数 - */ - private Integer segmentMaxTokens; - - /** - * 召回次数 - */ - private Integer retrievalCount; - - /** - * 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java deleted file mode 100644 index cccbd6846b24b4fcc33c51270570bad5b587147b..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/knowledge/AiKnowledgeSegmentDO.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.knowledge; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -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.Data; - -/** - * AI 知识库-文档分段 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_knowledge_segment") -@KeySequence("ai_knowledge_segment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiKnowledgeSegmentDO extends BaseDO { - - /** - * 向量库的编号 - 空值 - */ - public static final String VECTOR_ID_EMPTY = ""; - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 知识库编号 - *

- * 关联 {@link AiKnowledgeDO#getId()} - */ - private Long knowledgeId; - /** - * 文档编号 - *

- * 关联 {@link AiKnowledgeDocumentDO#getId()} - */ - private Long documentId; - /** - * 切片内容 - */ - private String content; - /** - * 切片内容长度 - */ - private Integer contentLength; - - /** - * 向量库的编号 - */ - private String vectorId; - /** - * token 数量 - */ - private Integer tokens; - - /** - * 召回次数 - */ - private Integer retrievalCount; - - /** - * 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java deleted file mode 100644 index db788b7e83b3e16cf7f4c48ee07c9949cc7d52a0..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/mindmap/AiMindMapDO.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.mindmap; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 思维导图 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_mind_map") -@KeySequence("ai_mind_map_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiMindMapDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - *

- * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 平台 - *

- * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long modelId; - /** - * 模型 - */ - private String model; - - /** - * 生成内容提示 - */ - private String prompt; - - /** - * 生成的内容 - */ - private String generatedContent; - - /** - * 错误信息 - */ - private String errorMessage; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java deleted file mode 100644 index f2c683a5035e48617066862823898b71713426c3..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiApiKeyDO.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -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.*; - -/** - * AI API 秘钥 DO - * - * @author 芋道源码 - */ -@TableName("ai_api_key") -@KeySequence("ai_chat_conversation_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiApiKeyDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 名称 - */ - private String name; - /** - * 密钥 - */ - private String apiKey; - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * API 地址 - */ - private String url; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java deleted file mode 100644 index d20b25e88484ffaa7ddc2633594c4301f3218268..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiChatRoleDO.java +++ /dev/null @@ -1,111 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; -import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.util.List; - -/** - * AI 聊天角色 DO - * - * @author fansili - * @since 2024/4/24 19:39 - */ -@TableName(value = "ai_chat_role", autoResultMap = true) -@KeySequence("ai_chat_role_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiChatRoleDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 角色名称 - */ - private String name; - /** - * 角色头像 - */ - private String avatar; - /** - * 角色分类 - */ - private String category; - /** - * 角色描述 - */ - private String description; - /** - * 角色设定 - */ - private String systemMessage; - - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} 字段 - */ - private Long modelId; - - /** - * 引用的知识库编号列表 - * - * 关联 {@link AiKnowledgeDO#getId()} 字段 - */ - @TableField(typeHandler = LongListTypeHandler.class) - private List knowledgeIds; - /** - * 引用的工具编号列表 - * - * 关联 {@link AiToolDO#getId()} 字段 - */ - @TableField(typeHandler = LongListTypeHandler.class) - private List toolIds; - /** - * 引用的 MCP Client 名字列表 - * - * 关联 spring.ai.mcp.client 下的名字 - */ - @TableField(typeHandler = StringListTypeHandler.class) - private List mcpClientNames; - - /** - * 是否公开 - * - * 1. true - 公开;由管理员在【角色管理】所创建 - * 2. false - 私有;由个人在【我的角色】所创建 - */ - private Boolean publicStatus; - - /** - * 排序值 - */ - private Integer sort; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java deleted file mode 100644 index 9e54f94c5ab18dc276054d83bb0d13ad3a467426..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiModelDO.java +++ /dev/null @@ -1,88 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiModelTypeEnum; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -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.*; - -/** - * AI 模型 DO - * - * 默认模型:{@link #status} 为开启,并且 {@link #sort} 排序第一 - * - * @author fansili - * @since 2024/4/24 19:39 - */ -@TableName("ai_model") -@KeySequence("ai_model_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiModelDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * API 秘钥编号 - * - * 关联 {@link AiApiKeyDO#getId()} - */ - private Long keyId; - /** - * 模型名称 - */ - private String name; - /** - * 模型标志 - */ - private String model; - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 类型 - * - * 枚举 {@link AiModelTypeEnum} - */ - private Integer type; - - /** - * 排序值 - */ - private Integer sort; - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - - // ========== 对话配置 ========== - - /** - * 温度参数 - * - * 用于调整生成回复的随机性和多样性程度:较低的温度值会使输出更收敛于高频词汇,较高的则增加多样性 - */ - private Double temperature; - /** - * 单条回复的最大 Token 数量 - */ - private Integer maxTokens; - /** - * 上下文的最大 Message 数量 - */ - private Integer maxContexts; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiToolDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiToolDO.java deleted file mode 100644 index 71322132f369f38a0b7e769da5630fa0d5f71743..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/model/AiToolDO.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.model; - -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.tool.function.DirectoryListToolFunction; -import cn.iocoder.yudao.module.ai.tool.function.WeatherQueryToolFunction; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * AI 工具 DO - * - * @author 芋道源码 - */ -@TableName("ai_tool") -@KeySequence("ai_tool_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class AiToolDO extends BaseDO { - - /** - * 工具编号 - */ - @TableId - private Long id; - /** - * 工具名称 - * - * 对应 Bean 的名字,例如说: - * 1. {@link DirectoryListToolFunction} 的 Bean 名字是 directory_list - * 2. {@link WeatherQueryToolFunction} 的 Bean 名字是 weather_query - */ - private String name; - /** - * 工具描述 - */ - private String description; - /** - * 状态 - * - * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} - */ - private Integer status; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java deleted file mode 100644 index cc16133a708a5ef203b17318b1f4db532581804f..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/music/AiMusicDO.java +++ /dev/null @@ -1,119 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.music; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicGenerateModeEnum; -import cn.iocoder.yudao.module.ai.enums.music.AiMusicStatusEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; -import lombok.Data; - -import java.util.List; - -/** - * AI 音乐 DO - * - * @author xiaoxin - */ -@TableName(value = "ai_music", autoResultMap = true) -@KeySequence("ai_music_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiMusicDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - *

- * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 音乐名称 - */ - private String title; - - /** - * 歌词 - */ - private String lyric; - - /** - * 图片地址 - */ - private String imageUrl; - /** - * 音频地址 - */ - private String audioUrl; - /** - * 视频地址 - */ - private String videoUrl; - - /** - * 音乐状态 - *

- * 枚举 {@link AiMusicStatusEnum} - */ - private Integer status; - - /** - * 生成模式 - *

- * 枚举 {@link AiMusicGenerateModeEnum} - */ - private Integer generateMode; - - /** - * 描述词 - */ - private String description; - - /** - * 平台 - *

- * 枚举 {@link AiPlatformEnum} - */ - private String platform; - // TODO @芋艿:modelId? - /** - * 模型 - */ - private String model; - - /** - * 音乐风格标签 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private List tags; - - /** - * 音乐时长 - */ - private Double duration; - - /** - * 是否公开 - */ - private Boolean publicStatus; - - /** - * 任务编号 - */ - private String taskId; - - /** - * 错误信息 - */ - private String errorMessage; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java deleted file mode 100644 index d844f7da2ef0f789599bdde4559ed43c8842bd0f..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/workflow/AiWorkflowDO.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.workflow; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -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.Data; - -/** - * AI 工作流 DO - * - * @author lesan - */ -@TableName(value = "ai_workflow", autoResultMap = true) -@KeySequence("ai_workflow") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiWorkflowDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 工作流名称 - */ - private String name; - /** - * 工作流标识 - */ - private String code; - - /** - * 工作流模型 JSON 数据 - */ - private String graph; - - /** - * 备注 - */ - private String remark; - - /** - * 状态 - * - * 枚举 {@link CommonStatusEnum} - */ - private Integer status; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java deleted file mode 100644 index 75e1e29cef77d16a7fe17239a06843212886258d..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/write/AiWriteDO.java +++ /dev/null @@ -1,104 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.dataobject.write; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import cn.iocoder.yudao.module.ai.enums.DictTypeConstants; -import cn.iocoder.yudao.module.ai.enums.write.AiWriteTypeEnum; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * AI 写作 DO - * - * @author xiaoxin - */ -@TableName("ai_write") -@KeySequence("ai_write_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -public class AiWriteDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - - /** - * 用户编号 - * - * 关联 AdminUserDO 的 userId 字段 - */ - private Long userId; - - /** - * 写作类型 - *

- * 枚举 {@link AiWriteTypeEnum} - */ - private Integer type; - - /** - * 平台 - * - * 枚举 {@link AiPlatformEnum} - */ - private String platform; - /** - * 模型编号 - * - * 关联 {@link AiModelDO#getId()} - */ - private Long modelId; - /** - * 模型 - */ - private String model; - - /** - * 生成内容提示 - */ - private String prompt; - - /** - * 生成的内容 - */ - private String generatedContent; - /** - * 原文 - */ - private String originalContent; - - /** - * 长度提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_LENGTH} - */ - private Integer length; - /** - * 格式提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_FORMAT} - */ - private Integer format; - /** - * 语气提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_TONE} - */ - private Integer tone; - /** - * 语言提示词 - * - * 字典:{@link DictTypeConstants#AI_WRITE_LANGUAGE} - */ - private Integer language; - - /** - * 错误信息 - */ - private String errorMessage; - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java deleted file mode 100644 index ce9da2f24dd373754d0046db0fdbb6ddb4cea50f..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatConversationMapper.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.chat; - -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.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 聊天对话 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface AiChatConversationMapper extends BaseMapperX { - - default List selectListByUserId(Long userId) { - return selectList(AiChatConversationDO::getUserId, userId); - } - - default List selectListByUserIdAndPinned(Long userId, boolean pinned) { - return selectList(new LambdaQueryWrapperX() - .eq(AiChatConversationDO::getUserId, userId) - .eq(AiChatConversationDO::getPinned, pinned)); - } - - default PageResult selectChatConversationPage(AiChatConversationPageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiChatConversationDO::getUserId, pageReqVO.getUserId()) - .likeIfPresent(AiChatConversationDO::getTitle, pageReqVO.getTitle()) - .betweenIfPresent(AiChatConversationDO::getCreateTime, pageReqVO.getCreateTime()) - .orderByDesc(AiChatConversationDO::getId)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java deleted file mode 100644 index 5020f3944ee0bb1ef3541a946cf2f27436e71ea8..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.chat; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; -import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * AI 聊天对话 Mapper - * - * @author fansili - */ -@Mapper -public interface AiChatMessageMapper extends BaseMapperX { - - default List selectListByConversationId(Long conversationId) { - return selectList(new LambdaQueryWrapperX() - .eq(AiChatMessageDO::getConversationId, conversationId) - .orderByAsc(AiChatMessageDO::getId)); - } - - default Map selectCountMapByConversationId(Collection conversationIds) { - // SQL count 查询 - List> result = selectMaps(new QueryWrapper() - .select("COUNT(id) AS count, conversation_id AS conversationId") - .in("conversation_id", conversationIds) - .groupBy("conversation_id")); - if (CollUtil.isEmpty(result)) { - return Collections.emptyMap(); - } - // 转换数据 - return CollectionUtils.convertMap(result, - record -> MapUtil.getLong(record, "conversationId"), - record -> MapUtil.getInt(record, "count" )); - } - - default PageResult selectPage(AiChatMessagePageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiChatMessageDO::getConversationId, pageReqVO.getConversationId()) - .eqIfPresent(AiChatMessageDO::getUserId, pageReqVO.getUserId()) - .likeIfPresent(AiChatMessageDO::getContent, pageReqVO.getContent()) - .betweenIfPresent(AiChatMessageDO::getCreateTime, pageReqVO.getCreateTime()) - .orderByDesc(AiChatMessageDO::getId)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java deleted file mode 100644 index f87c9472bc9bf78550b84fd02ca8369e69fe1ffc..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/image/AiImageMapper.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.image; - -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.ai.controller.admin.image.vo.AiImagePageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImagePublicPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 绘图 Mapper - * - * @author fansili - */ -@Mapper -public interface AiImageMapper extends BaseMapperX { - - default AiImageDO selectByTaskId(String taskId) { - return selectOne(AiImageDO::getTaskId, taskId); - } - - default PageResult selectPage(AiImagePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiImageDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiImageDO::getPlatform, reqVO.getPlatform()) - .eqIfPresent(AiImageDO::getStatus, reqVO.getStatus()) - .eqIfPresent(AiImageDO::getPublicStatus, reqVO.getPublicStatus()) - .betweenIfPresent(AiImageDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiImageDO::getId)); - } - - default PageResult selectPageMy(Long userId, AiImagePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiImageDO::getPrompt, reqVO.getPrompt()) - // 情况一:公开 - .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiImageDO::getPublicStatus, reqVO.getPublicStatus()) - // 情况二:私有 - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiImageDO::getUserId, userId) - .orderByDesc(AiImageDO::getId)); - } - - default PageResult selectPage(AiImagePublicPageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiImageDO::getPublicStatus, Boolean.TRUE) - .likeIfPresent(AiImageDO::getPrompt, pageReqVO.getPrompt()) - .orderByDesc(AiImageDO::getId)); - } - - default List selectListByStatusAndPlatform(Integer status, String platform) { - return selectList(AiImageDO::getStatus, status, - AiImageDO::getPlatform, platform); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java deleted file mode 100644 index 55f04bb3280926286456c8894ea30a7941151398..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; - -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.ai.controller.admin.knowledge.vo.document.AiKnowledgeDocumentPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDocumentDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -/** - * AI 知识库文档 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiKnowledgeDocumentMapper extends BaseMapperX { - - default PageResult selectPage(AiKnowledgeDocumentPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiKnowledgeDocumentDO::getKnowledgeId, reqVO.getKnowledgeId()) - .likeIfPresent(AiKnowledgeDocumentDO::getName, reqVO.getName()) - .orderByDesc(AiKnowledgeDocumentDO::getId)); - } - - default void updateRetrievalCountIncr(Collection ids) { - update(new LambdaUpdateWrapper() - .setSql(" retrieval_count = retrieval_count + 1") - .in(AiKnowledgeDocumentDO::getId, ids)); - } - - default List selectListByStatus(Integer status) { - return selectList(AiKnowledgeDocumentDO::getStatus, status); - } - - default List selectListByKnowledgeId(Long knowledgeId) { - return selectList(AiKnowledgeDocumentDO::getKnowledgeId, knowledgeId); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java deleted file mode 100644 index 3433c0b9737707ea66659667c94c5613f3613d63..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; - -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.ai.controller.admin.knowledge.vo.knowledge.AiKnowledgePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 知识库 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiKnowledgeMapper extends BaseMapperX { - - default PageResult selectPage(AiKnowledgePageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiKnowledgeDO::getName, pageReqVO.getName()) - .eqIfPresent(AiKnowledgeDO::getStatus, pageReqVO.getStatus()) - .betweenIfPresent(AiKnowledgeDO::getCreateTime, pageReqVO.getCreateTime()) - .orderByDesc(AiKnowledgeDO::getId)); - } - - default List selectListByStatus(Integer status) { - return selectList(AiKnowledgeDO::getStatus, status); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java deleted file mode 100644 index 1b9ca867f5f29e9b831dcb04c3d7bb835aadfd6e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.knowledge; - -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.framework.mybatis.core.query.MPJLambdaWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentPageReqVO; -import cn.iocoder.yudao.module.ai.controller.admin.knowledge.vo.segment.AiKnowledgeSegmentProcessRespVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.knowledge.AiKnowledgeSegmentDO; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.github.yulichang.wrapper.MPJLambdaWrapper; -import org.apache.ibatis.annotations.Mapper; - -import java.util.Collection; -import java.util.List; - -/** - * AI 知识库分片 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiKnowledgeSegmentMapper extends BaseMapperX { - - default PageResult selectPage(AiKnowledgeSegmentPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eq(AiKnowledgeSegmentDO::getDocumentId, reqVO.getDocumentId()) - .likeIfPresent(AiKnowledgeSegmentDO::getContent, reqVO.getContent()) - .eqIfPresent(AiKnowledgeSegmentDO::getStatus, reqVO.getStatus()) - .orderByDesc(AiKnowledgeSegmentDO::getId)); - } - - default List selectListByVectorIds(List vectorIds) { - return selectList(new LambdaQueryWrapperX() - .in(AiKnowledgeSegmentDO::getVectorId, vectorIds) - .orderByDesc(AiKnowledgeSegmentDO::getId)); - } - - default List selectListByDocumentId(Long documentId) { - return selectList(new LambdaQueryWrapperX() - .eq(AiKnowledgeSegmentDO::getDocumentId, documentId) - .orderByDesc(AiKnowledgeSegmentDO::getId)); - } - - default List selectListByKnowledgeIdAndStatus(Long knowledgeId, Integer status) { - return selectList(AiKnowledgeSegmentDO::getKnowledgeId, knowledgeId, - AiKnowledgeSegmentDO::getStatus, status); - } - - default List selectProcessList(Collection documentIds) { - MPJLambdaWrapper wrapper = new MPJLambdaWrapperX() - .selectAs(AiKnowledgeSegmentDO::getDocumentId, AiKnowledgeSegmentProcessRespVO::getDocumentId) - .selectCount(AiKnowledgeSegmentDO::getId, "count") - .select("COUNT(CASE WHEN vector_id > '" + AiKnowledgeSegmentDO.VECTOR_ID_EMPTY - + "' THEN 1 ELSE NULL END) AS embeddingCount") - .in(AiKnowledgeSegmentDO::getDocumentId, documentIds) - .groupBy(AiKnowledgeSegmentDO::getDocumentId); - return selectJoinList(AiKnowledgeSegmentProcessRespVO.class, wrapper); - } - - default void updateRetrievalCountIncrByIds(List ids) { - update(new LambdaUpdateWrapper() - .setSql(" retrieval_count = retrieval_count + 1") - .in(AiKnowledgeSegmentDO::getId, ids)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java deleted file mode 100644 index 0292ef473d414551e85ed5fdf81ae242ee30b3ed..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/mindmap/AiMindMapMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.mindmap; - -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.ai.controller.admin.mindmap.vo.AiMindMapPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.mindmap.AiMindMapDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 思维导图 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiMindMapMapper extends BaseMapperX { - - default PageResult selectPage(AiMindMapPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiMindMapDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiMindMapDO::getPrompt, reqVO.getPrompt()) - .betweenIfPresent(AiMindMapDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiMindMapDO::getId)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java deleted file mode 100644 index 0a2efe36f80ee7dda496cc40ad01194d3c5198b5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiApiKeyMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -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.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.apikey.AiApiKeyPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI API 密钥 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface AiApiKeyMapper extends BaseMapperX { - - default PageResult selectPage(AiApiKeyPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiApiKeyDO::getName, reqVO.getName()) - .eqIfPresent(AiApiKeyDO::getPlatform, reqVO.getPlatform()) - .eqIfPresent(AiApiKeyDO::getStatus, reqVO.getStatus()) - .orderByDesc(AiApiKeyDO::getId)); - } - - default AiApiKeyDO selectFirstByPlatformAndStatus(String platform, Integer status) { - return selectOne(new QueryWrapperX() - .eq("platform", platform) - .eq("status", status) - .limitN(1) - .orderByAsc("id")); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java deleted file mode 100644 index bfe2caf52aaec690ab06a174cacc67c315fd5862..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatMapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -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.framework.mybatis.core.query.QueryWrapperX; -import cn.iocoder.yudao.module.ai.controller.admin.model.vo.model.AiModelPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; -import org.apache.ibatis.annotations.Mapper; - -import javax.annotation.Nullable; -import java.util.List; - -/** - * API 模型 Mapper - * - * @author fansili - */ -@Mapper -public interface AiChatMapper extends BaseMapperX { - - default AiModelDO selectFirstByStatus(Integer type, Integer status) { - return selectOne(new QueryWrapperX() - .eq("type", type) - .eq("status", status) - .limitN(1) - .orderByAsc("sort")); - } - - default PageResult selectPage(AiModelPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiModelDO::getName, reqVO.getName()) - .eqIfPresent(AiModelDO::getModel, reqVO.getModel()) - .eqIfPresent(AiModelDO::getPlatform, reqVO.getPlatform()) - .orderByAsc(AiModelDO::getSort)); - } - - default List selectListByStatusAndType(Integer status, Integer type, - @Nullable String platform) { - return selectList(new LambdaQueryWrapperX() - .eq(AiModelDO::getStatus, status) - .eq(AiModelDO::getType, type) - .eqIfPresent(AiModelDO::getPlatform, platform) - .orderByAsc(AiModelDO::getSort)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java deleted file mode 100644 index ed91edf3facaf35856623cf8c8cddcb9e6eb4b0b..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiChatRoleMapper.java +++ /dev/null @@ -1,54 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -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.ai.controller.admin.model.vo.chatRole.AiChatRolePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 聊天角色 Mapper - * - * @author fansili - */ -@Mapper -public interface AiChatRoleMapper extends BaseMapperX { - - default PageResult selectPage(AiChatRolePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) - .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) - .eqIfPresent(AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) - .orderByAsc(AiChatRoleDO::getSort)); - } - - default PageResult selectPageByMy(AiChatRolePageReqVO reqVO, Long userId) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiChatRoleDO::getName, reqVO.getName()) - .eqIfPresent(AiChatRoleDO::getCategory, reqVO.getCategory()) - // 情况一:公开 - .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getPublicStatus, reqVO.getPublicStatus()) - // 情况二:私有 - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getUserId, userId) - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiChatRoleDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) - .orderByAsc(AiChatRoleDO::getSort)); - } - - default List selectListGroupByCategory(Integer status) { - return selectList(new LambdaQueryWrapperX() - .select(AiChatRoleDO::getCategory) - .eq(AiChatRoleDO::getStatus, status) - .groupBy(AiChatRoleDO::getCategory)); - } - - default List selectListByName(String name) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(AiChatRoleDO::getName, name) - .orderByAsc(AiChatRoleDO::getSort)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiToolMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiToolMapper.java deleted file mode 100644 index d5d296692a8a7849504b2853aa5bacebd0a05fe2..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/model/AiToolMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.model; - -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.ai.controller.admin.model.vo.tool.AiToolPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 工具 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface AiToolMapper extends BaseMapperX { - - default PageResult selectPage(AiToolPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(AiToolDO::getName, reqVO.getName()) - .eqIfPresent(AiToolDO::getDescription, reqVO.getDescription()) - .eqIfPresent(AiToolDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(AiToolDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiToolDO::getId)); - } - - default List selectListByStatus(Integer status) { - return selectList(new LambdaQueryWrapperX() - .eq(AiToolDO::getStatus, status) - .orderByDesc(AiToolDO::getId)); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/music/AiMusicMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/music/AiMusicMapper.java deleted file mode 100644 index 025f5e0185cfae382ac16928e732cc168e44852f..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/music/AiMusicMapper.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.music; - -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.ai.controller.admin.music.vo.AiMusicPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.music.AiMusicDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * AI 音乐 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiMusicMapper extends BaseMapperX { - - default List selectListByStatus(Integer status) { - return selectList(AiMusicDO::getStatus, status); - } - - default PageResult selectPage(AiMusicPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiMusicDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiMusicDO::getTitle, reqVO.getTitle()) - .eqIfPresent(AiMusicDO::getStatus, reqVO.getStatus()) - .eqIfPresent(AiMusicDO::getGenerateMode, reqVO.getGenerateMode()) - .betweenIfPresent(AiMusicDO::getCreateTime, reqVO.getCreateTime()) - .eqIfPresent(AiMusicDO::getPublicStatus, reqVO.getPublicStatus()) - .orderByDesc(AiMusicDO::getId)); - } - - default PageResult selectPageByMy(AiMusicPageReqVO reqVO, Long userId) { - return selectPage(reqVO, new LambdaQueryWrapperX() - // 情况一:公开 - .eq(Boolean.TRUE.equals(reqVO.getPublicStatus()), AiMusicDO::getPublicStatus, reqVO.getPublicStatus()) - // 情况二:私有 - .eq(Boolean.FALSE.equals(reqVO.getPublicStatus()), AiMusicDO::getUserId, userId) - .orderByAsc(AiMusicDO::getId)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java deleted file mode 100644 index 3770dbf0b554862d8beaff9a03f3ba07629bb06e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/workflow/AiWorkflowMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.workflow; - -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.ai.controller.admin.workflow.vo.AiWorkflowPageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.workflow.AiWorkflowDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 工作流 Mapper - * - * @author lesan - */ -@Mapper -public interface AiWorkflowMapper extends BaseMapperX { - - default AiWorkflowDO selectByCode(String code) { - return selectOne(AiWorkflowDO::getCode, code); - } - - default PageResult selectPage(AiWorkflowPageReqVO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiWorkflowDO::getStatus, pageReqVO.getStatus()) - .likeIfPresent(AiWorkflowDO::getName, pageReqVO.getName()) - .likeIfPresent(AiWorkflowDO::getCode, pageReqVO.getCode()) - .betweenIfPresent(AiWorkflowDO::getCreateTime, pageReqVO.getCreateTime())); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/write/AiWriteMapper.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/write/AiWriteMapper.java deleted file mode 100644 index c4983eb44405175108dc992d292cecd820c0c852..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/write/AiWriteMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.ai.dal.mysql.write; - -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.ai.controller.admin.write.vo.AiWritePageReqVO; -import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 写作 Mapper - * - * @author xiaoxin - */ -@Mapper -public interface AiWriteMapper extends BaseMapperX { - - default PageResult selectPage(AiWritePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(AiWriteDO::getUserId, reqVO.getUserId()) - .eqIfPresent(AiWriteDO::getType, reqVO.getType()) - .eqIfPresent(AiWriteDO::getPlatform, reqVO.getPlatform()) - .betweenIfPresent(AiWriteDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(AiWriteDO::getId)); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java deleted file mode 100644 index 1479274959525331498ee94ed3fdb2bbc51735df..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/AiChatRoleEnum.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI 内置聊天角色的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiChatRoleEnum { - - AI_WRITE_ROLE("写作助手", """ - 你是一位出色的写作助手,能够帮助用户生成创意和灵感,并在用户提供场景和提示词时生成对应的回复。你的任务包括: - 1. 撰写建议:根据用户提供的主题或问题,提供详细的写作建议、情节发展方向、角色设定以及背景描写,确保内容结构清晰、有逻辑。 - 2. 回复生成:根据用户提供的场景和提示词,生成合适的对话或文字回复,确保语气和风格符合场景需求。 - 除此之外不需要除了正文内容外的其他回复,如标题、开头、任何解释性语句或道歉。 - """), - - AI_MIND_MAP_ROLE("导图助手", """ - 你是一位非常优秀的思维导图助手,你会把用户的所有提问都总结成思维导图,然后以 Markdown 格式输出。markdown 只需要输出一级标题,二级标题,三级标题,四级标题,最多输出四级,除此之外不要输出任何其他 markdown 标记。下面是一个合格的例子: - # Geek-AI 助手 - ## 完整的开源系统 - ### 前端开源 - ### 后端开源 - ## 支持各种大模型 - ### OpenAI - ### Azure - ### 文心一言 - ### 通义千问 - ## 集成多种收费方式 - ### 支付宝 - ### 微信 - 除此之外不要任何解释性语句。 - """), - ; - - /** - * 角色名 - */ - private final String name; - - /** - * 角色设定 - */ - private final String systemMessage; - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/DictTypeConstants.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/DictTypeConstants.java deleted file mode 100644 index 73782a2cbbf649ecc6275b8933645c3d6530d8e2..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/DictTypeConstants.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -/** - * AI 字典类型的枚举类 - * - * @author xiaoxin - */ -public interface DictTypeConstants { - - // ========== AI Write ========== - String AI_WRITE_FORMAT = "ai_write_format"; // 写作格式 - String AI_WRITE_LENGTH = "ai_write_length"; // 写作长度 - String AI_WRITE_LANGUAGE = "ai_write_language"; // 写作语言 - String AI_WRITE_TONE = "ai_write_tone"; // 写作语气 - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java deleted file mode 100644 index 8a8a3883244271346f713d3e2932754305338e23..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/ErrorCodeConstants.java +++ /dev/null @@ -1,68 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * AI 错误码枚举类 - *

- * ai 系统,使用 1-040-000-000 段 - */ -public interface ErrorCodeConstants { - - // ========== API 密钥 1-040-000-000 ========== - ErrorCode API_KEY_NOT_EXISTS = new ErrorCode(1_040_000_000, "API 密钥不存在"); - ErrorCode API_KEY_DISABLE = new ErrorCode(1_040_000_001, "API 密钥已禁用!"); - - // ========== API 模型 1-040-001-000 ========== - ErrorCode MODEL_NOT_EXISTS = new ErrorCode(1_040_001_000, "模型不存在!"); - ErrorCode MODEL_DISABLE = new ErrorCode(1_040_001_001, "模型({})已禁用!"); - ErrorCode MODEL_DEFAULT_NOT_EXISTS = new ErrorCode(1_040_001_002, "操作失败,找不到默认模型"); - ErrorCode MODEL_USE_TYPE_ERROR = new ErrorCode(1_040_001_003, "操作失败,该模型的模型类型不正确"); - - // ========== API 聊天角色 1-040-002-000 ========== - ErrorCode CHAT_ROLE_NOT_EXISTS = new ErrorCode(1_040_002_000, "聊天角色不存在"); - ErrorCode CHAT_ROLE_DISABLE = new ErrorCode(1_040_001_001, "聊天角色({})已禁用!"); - - // ========== API 聊天会话 1-040-003-000 ========== - ErrorCode CHAT_CONVERSATION_NOT_EXISTS = new ErrorCode(1_040_003_000, "对话不存在!"); - ErrorCode CHAT_CONVERSATION_MODEL_ERROR = new ErrorCode(1_040_003_001, "操作失败,该聊天模型的配置不完整"); - - // ========== API 聊天消息 1-040-004-000 ========== - ErrorCode CHAT_MESSAGE_NOT_EXIST = new ErrorCode(1_040_004_000, "消息不存在!"); - ErrorCode CHAT_STREAM_ERROR = new ErrorCode(1_040_004_001, "对话生成异常!"); - - // ========== API 绘画 1-040-005-000 ========== - ErrorCode IMAGE_NOT_EXISTS = new ErrorCode(1_040_005_000, "图片不存在!"); - ErrorCode IMAGE_MIDJOURNEY_SUBMIT_FAIL = new ErrorCode(1_040_005_001, "Midjourney 提交失败!原因:{}"); - ErrorCode IMAGE_CUSTOM_ID_NOT_EXISTS = new ErrorCode(1_040_005_002, "Midjourney 按钮 customId 不存在! {}"); - - // ========== API 音乐 1-040-006-000 ========== - ErrorCode MUSIC_NOT_EXISTS = new ErrorCode(1_040_006_000, "音乐不存在!"); - - // ========== API 写作 1-040-007-000 ========== - ErrorCode WRITE_NOT_EXISTS = new ErrorCode(1_040_007_000, "作文不存在!"); - ErrorCode WRITE_STREAM_ERROR = new ErrorCode(1_040_07_001, "写作生成异常!"); - - // ========== API 思维导图 1-040-008-000 ========== - ErrorCode MIND_MAP_NOT_EXISTS = new ErrorCode(1_040_008_000, "思维导图不存在!"); - - // ========== API 知识库 1-040-009-000 ========== - ErrorCode KNOWLEDGE_NOT_EXISTS = new ErrorCode(1_040_009_000, "知识库不存在!"); - - ErrorCode KNOWLEDGE_DOCUMENT_NOT_EXISTS = new ErrorCode(1_040_009_101, "文档不存在!"); - ErrorCode KNOWLEDGE_DOCUMENT_FILE_EMPTY = new ErrorCode(1_040_009_102, "文档内容为空!"); - ErrorCode KNOWLEDGE_DOCUMENT_FILE_DOWNLOAD_FAIL = new ErrorCode(1_040_009_102, "文件下载失败!"); - ErrorCode KNOWLEDGE_DOCUMENT_FILE_READ_FAIL = new ErrorCode(1_040_009_102, "文档加载失败!"); - - ErrorCode KNOWLEDGE_SEGMENT_NOT_EXISTS = new ErrorCode(1_040_009_202, "段落不存在!"); - ErrorCode KNOWLEDGE_SEGMENT_CONTENT_TOO_LONG = new ErrorCode(1_040_009_203, "内容 Token 数为 {},超过最大限制 {}"); - - // ========== AI 工具 1-040-010-000 ========== - ErrorCode TOOL_NOT_EXISTS = new ErrorCode(1_040_010_000, "工具不存在"); - ErrorCode TOOL_NAME_NOT_EXISTS = new ErrorCode(1_040_010_001, "工具({})找不到 Bean"); - - // ========== AI 工作流 1-040-011-000 ========== - ErrorCode WORKFLOW_NOT_EXISTS = new ErrorCode(1_040_011_000, "工作流不存在"); - ErrorCode WORKFLOW_CODE_EXISTS = new ErrorCode(1_040_011_001, "工作流标识已存在"); - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java deleted file mode 100644 index cf80761503356a22098271118899ce0eca0c426e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/image/AiImageStatusEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.image; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI 绘画状态的枚举 - * - * @author fansili - */ -@AllArgsConstructor -@Getter -public enum AiImageStatusEnum { - - IN_PROGRESS(10, "进行中"), - SUCCESS(20, "已完成"), - FAIL(30, "已失败"); - - /** - * 状态 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - - public static AiImageStatusEnum valueOfStatus(Integer status) { - for (AiImageStatusEnum statusEnum : AiImageStatusEnum.values()) { - if (statusEnum.getStatus().equals(status)) { - return statusEnum; - } - } - throw new IllegalArgumentException("未知会话状态: " + status); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelTypeEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelTypeEnum.java deleted file mode 100644 index bdba3e89151bb8e4988ffdd0a6446b7c3cfbc457..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiModelTypeEnum.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.model; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -/** - * AI 模型类型的枚举 - * - * @author 芋道源码 - */ -@Getter -@RequiredArgsConstructor -public enum AiModelTypeEnum implements ArrayValuable { - - CHAT(1, "对话"), - IMAGE(2, "图片"), - VOICE(3, "语音"), - VIDEO(4, "视频"), - EMBEDDING(5, "向量"), - RERANK(6, "重排序"); - - /** - * 类型 - */ - private final Integer type; - /** - * 类型名 - */ - private final String name; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiModelTypeEnum::getType).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java deleted file mode 100644 index 47a4d2d719b7d3dd464e646bb332094231537b48..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/model/AiPlatformEnum.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.model; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 模型平台 - * - * @author fansili - */ -@Getter -@AllArgsConstructor -public enum AiPlatformEnum implements ArrayValuable { - - // ========== 国内平台 ========== - - TONG_YI("TongYi", "通义千问"), // 阿里 - YI_YAN("YiYan", "文心一言"), // 百度 - DEEP_SEEK("DeepSeek", "DeepSeek"), // DeepSeek - ZHI_PU("ZhiPu", "智谱"), // 智谱 AI - XING_HUO("XingHuo", "星火"), // 讯飞 - DOU_BAO("DouBao", "豆包"), // 字节 - HUN_YUAN("HunYuan", "混元"), // 腾讯 - SILICON_FLOW("SiliconFlow", "硅基流动"), // 硅基流动 - MINI_MAX("MiniMax", "MiniMax"), // 稀宇科技 - MOONSHOT("Moonshot", "月之暗灭"), // KIMI - BAI_CHUAN("BaiChuan", "百川智能"), // 百川智能 - - // ========== 国外平台 ========== - - OPENAI("OpenAI", "OpenAI"), // OpenAI 官方 - AZURE_OPENAI("AzureOpenAI", "AzureOpenAI"), // OpenAI 微软 - ANTHROPIC("Anthropic", "Anthropic"), // Anthropic Claude - GEMINI("Gemini", "Gemini"), // 谷歌 Gemini - OLLAMA("Ollama", "Ollama"), - - STABLE_DIFFUSION("StableDiffusion", "StableDiffusion"), // Stability AI - MIDJOURNEY("Midjourney", "Midjourney"), // Midjourney - SUNO("Suno", "Suno"), // Suno AI - - ; - - /** - * 平台 - */ - private final String platform; - /** - * 平台名 - */ - private final String name; - - public static final String[] ARRAYS = Arrays.stream(values()).map(AiPlatformEnum::getPlatform).toArray(String[]::new); - - public static AiPlatformEnum validatePlatform(String platform) { - for (AiPlatformEnum platformEnum : AiPlatformEnum.values()) { - if (platformEnum.getPlatform().equals(platform)) { - return platformEnum; - } - } - throw new IllegalArgumentException("非法平台: " + platform); - } - - @Override - public String[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java deleted file mode 100644 index 82052943bcb3cc05437befb42368f7d8059a1b91..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicGenerateModeEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.music; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 音乐生成模式的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiMusicGenerateModeEnum implements ArrayValuable { - - DESCRIPTION(1, "描述模式"), - LYRIC(2, "歌词模式"); - - /** - * 模式 - */ - private final Integer mode; - /** - * 模式名 - */ - private final String name; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiMusicGenerateModeEnum::getMode).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java deleted file mode 100644 index 9340a597620bfdbec027c510ee43a94cb1b413ff..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/music/AiMusicStatusEnum.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.music; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 音乐状态的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiMusicStatusEnum implements ArrayValuable { - - IN_PROGRESS(10, "进行中"), - SUCCESS(20, "已完成"), - FAIL(30, "已失败"); - - /** - * 状态 - */ - private final Integer status; - - /** - * 状态名 - */ - private final String name; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiMusicStatusEnum::getStatus).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/write/AiWriteTypeEnum.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/write/AiWriteTypeEnum.java deleted file mode 100644 index 6d91433b7b8b82864563e3f33dda14e8bb05537c..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/enums/write/AiWriteTypeEnum.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.module.ai.enums.write; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * AI 写作类型的枚举 - * - * @author xiaoxin - */ -@AllArgsConstructor -@Getter -public enum AiWriteTypeEnum implements ArrayValuable { - - WRITING(1, "撰写", "请撰写一篇关于 [{}] 的文章。文章的内容格式:{},语气:{},语言:{},长度:{}。请确保涵盖主要内容,不需要除了正文内容外的其他回复,如标题、额外的解释或道歉。"), - REPLY(2, "回复", "请针对如下内容:[{}] 做个回复。回复内容参考:[{}], 回复格式:{},语气:{},语言:{},长度:{}。不需要除了正文内容外的其他回复,如标题、开头、额外的解释或道歉。"); - - /** - * 类型 - */ - private final Integer type; - /** - * 类型名 - */ - private final String name; - - /** - * 模版 - */ - private final String prompt; - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(AiWriteTypeEnum::getType).toArray(Integer[]::new); - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java deleted file mode 100644 index 26fbe0ad410752a1bd12ac8e13dfdfb5d5dfc691..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java +++ /dev/null @@ -1,289 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.config; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactory; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.AiModelFactoryImpl; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini.GeminiChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.AiWebSearchClient; -import cn.iocoder.yudao.module.ai.framework.ai.core.webserch.bocha.AiBoChaWebSearchClient; -import cn.iocoder.yudao.module.ai.tool.method.PersonService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.deepseek.DeepSeekChatModel; -import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.deepseek.api.DeepSeekApi; -import org.springframework.ai.embedding.BatchingStrategy; -import org.springframework.ai.embedding.TokenCountBatchingStrategy; -import org.springframework.ai.model.tool.ToolCallingManager; -import org.springframework.ai.openai.OpenAiChatModel; -import org.springframework.ai.openai.OpenAiChatOptions; -import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.support.ToolCallbacks; -import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; -import org.springframework.ai.tokenizer.TokenCountEstimator; -import org.springframework.ai.tool.ToolCallback; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; -import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; -import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; -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 java.util.List; - -/** - * 芋道 AI 自动配置 - * - * @author fansili - */ -@Configuration -@EnableConfigurationProperties({ YudaoAiProperties.class, - QdrantVectorStoreProperties.class, // 解析 Qdrant 配置 - RedisVectorStoreProperties.class, // 解析 Redis 配置 - MilvusVectorStoreProperties.class, MilvusServiceClientProperties.class // 解析 Milvus 配置 -}) -@Slf4j -public class AiAutoConfiguration { - - @Bean - public AiModelFactory aiModelFactory() { - return new AiModelFactoryImpl(); - } - - // ========== 各种 AI Client 创建 ========== - - @Bean - @ConditionalOnProperty(value = "yudao.ai.gemini.enable", havingValue = "true") - public GeminiChatModel geminiChatModel(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.Gemini properties = yudaoAiProperties.getGemini(); - return buildGeminiChatClient(properties); - } - - public GeminiChatModel buildGeminiChatClient(YudaoAiProperties.Gemini properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(GeminiChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(GeminiChatModel.BASE_URL) - .completionsPath(GeminiChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new GeminiChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true") - public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.DouBao properties = yudaoAiProperties.getDoubao(); - return buildDouBaoChatClient(properties); - } - - public DouBaoChatModel buildDouBaoChatClient(YudaoAiProperties.DouBao properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(DouBaoChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(DouBaoChatModel.BASE_URL) - .completionsPath(DouBaoChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new DouBaoChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.siliconflow.enable", havingValue = "true") - public SiliconFlowChatModel siliconFlowChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.SiliconFlow properties = yudaoAiProperties.getSiliconflow(); - return buildSiliconFlowChatClient(properties); - } - - public SiliconFlowChatModel buildSiliconFlowChatClient(YudaoAiProperties.SiliconFlow properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(SiliconFlowApiConstants.MODEL_DEFAULT); - } - DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder() - .deepSeekApi(DeepSeekApi.builder() - .baseUrl(SiliconFlowApiConstants.DEFAULT_BASE_URL) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(DeepSeekChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new SiliconFlowChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.hunyuan.enable", havingValue = "true") - public HunYuanChatModel hunYuanChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.HunYuan properties = yudaoAiProperties.getHunyuan(); - return buildHunYuanChatClient(properties); - } - - public HunYuanChatModel buildHunYuanChatClient(YudaoAiProperties.HunYuan properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(HunYuanChatModel.MODEL_DEFAULT); - } - // 特殊:由于混元大模型不提供 deepseek,而是通过知识引擎,所以需要区分下 URL - if (StrUtil.isEmpty(properties.getBaseUrl())) { - properties.setBaseUrl( - StrUtil.startWithIgnoreCase(properties.getModel(), "deepseek") ? HunYuanChatModel.DEEP_SEEK_BASE_URL - : HunYuanChatModel.BASE_URL); - } - // 创建 DeepSeekChatModel、HunYuanChatModel 对象 - DeepSeekChatModel openAiChatModel = DeepSeekChatModel.builder() - .deepSeekApi(DeepSeekApi.builder() - .baseUrl(properties.getBaseUrl()) - .completionsPath(HunYuanChatModel.COMPLETE_PATH) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(DeepSeekChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new HunYuanChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.xinghuo.enable", havingValue = "true") - public XingHuoChatModel xingHuoChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.XingHuo properties = yudaoAiProperties.getXinghuo(); - return buildXingHuoChatClient(properties); - } - - public XingHuoChatModel buildXingHuoChatClient(YudaoAiProperties.XingHuo properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(XingHuoChatModel.MODEL_DEFAULT); - } - OpenAiApi.Builder builder = OpenAiApi.builder() - .baseUrl(XingHuoChatModel.BASE_URL_V1) - .apiKey(properties.getAppKey() + ":" + properties.getSecretKey()); - if ("x1".equals(properties.getModel())) { - builder.baseUrl(XingHuoChatModel.BASE_URL_V2) - .completionsPath(XingHuoChatModel.BASE_COMPLETIONS_PATH_V2); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(builder.build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - // TODO @芋艿:星火的 function call 有 bug,会报 ToolResponseMessage must have an id 错误!!! - .toolCallingManager(getToolCallingManager()) - .build(); - return new XingHuoChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.baichuan.enable", havingValue = "true") - public BaiChuanChatModel baiChuanChatClient(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.BaiChuan properties = yudaoAiProperties.getBaichuan(); - return buildBaiChuanChatClient(properties); - } - - public BaiChuanChatModel buildBaiChuanChatClient(YudaoAiProperties.BaiChuan properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(BaiChuanChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(BaiChuanChatModel.BASE_URL) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new BaiChuanChatModel(openAiChatModel); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.midjourney.enable", havingValue = "true") - public MidjourneyApi midjourneyApi(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.Midjourney config = yudaoAiProperties.getMidjourney(); - return new MidjourneyApi(config.getBaseUrl(), config.getApiKey(), config.getNotifyUrl()); - } - - @Bean - @ConditionalOnProperty(value = "yudao.ai.suno.enable", havingValue = "true") - public SunoApi sunoApi(YudaoAiProperties yudaoAiProperties) { - return new SunoApi(yudaoAiProperties.getSuno().getBaseUrl()); - } - - // ========== RAG 相关 ========== - - @Bean - public TokenCountEstimator tokenCountEstimator() { - return new JTokkitTokenCountEstimator(); - } - - @Bean - public BatchingStrategy batchingStrategy() { - return new TokenCountBatchingStrategy(); - } - - private static ToolCallingManager getToolCallingManager() { - return SpringUtil.getBean(ToolCallingManager.class); - } - - // ========== Web Search 相关 ========== - - @Bean - @ConditionalOnProperty(value = "yudao.ai.web-search.enable", havingValue = "true") - public AiWebSearchClient webSearchClient(YudaoAiProperties yudaoAiProperties) { - return new AiBoChaWebSearchClient(yudaoAiProperties.getWebSearch().getApiKey()); - } - - // ========== MCP 相关 ========== - - /** - * 参考自 MCP Server Boot Starter - */ - @Bean - public List toolCallbacks(PersonService personService) { - return List.of(ToolCallbacks.from(personService)); - } - -} \ No newline at end of file diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java deleted file mode 100644 index 67d3bb5f3acb68d5ec87f78cfe8af91337d9ddcf..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java +++ /dev/null @@ -1,172 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * 芋道 AI 配置类 - * - * @author fansili - * @since 1.0 - */ -@ConfigurationProperties(prefix = "yudao.ai") -@Data -public class YudaoAiProperties { - - /** - * 谷歌 Gemini - */ - private Gemini gemini; - - /** - * 字节豆包 - */ - private DouBao doubao; - - /** - * 腾讯混元 - */ - private HunYuan hunyuan; - - /** - * 硅基流动 - */ - private SiliconFlow siliconflow; - - /** - * 讯飞星火 - */ - private XingHuo xinghuo; - - /** - * 百川 - */ - private BaiChuan baichuan; - - /** - * Midjourney 绘图 - */ - private Midjourney midjourney; - - /** - * Suno 音乐 - */ - @SuppressWarnings("SpellCheckingInspection") - private Suno suno; - - /** - * 网络搜索 - */ - private WebSearch webSearch; - - @Data - public static class Gemini { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class DouBao { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class HunYuan { - - private String enable; - private String baseUrl; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class SiliconFlow { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class XingHuo { - - private String enable; - private String appId; - private String appKey; - private String secretKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class BaiChuan { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - - @Data - public static class Midjourney { - - private String enable; - private String baseUrl; - - private String apiKey; - private String notifyUrl; - - } - - @Data - public static class Suno { - - private boolean enable; - - private String baseUrl; - - } - - @Data - public static class WebSearch { - - private boolean enable; - - private String apiKey; - - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactory.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactory.java deleted file mode 100644 index 1c0b808b9ef6c96e7ef66b7832ac178a76ce3407..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactory.java +++ /dev/null @@ -1,113 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model; - -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.embedding.EmbeddingModel; -import org.springframework.ai.image.ImageModel; -import org.springframework.ai.vectorstore.VectorStore; - -import java.util.Map; - -/** - * AI Model 模型工厂的接口类 - * - * @author fansili - */ -public interface AiModelFactory { - - /** - * 基于指定配置,获得 ChatModel 对象 - * - * 如果不存在,则进行创建 - * - * @param platform 平台 - * @param apiKey API KEY - * @param url API URL - * @return ChatModel 对象 - */ - ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url); - - /** - * 基于默认配置,获得 ChatModel 对象 - * - * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 - * - * @param platform 平台 - * @return ChatModel 对象 - */ - ChatModel getDefaultChatModel(AiPlatformEnum platform); - - /** - * 基于默认配置,获得 ImageModel 对象 - * - * 默认配置,指的是在 application.yaml 配置文件中的 spring.ai 相关的配置 - * - * @param platform 平台 - * @return ImageModel 对象 - */ - ImageModel getDefaultImageModel(AiPlatformEnum platform); - - /** - * 基于指定配置,获得 ImageModel 对象 - * - * 如果不存在,则进行创建 - * - * @param platform 平台 - * @param apiKey API KEY - * @param url API URL - * @return ImageModel 对象 - */ - ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url); - - /** - * 基于指定配置,获得 MidjourneyApi 对象 - * - * 如果不存在,则进行创建 - * - * @param apiKey API KEY - * @param url API URL - * @return MidjourneyApi 对象 - */ - MidjourneyApi getOrCreateMidjourneyApi(String apiKey, String url); - - /** - * 基于指定配置,获得 SunoApi 对象 - * - * 如果不存在,则进行创建 - * - * @param apiKey API KEY - * @param url API URL - * @return SunoApi 对象 - */ - SunoApi getOrCreateSunoApi(String apiKey, String url); - - /** - * 基于指定配置,获得 EmbeddingModel 对象 - * - * 如果不存在,则进行创建 - * - * @param platform 平台 - * @param apiKey API KEY - * @param url API URL - * @param model 模型 - * @return ChatModel 对象 - */ - EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url, String model); - - /** - * 基于指定配置,获得 VectorStore 对象 - * - * 如果不存在,则进行创建 - * - * @param type 向量存储类型 - * @param embeddingModel 向量模型 - * @param metadataFields 元数据字段 - * @return VectorStore 对象 - */ - VectorStore getOrCreateVectorStore(Class type, - EmbeddingModel embeddingModel, - Map> metadataFields); - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java deleted file mode 100644 index 75798ebd2a26a964d776363ab7f770cdd34f3643..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/AiModelFactoryImpl.java +++ /dev/null @@ -1,832 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.Singleton; -import cn.hutool.core.lang.func.Func0; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.RuntimeUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration; -import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini.GeminiChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowApiConstants; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration; -import com.alibaba.cloud.ai.dashscope.api.DashScopeApi; -import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi; -import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel; -import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; -import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel; -import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; -import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; -import com.azure.ai.openai.OpenAIClientBuilder; -import com.azure.core.credential.KeyCredential; -import io.micrometer.observation.ObservationRegistry; -import io.milvus.client.MilvusServiceClient; -import io.qdrant.client.QdrantClient; -import io.qdrant.client.QdrantGrpcClient; -import lombok.SneakyThrows; -import org.springaicommunity.moonshot.MoonshotChatModel; -import org.springaicommunity.moonshot.MoonshotChatOptions; -import org.springaicommunity.moonshot.api.MoonshotApi; -import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration; -import org.springaicommunity.qianfan.QianFanChatModel; -import org.springaicommunity.qianfan.QianFanEmbeddingModel; -import org.springaicommunity.qianfan.QianFanEmbeddingOptions; -import org.springaicommunity.qianfan.QianFanImageModel; -import org.springaicommunity.qianfan.api.QianFanApi; -import org.springaicommunity.qianfan.api.QianFanImageApi; -import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration; -import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration; -import org.springframework.ai.azure.openai.AzureOpenAiChatModel; -import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.deepseek.DeepSeekChatModel; -import org.springframework.ai.deepseek.DeepSeekChatOptions; -import org.springframework.ai.deepseek.api.DeepSeekApi; -import org.springframework.ai.document.MetadataMode; -import org.springframework.ai.embedding.BatchingStrategy; -import org.springframework.ai.embedding.EmbeddingModel; -import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention; -import org.springframework.ai.image.ImageModel; -import org.springframework.ai.minimax.MiniMaxChatModel; -import org.springframework.ai.minimax.MiniMaxChatOptions; -import org.springframework.ai.minimax.MiniMaxEmbeddingModel; -import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; -import org.springframework.ai.minimax.api.MiniMaxApi; -import org.springframework.ai.model.anthropic.autoconfigure.AnthropicChatAutoConfiguration; -import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; -import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration; -import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties; -import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; -import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration; -import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration; -import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration; -import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; -import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration; -import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration; -import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration; -import org.springframework.ai.model.tool.ToolCallingManager; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration; -import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration; -import org.springframework.ai.ollama.OllamaChatModel; -import org.springframework.ai.ollama.OllamaEmbeddingModel; -import org.springframework.ai.ollama.api.OllamaApi; -import org.springframework.ai.ollama.api.OllamaOptions; -import org.springframework.ai.openai.OpenAiChatModel; -import org.springframework.ai.openai.OpenAiEmbeddingModel; -import org.springframework.ai.openai.OpenAiEmbeddingOptions; -import org.springframework.ai.openai.OpenAiImageModel; -import org.springframework.ai.openai.api.OpenAiApi; -import org.springframework.ai.openai.api.OpenAiImageApi; -import org.springframework.ai.openai.api.common.OpenAiApiConstants; -import org.springframework.ai.anthropic.AnthropicChatModel; -import org.springframework.ai.anthropic.api.AnthropicApi; -import org.springframework.ai.stabilityai.StabilityAiImageModel; -import org.springframework.ai.stabilityai.api.StabilityAiApi; -import org.springframework.ai.vectorstore.SimpleVectorStore; -import org.springframework.ai.vectorstore.VectorStore; -import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration; -import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; -import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; -import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; -import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; -import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration; -import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; -import org.springframework.ai.vectorstore.redis.RedisVectorStore; -import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration; -import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; -import org.springframework.ai.zhipuai.*; -import org.springframework.ai.zhipuai.api.ZhiPuAiApi; -import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.data.redis.RedisProperties; -import org.springframework.web.client.RestClient; -import redis.clients.jedis.JedisPooled; - -import java.io.File; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static org.springframework.ai.retry.RetryUtils.DEFAULT_RETRY_TEMPLATE; - -/** - * AI Model 模型工厂的实现类 - * - * @author 芋道源码 - */ -public class AiModelFactoryImpl implements AiModelFactory { - - @Override - public ChatModel getOrCreateChatModel(AiPlatformEnum platform, String apiKey, String url) { - String cacheKey = buildClientCacheKey(ChatModel.class, platform, apiKey, url); - return Singleton.get(cacheKey, (Func0) () -> { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return buildTongYiChatModel(apiKey); - case YI_YAN: - return buildYiYanChatModel(apiKey); - case DEEP_SEEK: - return buildDeepSeekChatModel(apiKey); - case DOU_BAO: - return buildDouBaoChatModel(apiKey); - case HUN_YUAN: - return buildHunYuanChatModel(apiKey, url); - case SILICON_FLOW: - return buildSiliconFlowChatModel(apiKey); - case ZHI_PU: - return buildZhiPuChatModel(apiKey, url); - case MINI_MAX: - return buildMiniMaxChatModel(apiKey, url); - case MOONSHOT: - return buildMoonshotChatModel(apiKey, url); - case XING_HUO: - return buildXingHuoChatModel(apiKey); - case BAI_CHUAN: - return buildBaiChuanChatModel(apiKey); - case OPENAI: - return buildOpenAiChatModel(apiKey, url); - case AZURE_OPENAI: - return buildAzureOpenAiChatModel(apiKey, url); - case ANTHROPIC: - return buildAnthropicChatModel(apiKey, url); - case GEMINI: - return buildGeminiChatModel(apiKey); - case OLLAMA: - return buildOllamaChatModel(url); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - }); - } - - @Override - public ChatModel getDefaultChatModel(AiPlatformEnum platform) { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return SpringUtil.getBean(DashScopeChatModel.class); - case YI_YAN: - return SpringUtil.getBean(QianFanChatModel.class); - case DEEP_SEEK: - return SpringUtil.getBean(DeepSeekChatModel.class); - case DOU_BAO: - return SpringUtil.getBean(DouBaoChatModel.class); - case HUN_YUAN: - return SpringUtil.getBean(HunYuanChatModel.class); - case SILICON_FLOW: - return SpringUtil.getBean(SiliconFlowChatModel.class); - case ZHI_PU: - return SpringUtil.getBean(ZhiPuAiChatModel.class); - case MINI_MAX: - return SpringUtil.getBean(MiniMaxChatModel.class); - case MOONSHOT: - return SpringUtil.getBean(MoonshotChatModel.class); - case XING_HUO: - return SpringUtil.getBean(XingHuoChatModel.class); - case BAI_CHUAN: - return SpringUtil.getBean(BaiChuanChatModel.class); - case OPENAI: - return SpringUtil.getBean(OpenAiChatModel.class); - case AZURE_OPENAI: - return SpringUtil.getBean(AzureOpenAiChatModel.class); - case ANTHROPIC: - return SpringUtil.getBean(AnthropicChatModel.class); - case GEMINI: - return SpringUtil.getBean(GeminiChatModel.class); - case OLLAMA: - return SpringUtil.getBean(OllamaChatModel.class); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - - @Override - public ImageModel getDefaultImageModel(AiPlatformEnum platform) { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return SpringUtil.getBean(DashScopeImageModel.class); - case YI_YAN: - return SpringUtil.getBean(QianFanImageModel.class); - case ZHI_PU: - return SpringUtil.getBean(ZhiPuAiImageModel.class); - case SILICON_FLOW: - return SpringUtil.getBean(SiliconFlowImageModel.class); - case OPENAI: - return SpringUtil.getBean(OpenAiImageModel.class); - case STABLE_DIFFUSION: - return SpringUtil.getBean(StabilityAiImageModel.class); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - - @Override - public ImageModel getOrCreateImageModel(AiPlatformEnum platform, String apiKey, String url) { - // noinspection EnhancedSwitchMigration - switch (platform) { - case TONG_YI: - return buildTongYiImagesModel(apiKey); - case YI_YAN: - return buildQianFanImageModel(apiKey); - case ZHI_PU: - return buildZhiPuAiImageModel(apiKey, url); - case OPENAI: - return buildOpenAiImageModel(apiKey, url); - case SILICON_FLOW: - return buildSiliconFlowImageModel(apiKey,url); - case STABLE_DIFFUSION: - return buildStabilityAiImageModel(apiKey, url); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - } - - @Override - public MidjourneyApi getOrCreateMidjourneyApi(String apiKey, String url) { - String cacheKey = buildClientCacheKey(MidjourneyApi.class, AiPlatformEnum.MIDJOURNEY.getPlatform(), apiKey, - url); - return Singleton.get(cacheKey, (Func0) () -> { - YudaoAiProperties.Midjourney properties = SpringUtil.getBean(YudaoAiProperties.class) - .getMidjourney(); - return new MidjourneyApi(url, apiKey, properties.getNotifyUrl()); - }); - } - - @Override - public SunoApi getOrCreateSunoApi(String apiKey, String url) { - String cacheKey = buildClientCacheKey(SunoApi.class, AiPlatformEnum.SUNO.getPlatform(), apiKey, url); - return Singleton.get(cacheKey, (Func0) () -> new SunoApi(url)); - } - - @Override - @SuppressWarnings("EnhancedSwitchMigration") - public EmbeddingModel getOrCreateEmbeddingModel(AiPlatformEnum platform, String apiKey, String url, String model) { - String cacheKey = buildClientCacheKey(EmbeddingModel.class, platform, apiKey, url, model); - return Singleton.get(cacheKey, (Func0) () -> { - switch (platform) { - case TONG_YI: - return buildTongYiEmbeddingModel(apiKey, model); - case YI_YAN: - return buildYiYanEmbeddingModel(apiKey, model); - case ZHI_PU: - return buildZhiPuEmbeddingModel(apiKey, url, model); - case MINI_MAX: - return buildMiniMaxEmbeddingModel(apiKey, url, model); - case OPENAI: - return buildOpenAiEmbeddingModel(apiKey, url, model); - case AZURE_OPENAI: - return buildAzureOpenAiEmbeddingModel(apiKey, url, model); - case OLLAMA: - return buildOllamaEmbeddingModel(url, model); - default: - throw new IllegalArgumentException(StrUtil.format("未知平台({})", platform)); - } - }); - } - - @Override - public VectorStore getOrCreateVectorStore(Class type, - EmbeddingModel embeddingModel, - Map> metadataFields) { - String cacheKey = buildClientCacheKey(VectorStore.class, embeddingModel, type); - return Singleton.get(cacheKey, (Func0) () -> { - if (type == SimpleVectorStore.class) { - return buildSimpleVectorStore(embeddingModel); - } - if (type == QdrantVectorStore.class) { - return buildQdrantVectorStore(embeddingModel); - } - if (type == RedisVectorStore.class) { - return buildRedisVectorStore(embeddingModel, metadataFields); - } - if (type == MilvusVectorStore.class) { - return buildMilvusVectorStore(embeddingModel); - } - throw new IllegalArgumentException(StrUtil.format("未知类型({})", type)); - }); - } - - private static String buildClientCacheKey(Class clazz, Object... params) { - if (ArrayUtil.isEmpty(params)) { - return clazz.getName(); - } - return StrUtil.format("{}#{}", clazz.getName(), ArrayUtil.join(params, "_")); - } - - // ========== 各种创建 spring-ai 客户端的方法 ========== - - /** - * 可参考 {@link DashScopeChatAutoConfiguration} 的 dashscopeChatModel 方法 - */ - private static DashScopeChatModel buildTongYiChatModel(String key) { - DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build(); - DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL) - .withTemperature(0.7).build(); - return DashScopeChatModel.builder() - .dashScopeApi(dashScopeApi) - .defaultOptions(options) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法 - */ - private static DashScopeImageModel buildTongYiImagesModel(String key) { - DashScopeImageApi dashScopeImageApi = DashScopeImageApi.builder().apiKey(key).build(); - return DashScopeImageModel.builder() - .dashScopeApi(dashScopeImageApi) - .build(); - } - - /** - * 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法 - */ - private static QianFanChatModel buildYiYanChatModel(String key) { - // TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6 - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); - String appKey = keys.get(0); - String secretKey = keys.get(1); - QianFanApi qianFanApi = new QianFanApi(appKey, secretKey); - return new QianFanChatModel(qianFanApi); - } - - /** - * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法 - */ - private QianFanImageModel buildQianFanImageModel(String key) { - // TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6 - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); - String appKey = keys.get(0); - String secretKey = keys.get(1); - QianFanImageApi qianFanApi = new QianFanImageApi(appKey, secretKey); - return new QianFanImageModel(qianFanApi); - } - - /** - * 可参考 {@link DeepSeekChatAutoConfiguration} 的 deepSeekChatModel 方法 - */ - private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { - DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build(); - DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL) - .temperature(0.7).build(); - return DeepSeekChatModel.builder() - .deepSeekApi(deepSeekApi) - .defaultOptions(options) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AiAutoConfiguration#douBaoChatClient(YudaoAiProperties)} - */ - private ChatModel buildDouBaoChatModel(String apiKey) { - YudaoAiProperties.DouBao properties = new YudaoAiProperties.DouBao() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildDouBaoChatClient(properties); - } - - /** - * 可参考 {@link AiAutoConfiguration#hunYuanChatClient(YudaoAiProperties)} - */ - private ChatModel buildHunYuanChatModel(String apiKey, String url) { - YudaoAiProperties.HunYuan properties = new YudaoAiProperties.HunYuan() - .setBaseUrl(url).setApiKey(apiKey); - return new AiAutoConfiguration().buildHunYuanChatClient(properties); - } - - /** - * 可参考 {@link AiAutoConfiguration#siliconFlowChatClient(YudaoAiProperties)} - */ - private ChatModel buildSiliconFlowChatModel(String apiKey) { - YudaoAiProperties.SiliconFlow properties = new YudaoAiProperties.SiliconFlow() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildSiliconFlowChatClient(properties); - } - - /** - * 可参考 {@link ZhiPuAiChatAutoConfiguration} 的 zhiPuAiChatModel 方法 - */ - private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { - ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) - : new ZhiPuAiApi(url, apiKey); - ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); - return new ZhiPuAiChatModel(zhiPuAiApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE, - getObservationRegistry().getIfAvailable()); - } - - /** - * 可参考 {@link ZhiPuAiImageAutoConfiguration} 的 zhiPuAiImageModel 方法 - */ - private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { - ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey) - : new ZhiPuAiImageApi(url, apiKey, RestClient.builder()); - return new ZhiPuAiImageModel(zhiPuAiApi); - } - - /** - * 可参考 {@link MiniMaxChatAutoConfiguration} 的 miniMaxChatModel 方法 - */ - private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) { - MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey) - : new MiniMaxApi(url, apiKey); - MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); - return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE); - } - - /** - * 可参考 {@link MoonshotChatAutoConfiguration} 的 moonshotChatModel 方法 - */ - private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) { - MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder() - .apiKey(apiKey); - if (StrUtil.isNotEmpty(url)) { - moonshotApiBuilder.baseUrl(url); - } - MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build(); - return MoonshotChatModel.builder() - .moonshotApi(moonshotApiBuilder.build()) - .defaultOptions(options) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AiAutoConfiguration#xingHuoChatClient(YudaoAiProperties)} - */ - private static XingHuoChatModel buildXingHuoChatModel(String key) { - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "XingHuoChatClient 的密钥需要 (appKey|secretKey) 格式"); - YudaoAiProperties.XingHuo properties = new YudaoAiProperties.XingHuo() - .setAppKey(keys.get(0)).setSecretKey(keys.get(1)); - return new AiAutoConfiguration().buildXingHuoChatClient(properties); - } - - /** - * 可参考 {@link AiAutoConfiguration#baiChuanChatClient(YudaoAiProperties)} - */ - private BaiChuanChatModel buildBaiChuanChatModel(String apiKey) { - YudaoAiProperties.BaiChuan properties = new YudaoAiProperties.BaiChuan() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildBaiChuanChatClient(properties); - } - - /** - * 可参考 {@link OpenAiChatAutoConfiguration} 的 openAiChatModel 方法 - */ - private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { - url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); - OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); - return OpenAiChatModel.builder() - .openAiApi(openAiApi) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AzureOpenAiChatAutoConfiguration} - */ - private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) { - // TODO @芋艿:使用前,请测试,暂时没密钥!!! - OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() - .endpoint(url).credential(new KeyCredential(apiKey)); - return AzureOpenAiChatModel.builder() - .openAIClientBuilder(openAIClientBuilder) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AnthropicChatAutoConfiguration} 的 anthropicApi 方法 - */ - private static AnthropicChatModel buildAnthropicChatModel(String apiKey, String url) { - AnthropicApi.Builder builder = AnthropicApi.builder().apiKey(apiKey); - if (StrUtil.isNotEmpty(url)) { - builder.baseUrl(url); - } - AnthropicApi anthropicApi = builder.build(); - return AnthropicChatModel.builder() - .anthropicApi(anthropicApi) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link AiAutoConfiguration#buildGeminiChatClient(YudaoAiProperties.Gemini)} - */ - private static GeminiChatModel buildGeminiChatModel(String apiKey) { - YudaoAiProperties.Gemini properties = SpringUtil.getBean(YudaoAiProperties.class) - .getGemini().setApiKey(apiKey); - return new AiAutoConfiguration().buildGeminiChatClient(properties); - } - - /** - * 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法 - */ - private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { - url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); - OpenAiImageApi openAiApi = OpenAiImageApi.builder().baseUrl(url).apiKey(openAiToken).build(); - return new OpenAiImageModel(openAiApi); - } - - /** - * 创建 SiliconFlowImageModel 对象 - */ - private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) { - url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL); - SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken); - return new SiliconFlowImageModel(openAiApi); - } - - /** - * 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法 - */ - private static OllamaChatModel buildOllamaChatModel(String url) { - OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); - return OllamaChatModel.builder() - .ollamaApi(ollamaApi) - .toolCallingManager(getToolCallingManager()) - .build(); - } - - /** - * 可参考 {@link StabilityAiImageAutoConfiguration} 的 stabilityAiImageModel 方法 - */ - private StabilityAiImageModel buildStabilityAiImageModel(String apiKey, String url) { - url = StrUtil.blankToDefault(url, StabilityAiApi.DEFAULT_BASE_URL); - StabilityAiApi stabilityAiApi = new StabilityAiApi(apiKey, StabilityAiApi.DEFAULT_IMAGE_MODEL, url); - return new StabilityAiImageModel(stabilityAiApi); - } - - // ========== 各种创建 EmbeddingModel 的方法 ========== - - /** - * 可参考 {@link DashScopeEmbeddingAutoConfiguration} 的 dashscopeEmbeddingModel 方法 - */ - private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) { - DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build(); - DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build(); - return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions); - } - - /** - * 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法 - */ - private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) { - ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) - : new ZhiPuAiApi(url, apiKey); - ZhiPuAiEmbeddingOptions zhiPuAiEmbeddingOptions = ZhiPuAiEmbeddingOptions.builder().model(model).build(); - return new ZhiPuAiEmbeddingModel(zhiPuAiApi, MetadataMode.EMBED, zhiPuAiEmbeddingOptions); - } - - /** - * 可参考 {@link MiniMaxEmbeddingAutoConfiguration} 的 miniMaxEmbeddingModel 方法 - */ - private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) { - MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey) - : new MiniMaxApi(url, apiKey); - MiniMaxEmbeddingOptions miniMaxEmbeddingOptions = MiniMaxEmbeddingOptions.builder().model(model).build(); - return new MiniMaxEmbeddingModel(miniMaxApi, MetadataMode.EMBED, miniMaxEmbeddingOptions); - } - - /** - * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanEmbeddingModel 方法 - */ - private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) { - List keys = StrUtil.split(key, '|'); - Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); - String appKey = keys.get(0); - String secretKey = keys.get(1); - QianFanApi qianFanApi = new QianFanApi(appKey, secretKey); - QianFanEmbeddingOptions qianFanEmbeddingOptions = QianFanEmbeddingOptions.builder().model(model).build(); - return new QianFanEmbeddingModel(qianFanApi, MetadataMode.EMBED, qianFanEmbeddingOptions); - } - - private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) { - OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); - OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build(); - return OllamaEmbeddingModel.builder() - .ollamaApi(ollamaApi) - .defaultOptions(ollamaOptions) - .build(); - } - - /** - * 可参考 {@link OpenAiEmbeddingAutoConfiguration} 的 openAiEmbeddingModel 方法 - */ - private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) { - url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); - OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); - OpenAiEmbeddingOptions openAiEmbeddingProperties = OpenAiEmbeddingOptions.builder().model(model).build(); - return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties); - } - - /** - * 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法 - */ - private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) { - // TODO @芋艿:手头暂时没密钥,使用建议再测试下 - AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration(); - // 创建 OpenAIClientBuilder 对象 - OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() - .endpoint(url).credential(new KeyCredential(apiKey)); - // 获取 AzureOpenAiChatProperties 对象 - AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class); - return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties, - getObservationRegistry(), getEmbeddingModelObservationConvention()); - } - - // ========== 各种创建 VectorStore 的方法 ========== - - /** - * 注意:仅适合本地测试使用,生产建议还是使用 Qdrant、Milvus 等 - */ - @SneakyThrows - @SuppressWarnings("ResultOfMethodCallIgnored") - private SimpleVectorStore buildSimpleVectorStore(EmbeddingModel embeddingModel) { - SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel).build(); - // 启动加载 - File file = new File(StrUtil.format("{}/vector_store/simple_{}.json", - FileUtil.getUserHomePath(), embeddingModel.getClass().getSimpleName())); - if (!file.exists()) { - FileUtil.mkParentDirs(file); - file.createNewFile(); - } else if (file.length() > 0) { - vectorStore.load(file); - } - // 定时持久化,每分钟一次 - Timer timer = new Timer("SimpleVectorStoreTimer-" + file.getAbsolutePath()); - timer.scheduleAtFixedRate(new TimerTask() { - - @Override - public void run() { - vectorStore.save(file); - } - - }, Duration.ofMinutes(1).toMillis(), Duration.ofMinutes(1).toMillis()); - // 关闭时,进行持久化 - RuntimeUtil.addShutdownHook(() -> vectorStore.save(file)); - return vectorStore; - } - - /** - * 参考 {@link QdrantVectorStoreAutoConfiguration} 的 vectorStore 方法 - */ - @SneakyThrows - private QdrantVectorStore buildQdrantVectorStore(EmbeddingModel embeddingModel) { - QdrantVectorStoreAutoConfiguration configuration = new QdrantVectorStoreAutoConfiguration(); - QdrantVectorStoreProperties properties = SpringUtil.getBean(QdrantVectorStoreProperties.class); - // 参考 QdrantVectorStoreAutoConfiguration 实现,创建 QdrantClient 对象 - QdrantGrpcClient.Builder grpcClientBuilder = QdrantGrpcClient.newBuilder( - properties.getHost(), properties.getPort(), properties.isUseTls()); - if (StrUtil.isNotEmpty(properties.getApiKey())) { - grpcClientBuilder.withApiKey(properties.getApiKey()); - } - QdrantClient qdrantClient = new QdrantClient(grpcClientBuilder.build()); - // 创建 QdrantVectorStore 对象 - QdrantVectorStore vectorStore = configuration.vectorStore(embeddingModel, properties, qdrantClient, - getObservationRegistry(), getCustomObservationConvention(), getBatchingStrategy()); - // 初始化索引 - vectorStore.afterPropertiesSet(); - return vectorStore; - } - - /** - * 参考 {@link RedisVectorStoreAutoConfiguration} 的 vectorStore 方法 - */ - private RedisVectorStore buildRedisVectorStore(EmbeddingModel embeddingModel, - Map> metadataFields) { - // 创建 JedisPooled 对象 - RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); - JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort(), - redisProperties.getUsername(), redisProperties.getPassword()); - // 创建 RedisVectorStoreProperties 对象 - RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class); - RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel) - .indexName(properties.getIndexName()).prefix(properties.getPrefix()) - .initializeSchema(properties.isInitializeSchema()) - .metadataFields(convertList(metadataFields.entrySet(), entry -> { - String fieldName = entry.getKey(); - Class fieldType = entry.getValue(); - if (Number.class.isAssignableFrom(fieldType)) { - return RedisVectorStore.MetadataField.numeric(fieldName); - } - if (Boolean.class.isAssignableFrom(fieldType)) { - return RedisVectorStore.MetadataField.tag(fieldName); - } - return RedisVectorStore.MetadataField.text(fieldName); - })) - .observationRegistry(getObservationRegistry().getObject()) - .customObservationConvention(getCustomObservationConvention().getObject()) - .batchingStrategy(getBatchingStrategy()) - .build(); - // 初始化索引 - redisVectorStore.afterPropertiesSet(); - return redisVectorStore; - } - - /** - * 参考 {@link MilvusVectorStoreAutoConfiguration} 的 vectorStore 方法 - */ - @SneakyThrows - private MilvusVectorStore buildMilvusVectorStore(EmbeddingModel embeddingModel) { - MilvusVectorStoreAutoConfiguration configuration = new MilvusVectorStoreAutoConfiguration(); - // 获取配置属性 - MilvusVectorStoreProperties serverProperties = SpringUtil.getBean(MilvusVectorStoreProperties.class); - MilvusServiceClientProperties clientProperties = SpringUtil.getBean(MilvusServiceClientProperties.class); - - // 创建 MilvusServiceClient 对象 - MilvusServiceClient milvusClient = configuration.milvusClient(serverProperties, clientProperties, - new MilvusServiceClientConnectionDetails() { - - @Override - public String getHost() { - return clientProperties.getHost(); - } - - @Override - public int getPort() { - return clientProperties.getPort(); - } - - } - ); - // 创建 MilvusVectorStore 对象 - MilvusVectorStore vectorStore = configuration.vectorStore(milvusClient, embeddingModel, serverProperties, - getBatchingStrategy(), getObservationRegistry(), getCustomObservationConvention()); - - // 初始化索引 - vectorStore.afterPropertiesSet(); - return vectorStore; - } - - private static ObjectProvider getObservationRegistry() { - return new ObjectProvider<>() { - - @Override - public ObservationRegistry getObject() throws BeansException { - return SpringUtil.getBean(ObservationRegistry.class); - } - - }; - } - - private static ObjectProvider getCustomObservationConvention() { - return new ObjectProvider<>() { - - @Override - public VectorStoreObservationConvention getObject() throws BeansException { - return new DefaultVectorStoreObservationConvention(); - } - - }; - } - - private static BatchingStrategy getBatchingStrategy() { - return SpringUtil.getBean(BatchingStrategy.class); - } - - private static ToolCallingManager getToolCallingManager() { - return SpringUtil.getBean(ToolCallingManager.class); - } - - private static ObjectProvider getEmbeddingModelObservationConvention() { - return new ObjectProvider<>() { - - @Override - public EmbeddingModelObservationConvention getObject() throws BeansException { - return SpringUtil.getBean(EmbeddingModelObservationConvention.class); - } - - }; - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/baichuan/BaiChuanChatModel.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/baichuan/BaiChuanChatModel.java deleted file mode 100644 index 5fb71c942cf45ccf8326befb5124b08b8da697d5..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/baichuan/BaiChuanChatModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatModel; -import reactor.core.publisher.Flux; - -/** - * 百川 {@link ChatModel} 实现类 - * - * @author 芋道源码 - */ -@Slf4j -@RequiredArgsConstructor -public class BaiChuanChatModel implements ChatModel { - - public static final String BASE_URL = "https://api.baichuan-ai.com"; - - public static final String MODEL_DEFAULT = "Baichuan4-Turbo"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final OpenAiChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/doubao/DouBaoChatModel.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/doubao/DouBaoChatModel.java deleted file mode 100644 index a542cb3722dd6dc19fb507f842288012ac1c5382..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/doubao/DouBaoChatModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import reactor.core.publisher.Flux; - -/** - * 字节豆包 {@link ChatModel} 实现类 - * - * @author fansili - */ -@Slf4j -@RequiredArgsConstructor -public class DouBaoChatModel implements ChatModel { - - public static final String BASE_URL = "https://ark.cn-beijing.volces.com/api"; - public static final String COMPLETE_PATH = "/v3/chat/completions"; - - public static final String MODEL_DEFAULT = "doubao-1-5-lite-32k-250115"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final ChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/gemini/GeminiChatModel.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/gemini/GeminiChatModel.java deleted file mode 100644 index 378a0af1fb0590c064820091773e72204757bd78..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/gemini/GeminiChatModel.java +++ /dev/null @@ -1,46 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.gemini; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatModel; -import reactor.core.publisher.Flux; - -/** - * 谷歌 Gemini {@link ChatModel} 实现类,基于 Google AI Studio 提供的 OpenAI 兼容方案 - * - * @author 芋道源码 - */ -@Slf4j -@RequiredArgsConstructor -public class GeminiChatModel implements ChatModel { - - public static final String BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"; - public static final String COMPLETE_PATH = "/chat/completions"; - - public static final String MODEL_DEFAULT = "gemini-2.5-flash"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final OpenAiChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java deleted file mode 100644 index 9513c6c5f751557eda68d8cabe08c9860fe201d4..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/hunyuan/HunYuanChatModel.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import reactor.core.publisher.Flux; - -/** - * 腾云混元 {@link ChatModel} 实现类 - * - * 1. 混元大模型:基于 知识引擎原子能力 实现 - * 2. 知识引擎原子能力:基于 知识引擎原子能力 实现 - * - * @author fansili - */ -@Slf4j -@RequiredArgsConstructor -public class HunYuanChatModel implements ChatModel { - - public static final String BASE_URL = "https://api.hunyuan.cloud.tencent.com"; - public static final String COMPLETE_PATH = "/v1/chat/completions"; - - public static final String MODEL_DEFAULT = "hunyuan-turbo"; - - public static final String DEEP_SEEK_BASE_URL = "https://api.lkeap.cloud.tencent.com"; - - public static final String DEEP_SEEK_MODEL_DEFAULT = "deepseek-v3"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final ChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/midjourney/api/MidjourneyApi.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/midjourney/api/MidjourneyApi.java deleted file mode 100644 index 051ef31851d7ebcf51f5e4a67194054b74fbc95e..0000000000000000000000000000000000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/midjourney/api/MidjourneyApi.java +++ /dev/null @@ -1,351 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Midjourney API - * - * @author fansili - * @since 1.0 - */ -@Slf4j -public class MidjourneyApi { - - private final Predicate STATUS_PREDICATE = status -> !status.is2xxSuccessful(); - - private final Function>> EXCEPTION_FUNCTION = - reqParam -> response -> response.bodyToMono(String.class).handle((responseBody, sink) -> { - HttpRequest request = response.request(); - log.error("[midjourney-api] 调用失败!请求方式:[{}],请求地址:[{}],请求参数:[{}],响应数据: [{}]", - request.getMethod(), request.getURI(), reqParam, responseBody); - sink.error(new IllegalStateException("[midjourney-api] 调用失败!")); - }); - - private final WebClient webClient; - - /** - * 回调地址 - */ - private final String notifyUrl; - - public MidjourneyApi(String baseUrl, String apiKey, String notifyUrl) { - this.webClient = WebClient.builder() - .baseUrl(baseUrl) - .defaultHeaders(httpHeaders -> { - httpHeaders.setContentType(MediaType.APPLICATION_JSON); - httpHeaders.setBearerAuth(apiKey); - }) - .build(); - this.notifyUrl = notifyUrl; - } - - /** - * imagine - 根据提示词提交绘画任务 - * - * @param request 请求 - * @return 提交结果 - */ - public SubmitResponse imagine(ImagineRequest request) { - if (StrUtil.isEmpty(request.getNotifyHook())) { - request.setNotifyHook(notifyUrl); - } - String response = post("/submit/imagine", request); - return JsonUtils.parseObject(response, SubmitResponse.class); - } - - /** - * action - 放大、缩小、U1、U2... - * - * @param request 请求 - * @return 提交结果 - */ - public SubmitResponse action(ActionRequest request) { - if (StrUtil.isEmpty(request.getNotifyHook())) { - request.setNotifyHook(notifyUrl); - } - String response = post("/submit/action", request); - return JsonUtils.parseObject(response, SubmitResponse.class); - } - - /** - * 批量查询 task 任务 - * - * @param ids 任务编号数组 - * @return task 任务 - */ - public List getTaskList(Collection ids) { - String res = post("/task/list-by-condition", ImmutableMap.of("ids", ids)); - return JsonUtils.parseArray(res, Notify.class); - } - - private String post(String uri, Object body) { - return webClient.post() - .uri(uri) - .body(Mono.just(JsonUtils.toJsonString(body)), String.class) - .retrieve() - .onStatus(STATUS_PREDICATE, EXCEPTION_FUNCTION.apply(body)) - .bodyToMono(String.class) - .block(); - } - - // ========== record 结构 ========== - - /** - * Imagine 请求(生成图片) - */ - @Data - public static final class ImagineRequest { - - /** - * 垫图(参考图) base64 数组 - */ - private List base64Array; - /** - * 提示词 - */ - private String prompt; - /** - * 通知地址 - */ - private String notifyHook; - /** - * 自定义参数 - */ - private String state; - - public ImagineRequest(List base64Array, String prompt, String notifyHook, String state) { - this.base64Array = base64Array; - this.prompt = prompt; - this.notifyHook = notifyHook; - this.state = state; - } - - public static String buildState(Integer width, Integer height, String version, String model) { - StringBuilder params = new StringBuilder(); - // --ar 来设置尺寸 - params.append(String.format(" --ar %s:%s ", width, height)); - // --niji 模型 - if (ModelEnum.NIJI.getModel().equals(model)) { - params.append(String.format(" --niji %s ", version)); - } else { - params.append(String.format(" --v %s ", version)); - } - return params.toString(); - } - - } - - /** - * Action 请求 - */ - @Data - public static final class ActionRequest { - - private String customId; - private String taskId; - private String notifyHook; - - public ActionRequest(String taskId, String customId, String notifyHook) { - this.customId = customId; - this.taskId = taskId; - this.notifyHook = notifyHook; - } - - } - - /** - * Submit 统一返回 - * - * @param code 状态码: 1(提交成功), 21(已存在), 22(排队中), other(错误) - * @param description 描述 - * @param properties 扩展字段 - * @param result 任务ID - */ - public record SubmitResponse(String code, - String description, - Map properties, - String result) { - } - - /** - * 通知 request - * - * @param id job id - * @param action 任务类型 {@link TaskActionEnum} - * @param status 任务状态 {@link TaskStatusEnum} - * @param prompt 提示词 - * @param promptEn 提示词-英文 - * @param description 任务描述 - * @param state 自定义参数 - * @param submitTime 提交时间 - * @param startTime 开始执行时间 - * @param finishTime 结束时间 - * @param imageUrl 图片url - * @param progress 任务进度 - * @param failReason 失败原因 - * @param buttons 任务完成后的可执行按钮 - */ - public record Notify(String id, - String action, - String status, - - String prompt, - String promptEn, - - String description, - String state, - - Long submitTime, - Long startTime, - Long finishTime, - - String imageUrl, - String progress, - String failReason, - List