chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xspaceagi</groupId>
<artifactId>platform-system</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>system-spec</artifactId>
<properties>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers-standard-package</artifactId>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- 密钥工具 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
<!-- 加密 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
<!--缓存-->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- hutool工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- hutool拼音功能依赖的底层引擎用于中文转拼音首字母 -->
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,27 @@
package com.xspaceagi.sandbox;
/**
* Sandbox 相关的attribute key
*/
public class SandboxRequestAttributes {
private SandboxRequestAttributes() {
}
/**
* 原始请求 URI形如/api/v1/4sandbox/{module}/...
* 鉴权拦截器需要基于这个值做白名单/AKTargetType 判断。
*/
public static final String ORIGINAL_REQUEST_URI = "ORIGINAL_REQUEST_URI";
/**
* 请求来源(用于 controller 做沙箱/前端差异处理)
*/
public static final String REQUEST_SOURCE = "REQUEST_SOURCE";
/**
* sandbox 来源标记值
*/
public static final String SOURCE_SANDBOX = "sandbox";
}

View File

@@ -0,0 +1,16 @@
package com.xspaceagi.system.spec.annotation;
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;
/**
* 执行后清除所有用户权限缓存
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ClearAllUserPermissionCache {
}

View File

@@ -0,0 +1,26 @@
package com.xspaceagi.system.spec.annotation;
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;
/**
* 执行后按用户ID列表清理权限缓存
*
* 通过 userIdParamIndexes 指定方法参数中哪些位置包含用户ID或用户ID集合
* - 如果参数类型是 Long则视为单个 userId
* - 如果是 Collection<Long> / List<Long>则视为用户ID列表
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ClearUserPermissionCacheByUserIds {
/**
* 方法参数中包含用户ID或用户ID集合的参数下标从 0 开始)
*/
int[] userIdParamIndexes();
}

View File

@@ -0,0 +1,33 @@
package com.xspaceagi.system.spec.annotation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RUNTIME)
@Repeatable(EnumValidation.List.class) // 允许在同一元素上多次使用该注解
@Constraint(validatedBy = {EnumValidator.class})
public @interface EnumValidation {
String message() default "{*.validation.constraint.Enum.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<?> clazz();
String method() default "ordinal";
@Documented
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
@interface List {
EnumValidation[] value();
}
}

View File

@@ -0,0 +1,37 @@
package com.xspaceagi.system.spec.annotation;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.lang.reflect.Method;
/**
* @desc: 枚举验证器
*/
public class EnumValidator implements ConstraintValidator<EnumValidation, Object> {
private EnumValidation annotation;
@Override
public void initialize(EnumValidation constraintAnnotation) {
this.annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
Object[] objects = annotation.clazz().getEnumConstants();
try {
Method method = annotation.clazz().getMethod(annotation.method());
for (Object o : objects) {
if (value.equals(method.invoke(o))) {
return true;
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return false;
}
}

View File

@@ -0,0 +1,12 @@
package com.xspaceagi.system.spec.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface I18n {
String module() default "";
}

View File

@@ -0,0 +1,19 @@
package com.xspaceagi.system.spec.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface I18nField {
String field() default "";
boolean subObj() default false;
boolean id() default false;
boolean keyPrefix() default false;
}

View File

@@ -0,0 +1,14 @@
package com.xspaceagi.system.spec.annotation;
import java.lang.annotation.*;
/**
* 请求参数,不需要解析转换到QueryMap的字段
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface NoParseRequestParam {
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.annotation;
import com.xspaceagi.system.spec.enums.ResourceEnum;
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;
/**
* 资源权限注解,支持方法级别和类级别
* - 方法级别:仅该方法的接口受此注解限制
* - 类级别:该类的所有接口方法都受此注解限制,方法上的注解优先于类上的
* 支持传入多个资源码
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequireResource {
/**
* 资源枚举(支持多个,用户拥有任意一个即可)
*/
ResourceEnum[] value() default {};
/**
* 资源码(支持多个,用户拥有任意一个即可)
* 当 value 与 codes 同时指定时,会合并校验
*/
String[] codes() default {};
/**
* 权限描述信息
*/
String description() default "需要资源权限";
/**
* 是否允许跳过权限检查(用于测试等场景)
*/
boolean skipCheck() default false;
}

View File

@@ -0,0 +1,15 @@
package com.xspaceagi.system.spec.annotation;
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;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SaasAdmin {
boolean skipCheck() default false;
}

View File

@@ -0,0 +1,26 @@
package com.xspaceagi.system.spec.annotation;
import lombok.Getter;
import lombok.Setter;
/**
* 敏感字段权限过滤, 目前自己从权限系统里获取,如有无成本权限,售价权限等
* <p>后续完善中,看实际情况,会继续增加敏感类型的区分和过滤</p>
*/
@Getter
@Setter
public class SensitiveAuthParam {
/**
* 用户密码权限
*/
private Boolean userPasswordFlag;
public static SensitiveAuthParam passwordAuthBuild(Boolean userPasswordFlag) {
SensitiveAuthParam sensitiveAuthParam = new SensitiveAuthParam();
sensitiveAuthParam.setUserPasswordFlag(userPasswordFlag);
return sensitiveAuthParam;
}
}

View File

@@ -0,0 +1,18 @@
package com.xspaceagi.system.spec.annotation;
import java.lang.annotation.*;
/**
* 敏感字段处理
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface SensitiveField {
/**
* 参考:SensitiveFieldEnum 枚举
*/
SensitiveFieldEnum type();
}

View File

@@ -0,0 +1,22 @@
package com.xspaceagi.system.spec.annotation;
import lombok.Getter;
@Getter
public enum SensitiveFieldEnum {
/**
*
*/
USER_PASSWORD("用户密码");
/**
* 描述
*/
private String desc;
SensitiveFieldEnum(String desc) {
this.desc = desc;
}
}

View File

@@ -0,0 +1,13 @@
package com.xspaceagi.system.spec.auth;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties({UserAuthProperties.class,UserJwtProperties.class})
public class AuthWebConfiguration {
}

View File

@@ -0,0 +1,24 @@
package com.xspaceagi.system.spec.auth;
import com.google.common.collect.Lists;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
/**
* 用户鉴权相关配置
*/
@Data
@ConfigurationProperties(prefix = "auth")
public class UserAuthProperties {
/**
* 不需要鉴权的uri
*/
private List<String> excludePath = Lists.newArrayList("/login", "/health", "/ready");
}

View File

@@ -0,0 +1,16 @@
package com.xspaceagi.system.spec.auth;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "auth.jwt")
public class UserJwtProperties {
/**
* jwt 密钥
*/
private String secretKey;
}

View File

@@ -0,0 +1,184 @@
package com.xspaceagi.system.spec.cache;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@Component
@Slf4j
public class SimpleJvmHashCache {
public static final long DEFAULT_EXPIRE_AFTER_SECONDS = 86400;
private static final Map<String, Map<String, CacheItem<Object>>> cache;
private static final ScheduledExecutorService cleanupExecutor;
static {
cache = new ConcurrentHashMap<>();
cleanupExecutor = Executors.newSingleThreadScheduledExecutor();
// 每5秒清理一次过期缓存
cleanupExecutor.scheduleAtFixedRate(SimpleJvmHashCache::cleanupExpiredItems, 5, 5, TimeUnit.SECONDS);
}
/**
* 添加Hash缓存项指定过期时间单位
*/
public static void putHash(String key, String field, Object value, long expireAfterSeconds, Consumer<Object> expireListener) {
if (key == null) {
return;
}
long expireTime = System.currentTimeMillis() + expireAfterSeconds * 1000;
cache.computeIfAbsent(key, k -> new ConcurrentHashMap<>())
.put(field, new CacheItem<>(value, expireTime, expireListener));
}
public static void putHash(String key, String field, Object value, long expireAfterSeconds) {
if (key == null) {
return;
}
long expireTime = System.currentTimeMillis() + expireAfterSeconds * 1000;
cache.computeIfAbsent(key, k -> new ConcurrentHashMap<>())
.put(field, new CacheItem<>(value, expireTime));
}
/**
* 获取Hash缓存项如果已过期则返回null
*/
public static Object getHash(String key, String field) {
if (key == null) {
return null;
}
Map<String, CacheItem<Object>> fieldMap = cache.get(key);
if (fieldMap == null) return null;
CacheItem<Object> item = fieldMap.get(field);
if (item == null || item.isExpired()) {
fieldMap.remove(field);
return null;
}
return item.getValue();
}
//getHashAll
public static Map<String, Object> getHashAll(String key) {
if (key == null) {
return null;
}
Map<String, CacheItem<Object>> fieldMap = cache.get(key);
if (fieldMap == null) return null;
Map<String, Object> result = new ConcurrentHashMap<>();
fieldMap.forEach((field, item) -> {
if (item != null && !item.isExpired() && item.getValue() != null) {
result.put(field, item.getValue());
}
});
return result;
}
/**
* 删除Hash缓存项
*/
public static Object removeHash(String key, String field) {
if (key == null) {
return null;
}
Map<String, CacheItem<Object>> fieldMap = cache.get(key);
if (fieldMap != null) {
CacheItem<Object> item = fieldMap.remove(field);
if (item != null) {
return item.getValue();
}
}
return null;
}
//删除
public static void removeHashAll(String key) {
if (key == null) {
return;
}
cache.remove(key);
}
private static void cleanupExpiredItems() {
try {
cleanupExpiredItems0();
} catch (Exception e) {
// ignore
log.error("cleanupExpiredItems error", e);
}
}
/**
* 清理所有过期的缓存项
*/
private static void cleanupExpiredItems0() {
List<String> toRemove = new ArrayList<>();
cache.forEach((key, fieldMap) -> {
fieldMap.entrySet().removeIf(entry -> {
if (entry.getValue().isExpired()) {
if (entry.getValue().expireListener != null) {
try {
entry.getValue().expireListener.accept(entry.getValue().getValue());
} catch (Exception e) {
// ignore
}
}
return true;
}
return false;
});
if (fieldMap.isEmpty()) {
toRemove.add(key);
}
});
toRemove.forEach(cache::remove);
}
/**
* 关闭缓存清理任务
*/
@PreDestroy
public void shutdown() {
cleanupExecutor.shutdown();
}
/**
* 缓存项包装类,记录过期时间
*/
private static class CacheItem<V> {
private final V value;
private final long expireTime;
private Consumer<V> expireListener;
CacheItem(V value, long expireTime) {
this.value = value;
this.expireTime = expireTime;
}
CacheItem(V value, long expireTime, Consumer<V> expireListener) {
this.value = value;
this.expireTime = expireTime;
this.expireListener = expireListener;
}
V getValue() {
return value;
}
boolean isExpired() {
return System.currentTimeMillis() > expireTime;
}
}
}

View File

@@ -0,0 +1,45 @@
package com.xspaceagi.system.spec.common;
import com.xspaceagi.system.spec.jackson.JsonSerializeUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;
public class JsonTypeHandler extends BaseTypeHandler<Object> {
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object object, JdbcType jdbcType) throws SQLException {
if (Objects.nonNull(object)) {
preparedStatement.setString(i, JsonSerializeUtil.toJSONStringGeneric(object));
}
}
@Override
public Object getNullableResult(ResultSet resultSet, String s) throws SQLException {
if (null != resultSet.getString(s)) {
return JsonSerializeUtil.parseObjectGeneric(resultSet.getString(s));
}
return null;
}
@Override
public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
if (null != resultSet.getString(i)) {
return JsonSerializeUtil.parseObjectGeneric(resultSet.getString(i));
}
return null;
}
@Override
public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
if (null != callableStatement.getString(i)) {
return JsonSerializeUtil.parseObjectGeneric(callableStatement.getString(i));
}
return null;
}
}

View File

@@ -0,0 +1,118 @@
package com.xspaceagi.system.spec.common;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* 不包含类型信息的 JsonTypeHandler
* 专门用于序列化不包含 @class 类型信息的 JSON 数据
*/
public class JsonTypeHandlerWithoutType extends BaseTypeHandler<Object> {
private static final ObjectMapper objectMapper;
/**
* 最大序列化大小限制100MB
* 超过此大小会抛出明确的异常,而不是导致 OOM
*/
private static final long MAX_SERIALIZATION_SIZE = 100 * 1024 * 1024L;
static {
objectMapper = new ObjectMapper();
// 配置不包含类型信息
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 配置 StreamReadConstraints 以支持更大的字符串长度
// 设置最大字符串长度为 100MB (100 * 1024 * 1024 字符)
StreamReadConstraints constraints = StreamReadConstraints.builder()
.maxStringLength(100 * 1024 * 1024)
.build();
JsonFactory factory = objectMapper.getFactory();
factory.setStreamReadConstraints(constraints);
}
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object object, JdbcType jdbcType)
throws SQLException {
if (Objects.nonNull(object)) {
try {
// 使用 ByteArrayOutputStream 来限制内存使用并检查大小
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (JsonGenerator generator = objectMapper.getFactory().createGenerator(outputStream)) {
objectMapper.writeValue(generator, object);
}
// 检查序列化后的大小
byte[] bytes = outputStream.toByteArray();
if (bytes.length > MAX_SERIALIZATION_SIZE) {
throw new SQLException(String.format(
"序列化后的数据大小超过限制: %d bytes > %d bytes (%.2f MB)。请减少数据量或分批处理。",
bytes.length, MAX_SERIALIZATION_SIZE, bytes.length / (1024.0 * 1024.0)));
}
String jsonString = outputStream.toString("UTF-8");
// 确保 JSON 字符串以正确的字符集传递给 MySQL
preparedStatement.setObject(i, jsonString, java.sql.Types.VARCHAR);
} catch (JsonProcessingException e) {
throw new SQLException("序列化失败: " + e.getMessage(), e);
} catch (IOException e) {
throw new SQLException("序列化IO失败: " + e.getMessage(), e);
} catch (OutOfMemoryError e) {
throw new SQLException("序列化时内存溢出请减少数据量或增加JVM堆内存。", e);
}
}
}
@Override
public Object getNullableResult(ResultSet resultSet, String s) throws SQLException {
if (null != resultSet.getString(s)) {
try {
return objectMapper.readValue(resultSet.getString(s), Object.class);
} catch (JsonProcessingException e) {
throw new SQLException("反序列化失败", e);
}
}
return null;
}
@Override
public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
if (null != resultSet.getString(i)) {
try {
return objectMapper.readValue(resultSet.getString(i), Object.class);
} catch (JsonProcessingException e) {
throw new SQLException("反序列化失败", e);
}
}
return null;
}
@Override
public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
if (null != callableStatement.getString(i)) {
try {
return objectMapper.readValue(callableStatement.getString(i), Object.class);
} catch (JsonProcessingException e) {
throw new SQLException("反序列化失败", e);
}
}
return null;
}
}

View File

@@ -0,0 +1,140 @@
package com.xspaceagi.system.spec.common;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
/**
* 支持泛型 List 的 JSON TypeHandler
*/
public abstract class ListJsonTypeHandler<T> extends BaseTypeHandler<List<T>> {
private static final ObjectMapper objectMapper;
/**
* 最大序列化大小限制100MB
* 超过此大小会抛出明确的异常,而不是导致 OOM
*/
private static final long MAX_SERIALIZATION_SIZE = 100 * 1024 * 1024L;
/**
* 最大列表元素数量限制10000
* 超过此数量会抛出明确的异常
*/
private static final int MAX_LIST_SIZE = 10000;
static {
objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 配置 StreamReadConstraints 以支持更大的字符串长度
// 设置最大字符串长度为 100MB (100 * 1024 * 1024 字符)
StreamReadConstraints constraints = StreamReadConstraints.builder()
.maxStringLength(100 * 1024 * 1024)
.build();
JsonFactory factory = objectMapper.getFactory();
factory.setStreamReadConstraints(constraints);
}
/**
* 子类需要提供 TypeReference 以支持正确的泛型反序列化
*/
protected abstract TypeReference<List<T>> getTypeReference();
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<T> list, JdbcType jdbcType)
throws SQLException {
if (Objects.nonNull(list)) {
// 检查列表大小
if (list.size() > MAX_LIST_SIZE) {
throw new SQLException(String.format(
"列表大小超过限制: %d > %d无法序列化。请减少数据量或分批处理。",
list.size(), MAX_LIST_SIZE));
}
try {
// 使用 ByteArrayOutputStream 来限制内存使用并检查大小
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (JsonGenerator generator = objectMapper.getFactory().createGenerator(outputStream)) {
objectMapper.writeValue(generator, list);
}
// 检查序列化后的大小
byte[] bytes = outputStream.toByteArray();
if (bytes.length > MAX_SERIALIZATION_SIZE) {
throw new SQLException(String.format(
"序列化后的数据大小超过限制: %d bytes > %d bytes (%.2f MB)。请减少数据量或分批处理。",
bytes.length, MAX_SERIALIZATION_SIZE, bytes.length / (1024.0 * 1024.0)));
}
String jsonString = outputStream.toString("UTF-8");
// 确保 JSON 字符串以正确的字符集传递给 MySQL
preparedStatement.setObject(i, jsonString, java.sql.Types.VARCHAR);
} catch (JsonProcessingException e) {
throw new SQLException("序列化失败: " + e.getMessage(), e);
} catch (IOException e) {
throw new SQLException("序列化IO失败: " + e.getMessage(), e);
} catch (OutOfMemoryError e) {
throw new SQLException(String.format(
"序列化时内存溢出。列表大小: %d请减少数据量或增加JVM堆内存。", list.size()), e);
}
}
}
@Override
public List<T> getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
String json = resultSet.getString(columnName);
if (json != null && !json.isEmpty()) {
try {
return objectMapper.readValue(json, getTypeReference());
} catch (JsonProcessingException e) {
throw new SQLException("反序列化失败: columnName=" + columnName + ", json=" + json, e);
}
}
return null;
}
@Override
public List<T> getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
String json = resultSet.getString(columnIndex);
if (json != null && !json.isEmpty()) {
try {
return objectMapper.readValue(json, getTypeReference());
} catch (JsonProcessingException e) {
throw new SQLException("反序列化失败: columnIndex=" + columnIndex + ", json=" + json, e);
}
}
return null;
}
@Override
public List<T> getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
String json = callableStatement.getString(columnIndex);
if (json != null && !json.isEmpty()) {
try {
return objectMapper.readValue(json, getTypeReference());
} catch (JsonProcessingException e) {
throw new SQLException("反序列化失败: columnIndex=" + columnIndex + ", json=" + json, e);
}
}
return null;
}
}

View File

@@ -0,0 +1,29 @@
package com.xspaceagi.system.spec.common;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Getter
@Setter
public class LoginWrapper {
/**
* 用户ID
*/
private Long userId;
/**
* 是否登录
*/
private boolean isLogin;
/**
* 用户信息
*/
private UserContext user;
}

View File

@@ -0,0 +1,72 @@
package com.xspaceagi.system.spec.common;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* 操作日志(SysOperatorLog)实体类
*
* @author p1
* @since 2024-11-01 11:16:02
*/
@Schema(description = "操作日志")
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class OperatorLogContext {
private Long tenantId;
/**
* 客户端请求时间
*/
private Long clientTime;
/**
* 客户端ip
*/
private String ip;
@Schema(description = "1:操作类型;2:访问日志")
private Long operateType;
@Schema(description = "系统编码")
private String systemCode;
@Schema(description = "系统名称")
private String systemName;
@Schema(description = "操作对象,比如:用户表,角色表,菜单表")
private String object;
@Schema(description = "操作动作,比如:新增,删除,修改,查看")
private String action;
@Schema(description = "操作内容,比如评估页面")
private String operateContent;
@Schema(description = "额外的操作内容信息记录,比如:更新提交的数据内容")
private String extraContent;
@Schema(description = "操作人所属机构id")
private Long orgId;
@Schema(description = "操作人所属机构名称")
private String orgName;
@Schema(description = "创建人id")
private Long userId;
@Schema(description = "创建人名称")
private String creator;
@Schema(description = "操作状态,成功;失败")
private String status;
}

View File

@@ -0,0 +1,117 @@
package com.xspaceagi.system.spec.common;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@Slf4j
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Getter
@Setter
public class RequestContext<T> implements Serializable {
private static ThreadLocal<RequestContext> threadLocal = new ThreadLocal<>();
private static ThreadLocal<Set<String>> tenantIgnoreTablesLocal = new ThreadLocal<>();
private Long userId;
private Long tenantId;
private Object tenantConfig;
private String clientIp;
private String clientLang;
private String clientCookieLang;
private String lang;//最终的语言
private Map<String, String> langMap;
private boolean isLogin;
private T user;
private UserContext userContext;
private String token;
private String requestId;
private Object akTarget;
private Object userAccessKey;
public static <T> void set(RequestContext<T> requestContext) {
requestContext.setRequestId(UUID.randomUUID().toString().replace("-", ""));
threadLocal.set(requestContext);
log.debug("RequestContext set, userId:{}, tenantId: {}", requestContext.getUserId(), requestContext.getTenantId());
}
public static <T> RequestContext<T> get() {
return threadLocal.get();
}
public static <T> void remove() {
RequestContext requestContext = get();
log.debug("RequestContext remove, userId:{}, tenantId: {}", requestContext == null ? null : requestContext.getUserId(),
requestContext == null ? null : requestContext.getTenantId());
threadLocal.remove();
tenantIgnoreTablesLocal.remove();
}
/**
* 跨线程运行,设置一个新的租户ID,用于数据库租户隔离使用
*
* @param tenantId 租户ID
*/
public static void setThreadTenantId(Long tenantId) {
log.debug("RequestContext setThreadTenantId, tenantId: {}", tenantId);
RequestContext<?> requestContext = new RequestContext<>();
requestContext.setTenantId(tenantId);
threadLocal.set(requestContext);
}
/**
* 获取租户忽略表
*
* @return
*/
public static Set<String> getTenantIgnoreTables() {
Set<String> tenantIgnoreTables = RequestContext.tenantIgnoreTablesLocal.get();
if (tenantIgnoreTables == null) {
RequestContext.tenantIgnoreTablesLocal.set(new HashSet<>());
}
return tenantIgnoreTables == null ? RequestContext.tenantIgnoreTablesLocal.get() : tenantIgnoreTables;
}
/**
* 添加忽略表
*
* @param clazz
*/
public static void addTenantIgnoreEntity(Class<?> clazz) {
TableName tableName = clazz.getAnnotation(TableName.class);
if (tableName != null) {
getTenantIgnoreTables().add(tableName.value());
}
}
/**
* 移除忽略表
*
* @param clazz
*/
public static void removeTenantIgnoreEntity(Class<?> clazz) {
TableName tableName = clazz.getAnnotation(TableName.class);
if (tableName != null) {
getTenantIgnoreTables().remove(tableName.value());
}
}
public void setUserId(Long userId) {
log.debug("RequestContext setUserId, userId: {}", userId);
this.userId = userId;
}
}

View File

@@ -0,0 +1,69 @@
package com.xspaceagi.system.spec.common;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Map;
/**
* 用户信息,从拦截器里获取到的用户信息
*/
@Getter
@Setter
@Builder
public class UserContext {
/**
* 用户ID
*/
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "用户唯一标识,部分租户会有值")
private String uid;
@Schema(description = "头像")
private String avatar;
/**
* 用户名
*/
@Schema(description = "用户名")
private String userName;
@Schema(description = "用户昵称")
private String nickName;
@Schema(description = "管理员邮箱,密文")
private String email;
/**
* 手机号
*/
@Schema(description = "手机号")
private String phone;
@Schema(description = "用户状态1:启用;-1:禁用")
private Integer status;
@Schema(description = "所属机构ID")
private Long orgId;
@Schema(description = "所属机构名称")
private String orgName;
@Schema(description = "角色类型1:管理员角色;2:普通角色")
private Integer roleType;
@Schema(description = "所属租户ID")
private Long tenantId;
@Schema(description = "所属租户名称")
private String tenantName;
private Object tenantConfig;
@Schema(description = "语言环境")
private Map<String, String> langMap;
}

View File

@@ -0,0 +1,22 @@
package com.xspaceagi.system.spec.config;
import com.google.common.eventbus.EventBus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* EventBus配置类
* 用于管理Guava EventBus实例
*/
@Slf4j
@Configuration
public class EventBusConfig {
@Bean
public EventBus eventBus() {
EventBus eventBus = new EventBus();
log.info("EventBus配置初始化完成");
return eventBus;
}
}

View File

@@ -0,0 +1,65 @@
package com.xspaceagi.system.spec.constants;
/**
* i18n 内置 JSON 导出目录与命名(与 classpath {@code i18n/} 下资源一致)。
*/
public final class I18nSyncConstants {
private I18nSyncConstants() {
}
/**
* 导出 i18n JSON 的默认基础路径(相对项目根目录,与权限导出同级约定)。
*/
public static final String I18N_JSON_EXPORT_BASE_PATH =
"app-platform-modules/platform-system/system-application/src/main/resources/i18n";
/**
* classpath 下语言列表:{@code i18n/i18n-lang-{version}.json}
*/
public static String buildI18nLangClasspathPath(String version) {
return "i18n/i18n-lang-" + version + ".json";
}
/**
* 导出文件名:{@code i18n-config-{version}.json}
*/
public static String buildI18nConfigExportFileName(String version) {
return "i18n-config-" + version + ".json";
}
/**
* classpath 配置项:{@code i18n/i18n-config-{version}.json}
*/
public static String buildI18nConfigClasspathPath(String version) {
return "i18n/" + buildI18nConfigExportFileName(version);
}
/**
* 新增差异文件名:{@code i18n-config-{version}-add.json}
*/
public static String buildI18nConfigAddFileName(String version) {
return "i18n-config-" + version + "-add.json";
}
/**
* classpath 新增差异配置:{@code i18n/i18n-config-{version}-add.json}
*/
public static String buildI18nConfigAddClasspathPath(String version) {
return "i18n/" + buildI18nConfigAddFileName(version);
}
/**
* 变更差异文件名:{@code i18n-config-{version}-update.json}
*/
public static String buildI18nConfigUpdateFileName(String version) {
return "i18n-config-" + version + "-update.json";
}
/**
* classpath 变更差异配置:{@code i18n/i18n-config-{version}-update.json}
*/
public static String buildI18nConfigUpdateClasspathPath(String version) {
return "i18n/" + buildI18nConfigUpdateFileName(version);
}
}

View File

@@ -0,0 +1,24 @@
package com.xspaceagi.system.spec.constants;
import java.util.List;
import java.util.Set;
import static com.xspaceagi.system.spec.enums.MenuEnum.ROLE_MANAGE;
import static com.xspaceagi.system.spec.enums.ResourceEnum.ROLE_MANAGE_BIND_MENU;
import static com.xspaceagi.system.spec.enums.ResourceEnum.ROLE_MANAGE_QUERY;
public class PermissionConstants {
private PermissionConstants() {
}
// 超管必须具备的菜单
public static Set<String> superAdminNecessaryMenus = Set.of(
ROLE_MANAGE.getCode()
);
// 超管必须具备的资源
public static Set<String> superAdminNecessaryResources = Set.of(
ROLE_MANAGE_QUERY.getCode(),
ROLE_MANAGE_BIND_MENU.getCode()
);
}

View File

@@ -0,0 +1,55 @@
package com.xspaceagi.system.spec.constants;
/**
* 权限同步 JSON 文件路径常量
* <p>
* 导出与导入使用同一目录:{@code system-application/src/main/resources/permission/}
* 文件命名:{@code permission-{version}.json}
* </p>
*/
public class PermissionSyncConstants {
private PermissionSyncConstants() {
}
/**
* 导入权限 JSON 的 classpath 路径前缀
* 完整路径:{@code permission/permission-{version}.json}
*/
public static final String PERMISSION_JSON_CLASSPATH_PREFIX = "permission/permission-";
/**
* 导出权限 JSON 的默认基础路径(相对项目根目录)
* 完整路径:{@code {basePath}/permission-{version}.json}
*/
public static final String PERMISSION_JSON_EXPORT_BASE_PATH = "app-platform-modules/platform-system/system-application/src/main/resources/permission";
/**
* 根据版本构建 classpath 路径(导入权限用)
*/
public static String buildClasspathPath(String version) {
return PERMISSION_JSON_CLASSPATH_PREFIX + version + ".json";
}
/**
* 根据版本构建导出文件路径(导出权限用,需拼接 basePath
*/
public static String buildExportFileName(String version) {
return "permission-" + version + ".json";
}
/**
* 差异 JSON 的 classpath 路径前缀
* 完整路径:{@code permission/permission-{toVersion}-diff.json}
*/
public static String buildDiffClasspathPath(String toVersion) {
return "permission/permission-" + toVersion + "-diff.json";
}
/**
* 根据目标版本构建差异文件名
*/
public static String buildDiffFileName(String toVersion) {
return "permission-" + toVersion + "-diff.json";
}
}

View File

@@ -0,0 +1,91 @@
package com.xspaceagi.system.spec.constants;
/**
* Redis Key 常量统一管理
* <p>
* 系统为租户隔离架构,所有 Redis 缓存 key 均需动态加上 tenantId 实现租户隔离。
* 格式示例:{prefix}:{tenantId}:{businessId}
* </p>
*/
public class RedisKeyConstants {
private RedisKeyConstants() {
// 工具类,禁止实例化
}
// ==================== 权限相关缓存 ====================
/**
* 用户权限缓存 key 前缀使用Hash存储
* 完整 key 格式user:permission:{tenantId}:{userId}
*/
public static final String USER_PERMISSION_CACHE_KEY = "user:permission:";
/**
* 权限最新生效时间 key 前缀(按租户隔离,用于判断缓存是否失效)
* 完整 key 格式permission:latest:time:{tenantId}
*/
public static final String PERMISSION_LATEST_TIME_KEY = "permission:latest:time:";
/**
* 构建用户权限缓存 key租户隔离
*
* @param tenantId 租户ID
* @param userId 用户ID
* @return user:permission:{tenantId}:{userId}
*/
public static String buildUserPermissionCacheKey(Long tenantId, Long userId) {
return USER_PERMISSION_CACHE_KEY + tenantId + ":" + userId;
}
/**
* 构建权限最新生效时间 key租户隔离
*
* @param tenantId 租户ID
* @return permission:latest:time:{tenantId}
*/
public static String buildPermissionLatestTimeKey(Long tenantId) {
return PERMISSION_LATEST_TIME_KEY + tenantId;
}
/**
* Hash存储字段名菜单树
*/
public static final String HASH_FIELD_MENU_TREE = "menuTree";
/**
* Hash存储字段名资源码集合
*/
public static final String HASH_FIELD_RESOURCE_CODES = "resourceCodes";
/**
* Hash存储字段名数据权限
*/
public static final String HASH_FIELD_DATA_PERMISSION = "dataPermission";
/**
* Hash存储字段名用户角色ID集合
*/
public static final String HASH_FIELD_ROLE_IDS = "roleIds";
/**
* Hash存储字段名用户组ID集合
*/
public static final String HASH_FIELD_GROUP_IDS = "groupIds";
/**
* Hash存储字段名缓存生成时间毫秒时间戳
*/
public static final String HASH_FIELD_CACHE_TIME = "cacheTime";
/**
* 用户权限相关缓存过期时间(秒)
*/
public static final long USER_PERMISSION_CACHE_EXPIRE_SECONDS = 24 * 60 * 60L; // 24小时
/**
* 按用户清除缓存的阈值:超过此数量的用户时,改为清除全部缓存(避免大量定向删除占用资源)
*/
public static final int CLEAR_CACHE_BY_USER_IDS_THRESHOLD = 500;
}

View File

@@ -0,0 +1,50 @@
package com.xspaceagi.system.spec.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
/**
* <p>
* 分页查询VO
* </p>
*
*/
@Schema(description = "分页查询VO")
public class PageQueryVo<T> {
@Schema(description = "分页查询过滤条件")
private T queryFilter;
@NotNull(message = "pageNo is required")
@Schema(description = "分页pageNo", required = true, example = "1")
private Long pageNo;
@NotNull(message = "pageSize is required")
@Schema(description = "分页pageSize", required = true, example = "10")
private Long pageSize;
public T getQueryFilter() {
return queryFilter;
}
public void setQueryFilter(T queryFilter) {
this.queryFilter = queryFilter;
}
public Long getPageNo() {
return pageNo;
}
public void setPageNo(Long pageNo) {
this.pageNo = pageNo;
}
public Long getPageSize() {
return pageSize;
}
public void setPageSize(Long pageSize) {
this.pageSize = pageSize;
}
}

View File

@@ -0,0 +1,92 @@
package com.xspaceagi.system.spec.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Schema(description = "请求响应信息")
public class ReqResult<T> implements Serializable {
public static final String SUCCESS = "0000";
@Schema(description = "业务状态码0000 表示成功,其余失败", example = "0000")
private String code = SUCCESS;
@Schema(description = "源系统状态码,用于问题跟踪", example = "0000")
private String displayCode;
@Schema(description = "错误描述信息")
private String message;
@Schema(description = "返回的具体业务数据")
private T data = null;
@Schema(description = "跟踪唯一标识")
private String tid;
public ReqResult(final String code, final String displayCode, final String message) {
this.code = code;
this.displayCode = displayCode;
this.message = message;
}
public ReqResult(String code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public ReqResult(String code, String displayCode, String message, T data) {
this.code = code;
this.displayCode = displayCode;
this.message = message;
this.data = data;
}
public boolean isSuccess() {
return "0000".equals(this.code);
}
public static <T> ReqResult<T> success() {
return create("0000", "成功", null);
}
public static <T> ReqResult<T> success(T obj) {
return create("0000", "success", obj);
}
public static <Void> ReqResult<Void> error(String msg) {
return create("0001", msg, null);
}
public static <Void> ReqResult<Void> error(String code, String displayCode, String msg) {
return create(code, displayCode, msg, null);
}
public static <Void> ReqResult<Void> error(String code, String msg) {
return create(code, code, msg, null);
}
public static <T> ReqResult<T> create(String code, String msg, T data) {
return new ReqResult(code, code, msg, data);
}
public static <T> ReqResult<T> create(String displayCode, String code, String msg, T data) {
return new ReqResult(code, displayCode, msg, data);
}
}

View File

@@ -0,0 +1,25 @@
package com.xspaceagi.system.spec.enums;
public enum AuthTypeEnum {
PHONE(1, "手机"),
EMAIL(3, "邮箱"),
CAS(2, "CAS");
private int code;
private String description;
AuthTypeEnum(int code, String description) {
this.code = code;
this.description = description;
}
public int getCode() {
return code;
}
public String getDescription() {
return description;
}
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 绑定类型枚举
*/
@Getter
public enum BindTypeEnum {
NONE(0, "NONE"),// 未绑定
ALL(1, "ALL"),// 全部绑定
PART( 2, "PART");//部分绑定
private final Integer code;
private final String desc;
BindTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static BindTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (BindTypeEnum typeEnum : values()) {
if (typeEnum.getCode().equals(code)) {
return typeEnum;
}
}
return null;
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,39 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 分类类型枚举
*/
@Getter
public enum CategoryTypeEnum {
AGENT("Agent", "智能体"),
PAGE_APP("PageApp", "网页应用"),
COMPONENT("Component", "组件");
private final String code;
private final String description;
CategoryTypeEnum(String code, String description) {
this.code = code;
this.description = description;
}
public static CategoryTypeEnum fromCode(String code) {
for (CategoryTypeEnum type : values()) {
if (type.getCode().equals(code)) {
return type;
}
}
return null;
}
public static boolean isValid(String code) {
return fromCode(code) != null;
}
public static boolean isInValid(String code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,9 @@
package com.xspaceagi.system.spec.enums;
public enum CodeTypeEnum {
LOGIN_OR_REGISTER,
RESET_PASSWORD,
BIND_EMAIL,
VERIFY_CODE
}

View File

@@ -0,0 +1,54 @@
package com.xspaceagi.system.spec.enums;
public enum ErrorCodeEnum {
SUCCESS("0000", "请求成功"),
ERROR_REQUEST("0001", "请求失败"),
INVALID_PARAM("4000", "参数错误"),
INVALID_INVITE_CODE("4001", "邀请码错误"),
PERMISSION_DENIED("4030", "无权限"),
RESOURCE_PERMISSION_DENIED("4033", "无此资源权限"),
UNAUTHORIZED("4010", "未登录或登录超时"),
UNAUTHORIZED_REDIRECT("4011", "未登录或登录超时"),
API_NOT_FOUND("4040", "接口不存在"),
METHOD_NOT_ALLOWED("4050", "未登录或登录超时"),
SYS_ERROR("5000", "系统异常"),
PROJECT_STARTING("6001", "项目启动中,请稍等"),
/** License 文件内容解析失败(与历史契约码 0400 对齐) */
LICENSE_CONTENT_INVALID("0400", "许可证内容无效");
private String code;
private String msg;
/**
* @param code
* @param msg
*/
ErrorCodeEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
/**
* @return the code
*/
public String getCode() {
return code;
}
/**
* @param code the code to set
*/
/**
* @return the msg
*/
public String getMsg() {
return msg;
}
}

View File

@@ -0,0 +1,33 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 系统内置用户组
*/
@Getter
public enum GroupEnum {
DEFAULT_GROUP("default_group", "默认用户组");
private final String code;
private final String name;
GroupEnum(String code, String name) {
this.code = code;
this.name = name;
}
public static GroupEnum getByCode(String code) {
if (code == null) {
return null;
}
for (GroupEnum resourceEnum : values()) {
if (resourceEnum.getCode().equals(code)) {
return resourceEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,136 @@
package com.xspaceagi.system.spec.enums;
public enum HttpStatusEnum {
CONTINUE(100, "Continue", "请继续发送请求的剩余部分"),
SWITCHING_PROTOCOLS(101, "Switching Protocols", "协议切换"),
PROCESSING(102, "Processing", "请求将继续执行"),
// for 103 https://news.ycombinator.com/item?id=15590049
CHECKPOINT(103, "Checkpoint", "可以预加载"),
OK(200, "OK", "请求已经成功处理"),
CREATED(201, "Created", "请求已经成功处理,并创建了资源"),
ACCEPTED(202, "Accepted", "请求已经接受,等待执行"),
NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information", "请求已经成功处理,但是信息不是原始的"),
NO_CONTENT(204, "No Content", "请求已经成功处理,没有内容需要返回"),
RESET_CONTENT(205, "Reset Content", "请求已经成功处理,请重置视图"),
PARTIAL_CONTENT(206, "Partial Content", "部分Get请求已经成功处理"),
MULTI_STATUS(207, "Multi-Status", "请求已经成功处理将返回XML消息体"),
ALREADY_REPORTED(208, "Already Reported", "请求已经成功处理一个DAV的绑定成员被前一个请求枚举并且没有被再一次包括"),
IM_USED(226, "IM Used", "请求已经成功处理,将响应一个或者多个实例"),
MULTIPLE_CHOICES(300, "Multiple Choices", "提供可供选择的回馈"),
MOVED_PERMANENTLY(301, "Moved Permanently", "请求的资源已经永久转移"),
FOUND(302, "Found", "请重新发送请求"),
// MOVED_TEMPORARILY(302, "Moved Temporarily", "") 已经过时
SEE_OTHER(303, "See Other", "请以Get方式请求另一个URI"),
NOT_MODIFIED(304, "Not Modified", "资源未改变"),
USE_PROXY(305, "Use Proxy", "请通过Location域中的代理进行访问"),
// 306在新版本的规范中被弃用
TEMPORARY_REDIRECT(307, "Temporary Redirect", "请求的资源临时从不同的URI响应请求"),
RESUME_INCOMPLETE(308, "Resume Incomplete", "请求的资源已经永久转移"),
BAD_REQUEST(400, "Bad Request", "请求错误,请修正请求"),
UNAUTHORIZED(401, "Unauthorized", "没有被授权或者授权已经失效"),
PAYMENT_REQUIRED(402, "Payment Required", "预留状态"),
FORBIDDEN(403, "Forbidden", "请求被理解,但是拒绝执行"),
NOT_FOUND(404, "Not Found", "资源未找到"),
METHOD_NOT_ALLOWED(405, "Method Not Allowed", "请求方法不允许被执行"),
NOT_ACCEPTABLE(406, "Not Acceptable", "请求的资源不满足请求者要求"),
PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required", "请通过代理进行身份验证"),
REQUEST_TIMEOUT(408, "Request Timeout", "请求超时"),
CONFLICT(409, "Conflict", "请求冲突"),
GONE(410, "Gone", "请求的资源不可用"),
LENGTH_REQUIRED(411, "Length Required", "Content-Length未定义"),
PRECONDITION_FAILED(412, "Precondition Failed", "不满足请求的先决条件"),
REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large", "请求发送的实体太大"),
REQUEST_URI_TOO_LONG(414, "Request-URI Too Long", "请求的URI超长"),
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type", "请求发送的实体类型不受支持"),
REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested range not satisfiable", "Range指定的范围与当前资源可用范围不一致"),
EXPECTATION_FAILED(417, "Expectation Failed", "请求头Expect中指定的预期内容无法被服务器满足"),
// I_AM_A_TEAPOT(418, "I'm a teapot", ""), 该代码没有被服务器实现
// INSUFFICIENT_SPACE_ON_RESOURCE(419, "Insufficient Space On Resource", ""), 已经过时
// METHOD_FAILURE(420, "Method Failure", ""), 已经过时
// DESTINATION_LOCKED(421, "Destination Locked", ""), 已经过时
UNPROCESSABLE_ENTITY(422, "Unprocessable Entity", "请求格式正确,但是由于含有语义错误,无法响应"),
LOCKED(423, "Locked", "当前资源被锁定"),
FAILED_DEPENDENCY(424, "Failed Dependency", "由于之前的请求发生错误,导致当前请求失败"),
UPGRADE_REQUIRED(426, "Upgrade Required", "客户端需要切换到TLS1.0"),
PRECONDITION_REQUIRED(428, "Precondition Required", "请求需要提供前置条件"),
TOO_MANY_REQUESTS(429, "Too Many Requests", "请求过多"),
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large", "请求头超大,拒绝请求"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error", "服务器内部错误"),
NOT_IMPLEMENTED(501, "Not Implemented", "服务器不支持当前请求的部分功能"),
BAD_GATEWAY(502, "Bad Gateway", "响应无效"),
SERVICE_UNAVAILABLE(503, "Service Unavailable", "服务器维护或者过载,拒绝服务"),
GATEWAY_TIMEOUT(504, "Gateway Timeout", "上游服务器超时"),
HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version not supported", "不支持的HTTP版本"),
VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates", "服务器内部配置错误"),
INSUFFICIENT_STORAGE(507, "Insufficient Storage", "服务器无法完成存储请求所需的内容"),
LOOP_DETECTED(508, "Loop Detected", "服务器处理请求时发现死循环"),
BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded", "服务器达到带宽限制"),
NOT_EXTENDED(510, "Not Extended", "获取资源所需的策略没有被满足"),
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required", "需要进行网络授权");
private final int code;
private final String reasonPhraseUS;
private final String reasonPhraseCN;
private static final int
INFORMATIONAL = 1,
successFUL = 2,
REDIRECTION = 3,
CLIENT_ERROR = 4,
SERVER_ERROR = 5;
HttpStatusEnum(int code, String reasonPhraseUS, String reasonPhraseCN) {
this.code = code;
this.reasonPhraseUS = reasonPhraseUS;
this.reasonPhraseCN = reasonPhraseCN;
}
public int code() {
return code;
}
public String reasonPhraseUS() {
return reasonPhraseUS;
}
public String reasonPhraseCN() {
return reasonPhraseCN;
}
public static HttpStatusEnum valueOf(int code) {
for (HttpStatusEnum httpStatus : values()) {
if (httpStatus.code() == code) {
return httpStatus;
}
}
throw new IllegalArgumentException("No matching constant for [" + code + "]");
}
public boolean is1xxInformational() {
return type() == INFORMATIONAL;
}
public boolean is2xxSuccessful() {
return type() == successFUL;
}
public boolean is3xxRedirection() {
return type() == REDIRECTION;
}
public boolean is4xxClientError() {
return type() == CLIENT_ERROR;
}
public boolean is5xxServerError() {
return type() == SERVER_ERROR;
}
private int type() {
return (int) code / 100;
}
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 时段类型枚举
*/
@Getter
public enum I18nSideEnum {
PC("PC", "pc"),
Mobile("Mobile", "h5"),
Claw("Claw", "qiming claw"),
Backend("Backend", "backend notice");
private final String side;
private final String desc;
I18nSideEnum(String side, String desc) {
this.side = side;
this.desc = desc;
}
public static I18nSideEnum fromSide(String side) {
if (side == null) {
return null;
}
for (I18nSideEnum type : I18nSideEnum.values()) {
if (type.getSide().equals(side)) {
return type;
}
}
return null;
}
public static boolean isValid(String side) {
return fromSide(side) != null;
}
public static boolean isInValid(String code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,46 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 系统内置菜单(部分)特殊用到的定义到这里
*/
@Getter
public enum MenuEnum {
ROOT("root", "根节点", "根节点"),
ECO_MARKET("eco_market", "生态市场", "root"),
SYSTEM_MANAGE("system_manage", "系统管理", "root"),
PERMISSION_MANAGE("permission_manage", "权限管理", "system_manage"),
RESOURCE_MANAGE("resource_manage", "资源管理", "permission_manage"),
MENU_MANAGE("menu_manage", "菜单管理", "permission_manage"),
ROLE_MANAGE("role_manage", "角色管理", "permission_manage"),
USER_GROUP_MANAGE("user_group_manage", "用户组管理", "permission_manage");
private final String code;
private final String name;
private final String parentCode;
MenuEnum(String code, String name, String parentCode) {
this.code = code;
this.name = name;
this.parentCode = parentCode;
}
/**
* 根据code获取枚举
*/
public static MenuEnum getByCode(String code) {
if (code == null) {
return null;
}
for (MenuEnum resourceEnum : values()) {
if (resourceEnum.getCode().equals(code)) {
return resourceEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,41 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 打开方式
*/
@Getter
public enum OpenTypeEnum {
CURRENT_TAB(1, "当前标签页打开"),
NEW_TAB(2, "新标签页打开");
private final Integer code;
private final String desc;
OpenTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static OpenTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (OpenTypeEnum typeEnum : values()) {
if (typeEnum.getCode().equals(code)) {
return typeEnum;
}
}
return null;
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 时段类型枚举
*/
@Getter
public enum PeriodTypeEnum {
YEAR("YEAR", ""),
MONTH("MONTH", ""),
DAY("DAY", ""),
HOUR("HOUR", "");
private final String code;
private final String desc;
PeriodTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static PeriodTypeEnum fromCode(String code) {
if (code == null) {
return null;
}
for (PeriodTypeEnum type : PeriodTypeEnum.values()) {
if (type.getCode().equals(code)) {
return type;
}
}
return null;
}
public static boolean isValid(String code) {
return fromCode(code) != null;
}
public static boolean isInValid(String code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,45 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 权限主体类型枚举
*/
@Getter
public enum PermissionSubjectTypeEnum {
MODEL(1, "模型"),
AGENT(2, "通用智能体"),
PAGE(3, "应用页面"),
OPEN_API(4, "开放API"),
KNOWLEDGE(5, "知识库");
private final Integer code;
private final String desc;
PermissionSubjectTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static PermissionSubjectTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (PermissionSubjectTypeEnum typeEnum : values()) {
if (typeEnum.getCode().equals(code)) {
return typeEnum;
}
}
return null;
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 来源枚举
*/
@Getter
public enum PermissionTargetTypeEnum {
USER(1, "用户"),
ROLE(2, "角色"),
GROUP(3, "用户组");
private final Integer code;
private final String desc;
PermissionTargetTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static PermissionTargetTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (PermissionTargetTypeEnum typeEnum : values()) {
if (typeEnum.getCode().equals(code)) {
return typeEnum;
}
}
return null;
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,462 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 系统内置资源
*/
@Getter
public enum ResourceEnum {
ROOT(ResourceTypeEnum.MODULE, "root", "根节点", "根节点"),
// ================== 主页模块 ==================
// HOMEPAGE(ResourceTypeEnum.MODULE, "homepage", "主页模块", "root"),
// ================== 生态市场模块 ==================
// ECO_MARKET(ResourceTypeEnum.MODULE, "eco_market", "生态市场模块", "root"),
// ================== 空间模块 ==================
SPACE(ResourceTypeEnum.MODULE, "space", "空间模块", "root"),
// SPACE_QUERY_LIST(ResourceTypeEnum.OPERATION, "space_query_list", "查询空间列表", "space"),
// SPACE_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "space_query_detail", "查询空间详情", "space"),
SPACE_CREATE(ResourceTypeEnum.OPERATION, "space_create", "创建团队空间", "space"),
SPACE_MODIFY(ResourceTypeEnum.OPERATION, "space_modify", "编辑", "space"),
SPACE_DELETE(ResourceTypeEnum.OPERATION, "space_delete", "删除空间", "space"),
SPACE_TRANSFER(ResourceTypeEnum.OPERATION, "space_transfer", "转让空间", "space"),
SPACE_QUERY_USER_LIST(ResourceTypeEnum.OPERATION, "space_query_user_list", "查询成员列表", "space"),
SPACE_ADD_USER(ResourceTypeEnum.OPERATION, "space_add_user", "添加成员", "space"),
SPACE_DELETE_USER(ResourceTypeEnum.OPERATION, "space_delete_user", "删除成员", "space"),
// ================== 智能体开发模块 ==================
AGENT_DEV(ResourceTypeEnum.MODULE, "agent_dev", "智能体开发模块", "root"),
AGENT_CREATE_CHAT_BOT(ResourceTypeEnum.OPERATION, "agent_create_chat_bot", "创建智能体-问答型", "agent_dev"),
AGENT_CREATE_TASK_AGENT(ResourceTypeEnum.OPERATION, "agent_create_task_agent", "创建智能体-通用型", "agent_dev"),
AGENT_PUBLISH(ResourceTypeEnum.OPERATION, "agent_publish", "发布", "agent_dev"),
AGENT_IMPORT(ResourceTypeEnum.OPERATION, "agent_import", "导入配置", "agent_dev"),
AGENT_QUERY_LIST(ResourceTypeEnum.OPERATION, "agent_query_list", "查询列表", "agent_dev"),
AGENT_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "agent_query_detail", "查询详情", "agent_dev"),
AGENT_COLLECT(ResourceTypeEnum.OPERATION, "agent_collect", "收藏", "agent_dev"),
AGENT_MODIFY(ResourceTypeEnum.OPERATION, "agent_modify", "编辑", "agent_dev"),
AGENT_COPY_TO_SPACE(ResourceTypeEnum.OPERATION, "agent_copy_to_space", "复制到空间", "agent_dev"),
AGENT_MIGRATE(ResourceTypeEnum.OPERATION, "agent_migrate", "迁移", "agent_dev"),
AGENT_API_KEY(ResourceTypeEnum.OPERATION, "agent_api_key", "API Key", "agent_dev"),
AGENT_EXPORT(ResourceTypeEnum.OPERATION, "agent_export", "导出配置", "agent_dev"),
// AGENT_LOG(ResourceTypeEnum.OPERATION, "agent_log", "日志", "agent_dev"),
AGENT_DELETE(ResourceTypeEnum.OPERATION, "agent_delete", "删除", "agent_dev"),
//AGENT_ANALYSE(ResourceTypeEnum.OPERATION, "agent_analyse", "分析", "agent_dev"),
AGENT_TEMP_CONVERSATION(ResourceTypeEnum.OPERATION, "agent_temp_conversation", "创建临时会话", "agent_dev"),
// ================== 网页应用开发模块 ==================
PAGE_APP_DEV(ResourceTypeEnum.MODULE, "page_app_dev", "网页应用开发模块", "root"),
PAGE_APP_CREATE(ResourceTypeEnum.OPERATION, "page_app_create", "创建", "page_app_dev"),
PAGE_APP_QUERY_LIST(ResourceTypeEnum.OPERATION, "page_app_query_list", "查询列表", "page_app_dev"),
PAGE_APP_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "page_app_query_detail", "查询详情", "page_app_dev"),
PAGE_APP_MODIFY(ResourceTypeEnum.OPERATION, "page_app_modify", "编辑", "page_app_dev"),
PAGE_APP_CONFIG_PROXY(ResourceTypeEnum.OPERATION, "page_app_config_proxy", "反向代理配置", "page_app_dev"),
PAGE_APP_CONFIG_PATH(ResourceTypeEnum.OPERATION, "page_app_config_path", "路径参数配置", "page_app_dev"),
//PAGE_APP_CONFIG_AUTH(ResourceTypeEnum.OPERATION, "page_app_config_auth", "认证配置", "page_app_dev"),
PAGE_APP_COPY_TO_SPACE(ResourceTypeEnum.OPERATION, "page_app_copy_to_space", "复制到空间", "page_app_dev"),
PAGE_APP_BIND_DOMAIN(ResourceTypeEnum.OPERATION, "page_app_bind_domain", "绑定域名", "page_app_dev"),
PAGE_APP_IMPORT(ResourceTypeEnum.OPERATION, "page_app_import", "导入项目", "page_app_dev"),
PAGE_APP_EXPORT(ResourceTypeEnum.OPERATION, "page_app_export", "导出项目", "page_app_dev"),
PAGE_APP_RESTART_SERVER(ResourceTypeEnum.OPERATION, "page_app_restart_server", "重启服务器", "page_app_dev"),
PAGE_APP_PUBLISH(ResourceTypeEnum.OPERATION, "page_app_publish", "发布", "page_app_dev"),
PAGE_APP_DELETE(ResourceTypeEnum.OPERATION, "page_app_delete", "删除", "page_app_dev"),
PAGE_APP_AI_CHAT(ResourceTypeEnum.OPERATION, "page_app_ai_chat", "AI对话", "page_app_dev"),
PAGE_APP_MODIFY_FILE(ResourceTypeEnum.OPERATION, "page_app_modify_file", "修改文件", "page_app_dev"),
PAGE_APP_UPLOAD_FILE(ResourceTypeEnum.OPERATION, "page_app_upload_file", "上传文件", "page_app_dev"),
PAGE_APP_ROLLBACK_VERSION(ResourceTypeEnum.OPERATION, "page_app_rollback_version", "回滚版本", "page_app_dev"),
// ================== 组件资源模块 ==================
COMPONENT_LIB_DEV(ResourceTypeEnum.MODULE, "component_lib_dev", "组件资源模块", "root"),
COMPONENT_LIB_CREATE(ResourceTypeEnum.OPERATION, "component_lib_create", "创建", "component_lib_dev"),
COMPONENT_LIB_PUBLISH(ResourceTypeEnum.OPERATION, "component_lib_publish", "发布", "component_lib_dev"),
COMPONENT_LIB_QUERY_LIST(ResourceTypeEnum.OPERATION, "component_lib_query_list", "查询列表", "component_lib_dev"),
COMPONENT_LIB_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "component_lib_query_detail", "查询详情", "component_lib_dev"),
COMPONENT_LIB_MODIFY(ResourceTypeEnum.OPERATION, "component_lib_modify", "编辑", "component_lib_dev"),
COMPONENT_LIB_COPY_TO_SPACE(ResourceTypeEnum.OPERATION, "component_lib_copy_to_space", "复制到空间", "component_lib_dev"),
COMPONENT_LIB_COPY(ResourceTypeEnum.OPERATION, "component_lib_copy", "复制", "component_lib_dev"),
COMPONENT_LIB_IMPORT(ResourceTypeEnum.OPERATION, "component_lib_import", "导入配置", "component_lib_dev"),
COMPONENT_LIB_EXPORT(ResourceTypeEnum.OPERATION, "component_lib_export", "导出配置", "component_lib_dev"),
COMPONENT_LIB_DELETE(ResourceTypeEnum.OPERATION, "component_lib_delete", "删除", "component_lib_dev"),
/**
* 以下注释的插件、工作流、知识库、数据表、模型,暂时不用这么细分的控制,后续如果要区分的时候再放开
*/
// // ================== 插件模块 ==================
// PLUGIN_DEV(ResourceTypeEnum.MODULE, "plugin_dev", "插件模块", "root"),
//
// PLUGIN_DEV_CREATE(ResourceTypeEnum.OPERATION, "plugin_dev_create", "创建", "plugin_dev"),
// PLUGIN_DEV_PUBLISH(ResourceTypeEnum.OPERATION, "plugin_dev_publish", "发布", "plugin_dev"),
// PLUGIN_DEV_QUERY_LIST(ResourceTypeEnum.OPERATION, "plugin_dev_query_list", "查询列表", "plugin_dev"),
// PLUGIN_DEV_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "plugin_dev_query_detail", "查询详情", "plugin_dev"),
// PLUGIN_DEV_MODIFY(ResourceTypeEnum.OPERATION, "plugin_dev_modify", "编辑", "plugin_dev"),
// PLUGIN_DEV_COPY_TO_SPACE(ResourceTypeEnum.OPERATION, "plugin_dev_copy_to_space", "复制到空间", "plugin_dev"),
// PLUGIN_DEV_COPY(ResourceTypeEnum.OPERATION, "plugin_dev_copy", "复制", "plugin_dev"),
// PLUGIN_DEV_IMPORT(ResourceTypeEnum.OPERATION, "plugin_dev_import", "导入配置", "plugin_dev"),
// PLUGIN_DEV_EXPORT(ResourceTypeEnum.OPERATION, "plugin_dev_export", "导出配置", "plugin_dev"),
// PLUGIN_DEV_DELETE(ResourceTypeEnum.OPERATION, "plugin_dev_delete", "删除", "plugin_dev"),
//
// // ================== 工作流模块 ==================
// WORKFLOW_DEV(ResourceTypeEnum.MODULE, "workflow_dev", "插件模块", "root"),
//
// WORKFLOW_DEV_CREATE(ResourceTypeEnum.OPERATION, "workflow_dev_create", "创建", "workflow_dev"),
// WORKFLOW_DEV_PUBLISH(ResourceTypeEnum.OPERATION, "workflow_dev_publish", "发布", "workflow_dev"),
// WORKFLOW_DEV_QUERY_LIST(ResourceTypeEnum.OPERATION, "workflow_dev_query_list", "查询列表", "workflow_dev"),
// WORKFLOW_DEV_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "workflow_dev_query_detail", "查询详情", "workflow_dev"),
// WORKFLOW_DEV_MODIFY(ResourceTypeEnum.OPERATION, "workflow_dev_modify", "编辑", "workflow_dev"),
// WORKFLOW_DEV_COPY_TO_SPACE(ResourceTypeEnum.OPERATION, "workflow_dev_copy_to_space", "复制到空间", "workflow_dev"),
// WORKFLOW_DEV_COPY(ResourceTypeEnum.OPERATION, "workflow_dev_copy", "复制", "workflow_dev"),
// WORKFLOW_DEV_IMPORT(ResourceTypeEnum.OPERATION, "workflow_dev_import", "导入配置", "workflow_dev"),
// WORKFLOW_DEV_EXPORT(ResourceTypeEnum.OPERATION, "workflow_dev_export", "导出配置", "workflow_dev"),
// WORKFLOW_DEV_DELETE(ResourceTypeEnum.OPERATION, "workflow_dev_delete", "删除", "workflow_dev"),
//
// // ================== 知识库模块 ==================
// KNOWLEDGE_DEV(ResourceTypeEnum.MODULE, "knowledge_dev", "知识库模块", "root"),
// KNOWLEDGE_DEV_CREATE(ResourceTypeEnum.OPERATION, "knowledge_dev_create", "创建", "knowledge_dev"),
// KNOWLEDGE_DEV_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "knowledge_dev_query_detail", "查询详情", "knowledge_dev"),
// KNOWLEDGE_DEV_MODIFY(ResourceTypeEnum.OPERATION, "knowledge_dev_modify", "编辑", "knowledge_dev"),
// KNOWLEDGE_DEV_IMPORT(ResourceTypeEnum.OPERATION, "knowledge_dev_import", "导入配置", "knowledge_dev"),
// KNOWLEDGE_DEV_DELETE(ResourceTypeEnum.OPERATION, "knowledge_dev_delete", "删除", "knowledge_dev"),
//
// // ================== 数据表模块 ==================
// DATATABLE_DEV(ResourceTypeEnum.MODULE, "datatable_dev", "数据表模块", "root"),
// DATATABLE_DEV_CREATE(ResourceTypeEnum.OPERATION, "datatable_dev_create", "创建", "datatable_dev"),
// DATATABLE_DEV_QUERY_LIST(ResourceTypeEnum.OPERATION, "datatable_dev_query_list", "查询列表", "datatable_dev"),
// DATATABLE_DEV_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "datatable_dev_query_detail", "查询详情", "datatable_dev"),
// DATATABLE_DEV_MODIFY(ResourceTypeEnum.OPERATION, "datatable_dev_modify", "编辑", "datatable_dev"),
// DATATABLE_DEV_COPY(ResourceTypeEnum.OPERATION, "datatable_dev_copy", "复制", "datatable_dev"),
// DATATABLE_DEV_IMPORT(ResourceTypeEnum.OPERATION, "datatable_dev_import", "导入配置", "datatable_dev"),
// DATATABLE_DEV_EXPORT(ResourceTypeEnum.OPERATION, "datatable_dev_export", "导出配置", "datatable_dev"),
// DATATABLE_DEV_DELETE(ResourceTypeEnum.OPERATION, "datatable_dev_delete", "删除", "datatable_dev"),
//
// // ================== 模型管理模块 ==================
// MODEL_DEV(ResourceTypeEnum.MODULE, "model_dev", "模型管理模块", "root"),
// MODEL_DEV_CREATE(ResourceTypeEnum.OPERATION, "model_dev_create", "创建", "model_dev"),
// MODEL_DEV_QUERY_LIST(ResourceTypeEnum.OPERATION, "model_dev_query_list", "查询列表", "model_dev"),
// MODEL_DEV_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "model_dev_query_detail", "查询详情", "model_dev"),
// MODEL_DEV_MODIFY(ResourceTypeEnum.OPERATION, "model_dev_modify", "编辑", "model_dev"),
// MODEL_DEV_DELETE(ResourceTypeEnum.OPERATION, "model_dev_delete", "删除", "model_dev"),
// ================== 技能开发模块 ==================
SKILL_DEV(ResourceTypeEnum.MODULE, "skill_dev", "技能开发模块", "root"),
SKILL_CREATE(ResourceTypeEnum.OPERATION, "skill_create", "创建技能", "skill_dev"),
SKILL_QUERY_LIST(ResourceTypeEnum.OPERATION, "skill_query_list", "查询列表", "skill_dev"),
SKILL_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "skill_query_detail", "查询详情", "skill_dev"),
SKILL_MODIFY(ResourceTypeEnum.OPERATION, "skill_modify", "编辑", "skill_dev"),
SKILL_IMPORT(ResourceTypeEnum.OPERATION, "skill_import", "导入技能", "skill_dev"),
SKILL_EXPORT(ResourceTypeEnum.OPERATION, "skill_export", "导出技能", "skill_dev"),
SKILL_COPY_TO_SPACE(ResourceTypeEnum.OPERATION, "skill_copy_to_space", "复制到空间", "skill_dev"),
SKILL_PUBLISH(ResourceTypeEnum.OPERATION, "skill_publish", "发布", "skill_dev"),
SKILL_DELETE(ResourceTypeEnum.OPERATION, "skill_delete", "删除", "skill_dev"),
// ================== MCP管理模块 ==================
MCP_DEV(ResourceTypeEnum.MODULE, "mcp_dev", "MCP管理模块", "root"),
MCP_CREATE(ResourceTypeEnum.OPERATION, "mcp_create", "创建MCP服务", "mcp_dev"),
MCP_QUERY_LIST(ResourceTypeEnum.OPERATION, "mcp_query_list", "查询列表", "mcp_dev"),
MCP_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "mcp_query_detail", "查询详情", "mcp_dev"),
MCP_SAVE(ResourceTypeEnum.OPERATION, "mcp_save", "保存", "mcp_dev"),
MCP_EXPORT(ResourceTypeEnum.OPERATION, "mcp_export", "导出", "mcp_dev"),
// MCP_LOG(ResourceTypeEnum.OPERATION, "mcp_log", "日志", "mcp_dev"),
MCP_DELETE(ResourceTypeEnum.OPERATION, "mcp_delete", "删除", "mcp_dev"),
MCP_STOP(ResourceTypeEnum.OPERATION, "mcp_stop", "停止服务", "mcp_dev"),
// ================== IM渠道 ==================
IM_CONFIG(ResourceTypeEnum.MODULE, "im_config", "IM渠道配置模块", "root"),
IM_CONFIG_QUERY_LIST(ResourceTypeEnum.MODULE, "im_config_query_list", "查询配置列表", "im_config"),
IM_CONFIG_QUERY_DETAIL(ResourceTypeEnum.MODULE, "im_config_query_detail", "查询配置详情", "im_config"),
IM_CONFIG_ADD(ResourceTypeEnum.MODULE, "im_config_add", "添加配置", "im_config"),
IM_CONFIG_MODIFY(ResourceTypeEnum.MODULE, "im_config_modify", "编辑配置", "im_config"),
IM_CONFIG_DELETE(ResourceTypeEnum.MODULE, "im_config_delete", "删除配置", "im_config"),
// IM_CONFIG_ENABLE(ResourceTypeEnum.MODULE, "im_config_enable", "启用/禁用配置", "im_config"),
// ================== 任务中心模块 ==================
SPACE_TASK_DEV(ResourceTypeEnum.MODULE, "space_task_dev", "任务中心模块", "root"),
SPACE_TASK_CREATE(ResourceTypeEnum.OPERATION, "space_task_create", "创建任务", "space_task_dev"),
SPACE_TASK_QUERY_LIST(ResourceTypeEnum.OPERATION, "space_task_query_list", "查询列表", "space_task_dev"),
SPACE_TASK_EXECUTE_MANUAL(ResourceTypeEnum.OPERATION, "space_task_execute_manual", "手动执行", "space_task_dev"),
SPACE_TASK_CANCEL(ResourceTypeEnum.OPERATION, "space_task_cancel", "取消任务", "space_task_dev"),
SPACE_TASK_ENABLE(ResourceTypeEnum.OPERATION, "space_task_enable", "启用", "space_task_dev"),
// SPACE_TASK_EXECUTE_RECORD(ResourceTypeEnum.OPERATION, "space_task_execute_record", "执行记录", "space_task_dev"),
SPACE_TASK_MODIFY(ResourceTypeEnum.OPERATION, "space_task_modify", "编辑", "space_task_dev"),
SPACE_TASK_DELETE(ResourceTypeEnum.OPERATION, "space_task_delete", "删除", "space_task_dev"),
// ================== 空间日志查询模块 ==================
SPACE_LOG_QUERY(ResourceTypeEnum.MODULE, "space_log_query", "空间日志查询模块", "root"),
SPACE_LOG_QUERY_LIST(ResourceTypeEnum.OPERATION, "space_log_query_list", "查询列表", "space_log_query"),
SPACE_LOG_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "space_log_query_detail", "详情", "space_log_query"),
// ================== 广场模块 ==================
// SQUARE(ResourceTypeEnum.MODULE, "space_square", "空间广场模块", "root"),
//
// SQUARE_QUERY_LIST(ResourceTypeEnum.OPERATION, "square_query_list", "查询列表", "space_square"),
// SQUARE_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "square_query_detail", "查询详情", "space_square"),
// SQUARE_OFFLINE(ResourceTypeEnum.OPERATION, "square_offline", "下架", "space_square"),
// SQUARE_COLLECT(ResourceTypeEnum.OPERATION, "square_collect", "收藏", "space_square"),
// SQUARE_COPY_TEMPLATE(ResourceTypeEnum.OPERATION, "square_copy_template", "复制模板(智能体、插件、工作流)", "space_square"),
// SQUARE_EXPORT(ResourceTypeEnum.OPERATION, "square_export", "导出", "space_square"),
// ================== 用户管理模块 ==================
USER_MANAGE(ResourceTypeEnum.MODULE, "user_manage", "用户管理模块", "root"),
USER_MANAGE_QUERY(ResourceTypeEnum.OPERATION, "user_manage_query", "查询用户", "user_manage"),
USER_MANAGE_ADD(ResourceTypeEnum.OPERATION, "user_manage_add", "添加用户", "user_manage"),
USER_MANAGE_SEND_MESSAGE(ResourceTypeEnum.OPERATION, "user_manage_send_message", "消息发送", "user_manage"),
USER_MANAGE_ENABLE(ResourceTypeEnum.OPERATION, "user_manage_enable", "启用", "user_manage"),
USER_MANAGE_DISABLE(ResourceTypeEnum.OPERATION, "user_manage_disable", "禁用", "user_manage"),
USER_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "user_manage_modify", "修改", "user_manage"),
USER_MANAGE_BIND_ROLE(ResourceTypeEnum.OPERATION, "user_manage_bind_role", "绑定角色", "user_manage"),
USER_MANAGE_BIND_GROUP(ResourceTypeEnum.OPERATION, "user_manage_bind_group", "绑定用户组", "user_manage"),
USER_MANAGE_QUERY_MENU_PERMISSION(ResourceTypeEnum.OPERATION, "user_manage_query_menu_permission", "查看权限", "user_manage"),
USER_MANAGE_QUERY_DATA_PERMISSION(ResourceTypeEnum.OPERATION, "user_manage_query_data_permission", "数据权限", "user_manage"),
// ================== 发布审核模块 ==================
PUBLISH_AUDIT(ResourceTypeEnum.MODULE, "publish_audit", "发布审核模块", "root"),
PUBLISH_AUDIT_QUERY_LIST(ResourceTypeEnum.OPERATION, "publish_audit_query_list", "查询列表", "publish_audit"),
PUBLISH_AUDIT_PASS(ResourceTypeEnum.OPERATION, "publish_audit_pass", "通过", "publish_audit"),
PUBLISH_AUDIT_REJECT(ResourceTypeEnum.OPERATION, "publish_audit_reject", "拒绝", "publish_audit"),
PUBLISH_AUDIT_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "publish_audit_query_detail", "查看", "publish_audit"),
// ================== 已发布管理模块 ==================
PUBLISHED_MANAGE(ResourceTypeEnum.MODULE, "published_manage", "已发布管理模块", "root"),
PUBLISHED_MANAGE_QUERY_LIST(ResourceTypeEnum.OPERATION, "published_manage_query_list", "查询列表", "published_manage"),
PUBLISHED_MANAGE_OFFLINE(ResourceTypeEnum.OPERATION, "published_manage_offline", "下架", "published_manage"),
PUBLISHED_MANAGE_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "published_manage_query_detail", "查看", "published_manage"),
// ================== 模型管理模块 ==================
MODEL_MANAGE(ResourceTypeEnum.MODULE, "model_manage", "模型管理模块", "root"),
MODEL_MANAGE_QUERY_LIST(ResourceTypeEnum.OPERATION, "model_manage_query_list", "查询列表", "model_manage"),
MODEL_MANAGE_ADD(ResourceTypeEnum.OPERATION, "model_manage_add", "添加模型", "model_manage"),
MODEL_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "model_manage_modify", "编辑", "model_manage"),
MODEL_MANAGE_DELETE(ResourceTypeEnum.OPERATION, "model_manage_delete", "删除", "model_manage"),
MODEL_MANAGE_ACCESS_CONTROL(ResourceTypeEnum.OPERATION, "model_manage_access_control", "访问授权", "model_manage"),
// ================== 系统设置模块 ==================
SYSTEM_SETTING(ResourceTypeEnum.MODULE, "system_setting", "系统设置模块", "root"),
SYSTEM_SETTING_BASIC(ResourceTypeEnum.MODULE, "system_setting_basic", "基础配置", "system_setting"),
SYSTEM_SETTING_MODEL_DEFAULT(ResourceTypeEnum.MODULE, "system_setting_model_default", "默认模型配置", "system_setting"),
SYSTEM_SETTING_SITE_AGENT(ResourceTypeEnum.MODULE, "system_setting_site_agent", "站点智能体设置", "system_setting"),
SYSTEM_SETTING_SAVE(ResourceTypeEnum.OPERATION, "system_setting_save", "保存", "system_setting"),
// ================== 主题配置模块 ==================
SYSTEM_THEME_CONFIG(ResourceTypeEnum.MODULE, "system_theme_config", "主题配置模块", "root"),
SYSTEM_THEME_CONFIG_SAVE(ResourceTypeEnum.OPERATION, "system_theme_config_save", "保存配置", "system_theme_config"),
// ================== 沙盒配置模块 ==================
SANDBOX_CONFIG(ResourceTypeEnum.MODULE, "sandbox_config", "沙盒配置模块", "root"),
SANDBOX_CONFIG_QUERY(ResourceTypeEnum.OPERATION, "sandbox_config_query", "查询", "sandbox_config"),
SANDBOX_CONFIG_ADD(ResourceTypeEnum.OPERATION, "sandbox_config_add", "添加", "sandbox_config"),
SANDBOX_CONFIG_MODIFY(ResourceTypeEnum.OPERATION, "sandbox_config_modify", "编辑", "sandbox_config"),
SANDBOX_CONFIG_SAVE(ResourceTypeEnum.OPERATION, "sandbox_config_save", "保存", "sandbox_config"),
SANDBOX_CONFIG_DELETE(ResourceTypeEnum.OPERATION, "sandbox_config_delete", "删除", "sandbox_config"),
// SANDBOX_CONFIG_ENABLE(ResourceTypeEnum.OPERATION, "sandbox_config_enable", "启用/禁用", "sandbox_config"),
// ================== 分类管理模块 ==================
CATEGORY_CONFIG(ResourceTypeEnum.MODULE, "category_config", "分类管理模块", "root"),
CATEGORY_CONFIG_QUERY(ResourceTypeEnum.OPERATION, "category_config_query", "查询", "category_config"),
CATEGORY_CONFIG_ADD(ResourceTypeEnum.OPERATION, "category_config_add", "添加", "category_config"),
CATEGORY_CONFIG_MODIFY(ResourceTypeEnum.OPERATION, "category_config_modify", "编辑", "category_config"),
CATEGORY_CONFIG_DELETE(ResourceTypeEnum.OPERATION, "category_config_delete", "删除", "category_config"),
// ================== 系统概览模块 ==================
SYSTEM_DASHBOARD(ResourceTypeEnum.MODULE, "system_dashboard", "系统概览查询", "root"),
// ================== 系统任务管理模块 ==================
SYSTEM_TASK_MANAGE(ResourceTypeEnum.MODULE, "system_task_manage", "系统任务管理模块", "root"),
TASK_MANAGE_QUERY_LIST(ResourceTypeEnum.OPERATION, "task_manage_query_list", "查询列表", "system_task_manage"),
TASK_MANAGE_EXECUTE_MANUAL(ResourceTypeEnum.OPERATION, "task_manage_execute_manual", "手动执行", "system_task_manage"),
TASK_MANAGE_ENABLE(ResourceTypeEnum.OPERATION, "task_manage_enable", "启用", "system_task_manage"),
TASK_MANAGE_CANCEL(ResourceTypeEnum.OPERATION, "task_manage_cancel", "停用", "system_task_manage"),
TASK_MANAGE_EXECUTE_RECORD(ResourceTypeEnum.OPERATION, "task_manage_execute_record", "执行记录", "system_task_manage"),
TASK_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "task_manage_modify", "编辑", "system_task_manage"),
TASK_MANAGE_DELETE(ResourceTypeEnum.OPERATION, "task_manage_delete", "删除", "system_task_manage"),
// ================== 权限管理模块 ==================
// 1级模块
PERMISSION_MANAGE(ResourceTypeEnum.MODULE, "permission_manage", "权限管理模块", "root"),
// 2级模块 - 资源管理模块
RESOURCE_MANAGE(ResourceTypeEnum.MODULE, "resource_manage", "资源管理模块", "permission_manage"),
RESOURCE_MANAGE_QUERY(ResourceTypeEnum.OPERATION, "resource_manage_query", "查询", "resource_manage"),
RESOURCE_MANAGE_ADD(ResourceTypeEnum.OPERATION, "resource_manage_add", "新增", "resource_manage"),
RESOURCE_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "resource_manage_modify", "编辑", "resource_manage"),
RESOURCE_MANAGE_DELETE(ResourceTypeEnum.OPERATION, "resource_manage_delete", "删除", "resource_manage"),
// 2级模块 - 菜单管理模块
MENU_MANAGE(ResourceTypeEnum.MODULE, "menu_manage", "菜单管理模块", "permission_manage"),
MENU_MANAGE_QUERY(ResourceTypeEnum.OPERATION, "menu_manage_query", "查询", "menu_manage"),
MENU_MANAGE_ADD(ResourceTypeEnum.OPERATION, "menu_manage_add", "新增", "menu_manage"),
MENU_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "menu_manage_modify", "编辑", "menu_manage"),
MENU_MANAGE_DELETE(ResourceTypeEnum.OPERATION, "menu_manage_delete", "删除", "menu_manage"),
// 2级模块 - 角色管理模块
ROLE_MANAGE(ResourceTypeEnum.MODULE, "role_manage", "角色管理模块", "permission_manage"),
ROLE_MANAGE_QUERY(ResourceTypeEnum.OPERATION, "role_manage_query", "查询", "role_manage"),
ROLE_MANAGE_ADD(ResourceTypeEnum.OPERATION, "role_manage_add", "新增", "role_manage"),
ROLE_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "role_manage_modify", "编辑", "role_manage"),
ROLE_MANAGE_DELETE(ResourceTypeEnum.OPERATION, "role_manage_delete", "删除", "role_manage"),
ROLE_MANAGE_BIND_MENU(ResourceTypeEnum.OPERATION, "role_manage_bind_menu", "菜单权限", "role_manage"),
ROLE_MANAGE_BIND_USER(ResourceTypeEnum.OPERATION, "role_manage_bind_user", "绑定用户", "role_manage"),
ROLE_MANAGE_BIND_DATA(ResourceTypeEnum.OPERATION, "role_manage_bind_data", "数据权限", "role_manage"),
// 2级模块 - 用户组管理模块
USER_GROUP_MANAGE(ResourceTypeEnum.MODULE, "user_group_manage", "用户组管理模块", "permission_manage"),
USER_GROUP_MANAGE_QUERY(ResourceTypeEnum.OPERATION, "user_group_manage_query", "查询", "user_group_manage"),
USER_GROUP_MANAGE_ADD(ResourceTypeEnum.OPERATION, "user_group_manage_add", "新增", "user_group_manage"),
USER_GROUP_MANAGE_MODIFY(ResourceTypeEnum.OPERATION, "user_group_manage_modify", "编辑", "user_group_manage"),
USER_GROUP_MANAGE_DELETE(ResourceTypeEnum.OPERATION, "user_group_manage_delete", "删除", "user_group_manage"),
USER_GROUP_MANAGE_BIND_MENU(ResourceTypeEnum.OPERATION, "user_group_manage_bind_menu", "菜单权限", "user_group_manage"),
USER_GROUP_MANAGE_BIND_USER(ResourceTypeEnum.OPERATION, "user_group_manage_bind_user", "绑定用户", "user_group_manage"),
USER_GROUP_MANAGE_BIND_DATA(ResourceTypeEnum.OPERATION, "user_group_manage_bind_data", "数据权限", "user_group_manage"),
// ================== 系统运行日志模块 ==================
// 1级模块
SYSTEM_LOG(ResourceTypeEnum.MODULE, "system_log", "系统日志模块", "root"),
// 2级模块 - 系统运行日志
SYSTEM_RUNNING_LOG(ResourceTypeEnum.MODULE, "system_running_log", "系统运行日志模块", "system_log"),
SYSTEM_RUNNING_LOG_QUERY_LIST(ResourceTypeEnum.OPERATION, "system_running_log_query_list", "查询列表", "system_running_log"),
SYSTEM_RUNNING_LOG_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "system_running_log_query_detail", "查询详情", "system_running_log"),
// ================== 内容管理模块 ==================
// 1级模块
CONTENT_MANAGE(ResourceTypeEnum.MODULE, "content_manage", "内容管理模块", "root"),
// 2级模块 - 空间管理
CONTENT_SPACE(ResourceTypeEnum.MODULE, "content_space", "空间管理", "content_manage"),
CONTENT_SPACE_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_space_query_list", "查询列表", "content_space"),
CONTENT_SPACE_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_space_query_detail", "查询详情", "content_space"),
CONTENT_SPACE_DELETE(ResourceTypeEnum.OPERATION, "content_space_delete", "删除", "content_space"),
// 2级模块 - 智能体管理
CONTENT_AGENT(ResourceTypeEnum.MODULE, "content_agent", "智能体管理", "content_manage"),
CONTENT_AGENT_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_agent_query_list", "查询列表", "content_agent"),
CONTENT_AGENT_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_agent_query_detail", "查询详情", "content_agent"),
CONTENT_AGENT_DELETE(ResourceTypeEnum.OPERATION, "content_agent_delete", "删除", "content_agent"),
CONTENT_AGENT_ACCESS_CONTROL(ResourceTypeEnum.OPERATION, "content_agent_access_control", "访问授权", "content_agent"),
// 2级模块 - 网页应用管理
CONTENT_PAGE_APP(ResourceTypeEnum.MODULE, "content_page_app", "网页应用管理", "content_manage"),
CONTENT_PAGE_APP_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_page_app_query_list", "查询列表", "content_page_app"),
CONTENT_PAGE_APP_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_page_app_query_detail", "查询详情", "content_page_app"),
CONTENT_PAGE_APP_DELETE(ResourceTypeEnum.OPERATION, "content_page_app_delete", "删除", "content_page_app"),
CONTENT_PAGE_APP_ACCESS_CONTROL(ResourceTypeEnum.OPERATION, "content_page_app_access_control", "访问授权", "content_page_app"),
// 2级模块 - 知识库管理
CONTENT_KNOWLEDGE(ResourceTypeEnum.MODULE, "content_knowledge", "知识库管理", "content_manage"),
CONTENT_KNOWLEDGE_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_knowledge_query_list", "查询列表", "content_knowledge"),
CONTENT_KNOWLEDGE_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_knowledge_query_detail", "查询详情", "content_knowledge"),
CONTENT_KNOWLEDGE_DELETE(ResourceTypeEnum.OPERATION, "content_knowledge_delete", "删除", "content_knowledge"),
CONTENT_KNOWLEDGE_ACCESS_CONTROL(ResourceTypeEnum.OPERATION, "content_knowledge_access_control", "访问授权", "content_knowledge"),
// 2级模块 - 数据表管理
CONTENT_DATATABLE(ResourceTypeEnum.MODULE, "content_datatable", "数据表管理", "content_manage"),
CONTENT_DATATABLE_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_datatable_query_list", "查询列表", "content_datatable"),
CONTENT_DATATABLE_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_datatable_query_detail", "查询详情", "content_datatable"),
CONTENT_DATATABLE_DELETE(ResourceTypeEnum.OPERATION, "content_datatable_delete", "删除", "content_datatable"),
// 2级模块 - 工作流管理
CONTENT_WORKFLOW(ResourceTypeEnum.MODULE, "content_workflow", "工作流管理", "content_manage"),
CONTENT_WORKFLOW_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_workflow_query_list", "查询列表", "content_workflow"),
CONTENT_WORKFLOW_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_workflow_query_detail", "查询详情", "content_workflow"),
CONTENT_WORKFLOW_DELETE(ResourceTypeEnum.OPERATION, "content_workflow_delete", "删除", "content_workflow"),
// 2级模块 - 插件管理
CONTENT_PLUGIN(ResourceTypeEnum.MODULE, "content_plugin", "插件管理", "content_manage"),
CONTENT_PLUGIN_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_plugin_query_list", "查询列表", "content_plugin"),
CONTENT_PLUGIN_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_plugin_query_detail", "查询详情", "content_plugin"),
CONTENT_PLUGIN_DELETE(ResourceTypeEnum.OPERATION, "content_plugin_delete", "删除", "content_plugin"),
// 2级模块 - MCP管理
CONTENT_MCP(ResourceTypeEnum.MODULE, "content_mcp", "MCP管理", "content_manage"),
CONTENT_MCP_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_mcp_query_list", "查询列表", "content_mcp"),
CONTENT_MCP_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_mcp_query_detail", "查询详情", "content_mcp"),
CONTENT_MCP_DELETE(ResourceTypeEnum.OPERATION, "content_mcp_delete", "删除", "content_mcp"),
// 2级模块 - 技能管理
CONTENT_SKILL(ResourceTypeEnum.MODULE, "content_skill", "技能管理", "content_manage"),
CONTENT_SKILL_QUERY_LIST(ResourceTypeEnum.OPERATION, "content_skill_query_list", "查询列表", "content_skill"),
CONTENT_SKILL_QUERY_DETAIL(ResourceTypeEnum.OPERATION, "content_skill_query_detail", "查询详情", "content_skill"),
CONTENT_SKILL_DELETE(ResourceTypeEnum.OPERATION, "content_skill_delete", "删除", "content_skill"),
// ================== 多语言管理模块 ==================
I18N_LANG_MANAGE(ResourceTypeEnum.MODULE, "i18n_lang_manage", "多语言管理模块", "root"),
I18N_LANG_QUERY(ResourceTypeEnum.OPERATION, "i18n_lang_query", "查询", "i18n_lang_manage"),
I18N_LANG_ADD(ResourceTypeEnum.OPERATION, "i18n_lang_add", "新增", "i18n_lang_manage"),
I18N_LANG_MODIFY(ResourceTypeEnum.OPERATION, "i18n_lang_modify", "编辑", "i18n_lang_manage"),
I18N_LANG_DELETE(ResourceTypeEnum.OPERATION, "i18n_lang_delete", "删除", "i18n_lang_manage"),
I18N_LANG_TRANSLATE(ResourceTypeEnum.OPERATION, "i18n_lang_translate", "翻译", "i18n_lang_manage"),
// ================== 订阅与积分模块 ==================
SUBSCRIPTION_POINTS(ResourceTypeEnum.MODULE, "subscription_points", "订阅与积分模块", "root"),
SUBSCRIPTION_POINTS_QUERY(ResourceTypeEnum.OPERATION, "subscription_points_query", "查询", "subscription_points"),
SUBSCRIPTION_POINTS_MODIFY(ResourceTypeEnum.OPERATION, "subscription_points_modify", "编辑", "subscription_points"),
SUBSCRIPTION_POINTS_DELETE(ResourceTypeEnum.OPERATION, "subscription_points_delete", "删除", "subscription_points"),
// ================== 支付与收益模块 ==================
PAY_EARNINGS(ResourceTypeEnum.MODULE, "pay_earnings", "支付与收益模块", "root"),
PAY_EARNINGS_QUERY(ResourceTypeEnum.OPERATION, "pay_earnings_query", "查询", "pay_earnings"),
PAY_EARNINGS_MODIFY(ResourceTypeEnum.OPERATION, "pay_earnings_modify", "编辑", "pay_earnings"),
MERCHANT_ONBOARDING_AUDIT(ResourceTypeEnum.OPERATION, "merchant_onboarding_audit", "进件审核", "pay_earnings"),
WITHDRAW_AUDIT(ResourceTypeEnum.OPERATION, "withdraw_audit", "提现审核", "pay_earnings");
private final ResourceTypeEnum type;
private final String code;
private final String name;
private final String parentCode;
ResourceEnum(ResourceTypeEnum type, String code, String name, String parentCode) {
this.type = type;
this.code = code;
this.name = name;
this.parentCode = parentCode;
}
/**
* 根据code获取枚举
*/
public static ResourceEnum getByCode(String code) {
if (code == null) {
return null;
}
for (ResourceEnum resourceEnum : values()) {
if (resourceEnum.getCode().equals(code)) {
return resourceEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,42 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 资源类型枚举
*/
@Getter
public enum ResourceTypeEnum {
MODULE(1, "模块"),
OPERATION(2, "组件");
private final Integer code;
private final String desc;
ResourceTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static ResourceTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (ResourceTypeEnum typeEnum : values()) {
if (typeEnum.getCode().equals(code)) {
return typeEnum;
}
}
return null;
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,21 @@
package com.xspaceagi.system.spec.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 重试进度
*/
@Getter
@AllArgsConstructor
public enum RetryProgress {
INIT(1, "初次上报"),
OVERFLOW(2, "重试超过最大次数"),
SUCCESS(3, "成功"),
;
private Integer value;
private String desc;
}

View File

@@ -0,0 +1,29 @@
package com.xspaceagi.system.spec.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 状态1待重试2重试成功3重试失败4禁止重试
*/
@Getter
@AllArgsConstructor
public enum RetryStatusEnum implements IEnum<Integer> {
WAIT(1, "待重试"),
SUCCESS(2, "重试成功"),
FAIL(3, "重试失败"),
BAN(4, "禁止重试"),
;
private final Integer value;
private final String desc;
public static boolean canRetry(RetryStatusEnum status) {
return WAIT.equals(status);
}
}

View File

@@ -0,0 +1,22 @@
package com.xspaceagi.system.spec.enums;
import com.baomidou.mybatisplus.annotation.IEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 重试类型1 异常数据需要重试 2 正常数据不需要重试
*/
@Getter
@AllArgsConstructor
public enum RetryTypeEnum implements IEnum<Integer> {
Y(1, "异常数据需要重试"),
N(2, "正常数据不需要重试"),
;
private final Integer value;
private final String desc;
}

View File

@@ -0,0 +1,33 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 系统内置角色
*/
@Getter
public enum RoleEnum {
SUPER_ADMIN("super_admin", "超级管理员");
private final String code;
private final String name;
RoleEnum(String code, String name) {
this.code = code;
this.name = name;
}
public static RoleEnum getByCode(String code) {
if (code == null) {
return null;
}
for (RoleEnum resourceEnum : values()) {
if (resourceEnum.getCode().equals(code)) {
return resourceEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,41 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 来源枚举
*/
@Getter
public enum SourceEnum {
SYSTEM(1, "系统内置"),
CUSTOM(2, "用户自定义");
private final Integer code;
private final String desc;
SourceEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static SourceEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (SourceEnum typeEnum : values()) {
if (typeEnum.getCode().equals(code)) {
return typeEnum;
}
}
return null;
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,46 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 状态枚举
*/
@Getter
public enum StatusEnum {
DISABLED(0, "禁用"),
ENABLED(1, "启用");
private final Integer code;
private final String desc;
StatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public static StatusEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (StatusEnum statusEnum : values()) {
if (statusEnum.getCode().equals(code)) {
return statusEnum;
}
}
return null;
}
public static boolean isEnabled(Integer code) {
return ENABLED.getCode().equals(code);
}
public static boolean isValid(Integer code) {
return getByCode(code) != null;
}
public static boolean isInValid(Integer code) {
return !isValid(code);
}
}

View File

@@ -0,0 +1,54 @@
//package com.xspaceagi.system.spec.enums;
//
//import lombok.Getter;
//
///**
// * 系统内置用户组
// */
//@Getter
//public enum SysBuiltinGroupEnum {
//
// DEFAULT_GROUP("default_group", "默认用户组", "系统默认用户组", 1);
//
// /**
// * 用户组编码
// */
// private final String code;
//
// /**
// * 用户组名称
// */
// private final String name;
//
// /**
// * 用户组描述
// */
// private final String description;
//
// /**
// * 排序索引
// */
// private final Integer sortIndex;
//
// SysBuiltinGroupEnum(String code, String name, String description, Integer sortIndex) {
// this.code = code;
// this.name = name;
// this.description = description;
// this.sortIndex = sortIndex;
// }
//
// /**
// * 根据code获取枚举
// */
// public static SysBuiltinGroupEnum getByCode(String code) {
// if (code == null) {
// return null;
// }
// for (SysBuiltinGroupEnum groupEnum : values()) {
// if (groupEnum.getCode().equals(code)) {
// return groupEnum;
// }
// }
// return null;
// }
//}

View File

@@ -0,0 +1,52 @@
//package com.xspaceagi.system.spec.enums;
//
//import lombok.Getter;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * 系统内置用户组-菜单关联
// */
//@Getter
//public enum SysBuiltinGroupMenuEnum {
//
// GROUP_MENU_EXAMPLE("default_group", "root", BindTypeEnum.ALL);
//
// //PLACEHOLDER("__PLACEHOLDER__", "__PLACEHOLDER__", BindTypeEnum.NONE, BindTypeEnum.NONE);
//
// /**
// * 用户组编码
// */
// private final String groupCode;
//
// /**
// * 菜单编码
// */
// private final String menuCode;
//
// /**
// * 子菜单绑定类型
// */
// private final BindTypeEnum menuBindType;
//
// SysBuiltinGroupMenuEnum(String groupCode, String menuCode, BindTypeEnum menuBindType) {
// this.groupCode = groupCode;
// this.menuCode = menuCode;
// this.menuBindType = menuBindType;
// }
//
// /**
// * 根据用户组编码获取关联的菜单列表
// */
// public static List<SysBuiltinGroupMenuEnum> getByGroupCode(String groupCode) {
// if (groupCode == null) {
// return List.of();
// }
// return Arrays.stream(values())
// .filter(enumItem -> enumItem.getGroupCode().equals(groupCode))
// .filter(enumItem -> !"__PLACEHOLDER__".equals(enumItem.getGroupCode()))
// .collect(Collectors.toList());
// }
//}

View File

@@ -0,0 +1,121 @@
//package com.xspaceagi.system.spec.enums;
//
//import lombok.Getter;
//
///**
// * 系统内置菜单枚举
// */
//@Getter
//public enum SysBuiltinMenuEnum {
//
// ROOT("root", "根菜单", "根菜单", null, null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 系统管理
// SYS_MANAGE("sys_manage", "系统管理", "系统管理", "root", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 用户管理
// SYS_USER_MANAGE("sys_user_manage", "用户管理", "用户管理", "sys_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 发布管理
// SYS_PUBLISH_MANAGE("sys_publish_manage", "发布管理", "发布管理", "sys_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// SYS_PUBLISH_APPROVE("sys_publish_approve", "发布审核", "发布审核", "sys_publish_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// SYS_PUBLISHED("sys_published", "已发布管理", "已发布管理", "sys_publish_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 模型管理
// SYS_MODEL_MANAGE("sys_model_manage", "模型管理", "模型管理", "sys_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 系统配置
//
// // 主题配置
//
// // 系统概览
//
// // 菜单权限
// SYS_MENU_MANAGE("sys_menu_manage", "菜单权限", "菜单权限", "sys_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// SYS_RESOURCE("sys_resource", "权限资源", "权限资源", "sys_manage", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 日志查询
//
// // 内容管理
//
// // 首页
// HOMEPAGE("homepage", "首页", "首页", "root", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// // 工作空间
// WORKSPACE("workspace", "工作空间", "工作空间", "root", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// AGENT_DEV("agent_dev", "智能体开发", "智能体开发", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// PAGE_APP_DEV("page_app_dev", "网页应用开发", "网页应用开发", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// COMPONENT_DEV("component_dev", "组件库", "组件库", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// SKILL_DEV("skill_dev", "技能管理", "技能管理", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// MCP_DEV("mcp_dev", "MCP管理", "MCP管理", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// TASK_MANAGE("task_manage", "任务中心", "任务中心", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// LOG_MANAGE("log_manage", "日志查询", "日志查询", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
// SPACE_SQUARE("space_square", "空间广场", "空间广场", "workspace", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// SQUARE("square", "广场", "广场", "root", null, "https://avatars.githubusercontent.com/u/41285659", 0),
//
// ECO_MARKET("eco_market", "生态市场", "生态市场", "root", null, "https://avatars.githubusercontent.com/u/41285659", 0);
//
// //PLACEHOLDER("__PLACEHOLDER__", "__占位符__", "__占位符__", null, "", "", 0);
//
// /**
// * 菜单编码
// */
// private final String code;
//
// /**
// * 菜单名称
// */
// private final String name;
//
// /**
// * 菜单描述
// */
// private final String description;
//
// /**
// * 父级菜单编码(如果为 null 或空字符串,则表示根菜单)
// */
// private final String parentCode;
//
// /**
// * 访问路径/路由地址
// */
// private final String path;
//
// /**
// * 图标
// */
// private final String icon;
//
// /**
// * 排序索引
// */
// private final Integer sortIndex;
//
// SysBuiltinMenuEnum(String code, String name, String description, String parentCode, String path, String icon, Integer sortIndex) {
// this.code = code;
// this.name = name;
// this.description = description;
// this.parentCode = parentCode;
// this.path = path;
// this.icon = icon;
// this.sortIndex = sortIndex;
// }
//
// /**
// * 根据code获取枚举
// */
// public static SysBuiltinMenuEnum getByCode(String code) {
// if (code == null) {
// return null;
// }
// for (SysBuiltinMenuEnum menuEnum : values()) {
// if (menuEnum.getCode().equals(code)) {
// return menuEnum;
// }
// }
// return null;
// }
//}

View File

@@ -0,0 +1,143 @@
//package com.xspaceagi.system.spec.enums;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.stream.Collectors;
//
//import lombok.Getter;
//
///**
// * 系统内置菜单-资源关联
// */
//@Getter
//public enum SysBuiltinMenuResourceEnum {
//
// ROOT(SysBuiltinMenuEnum.ROOT.getCode(), SysBuiltinResourceEnum.ROOT.getCode(), BindTypeEnum.ALL),
//
// // 系统管理
// //SYS_MANAGE_RESOURCE("sys_manage", "sys_manage", BindTypeEnum.ALL),
//
// // 用户管理
// SYS_USER_MANAGE_RESOURCE(SysBuiltinMenuEnum.SYS_USER_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_USER_MANAGE.getCode(), BindTypeEnum.ALL),
//// SYS_USER_MANAGE_QUERY(SysBuiltinMenuEnum.SYS_USER_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_USER_QUERY.getCode(), BindTypeEnum.ALL),
//// SYS_USER_MANAGE_ADD(SysBuiltinMenuEnum.SYS_USER_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_USER_ADD.getCode(), BindTypeEnum.ALL),
//// SYS_USER_MANAGE_EDIT(SysBuiltinMenuEnum.SYS_USER_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_USER_EDIT.getCode(), BindTypeEnum.ALL),
//// SYS_USER_MANAGE_DELETE(SysBuiltinMenuEnum.SYS_USER_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_USER_DELETE.getCode(), BindTypeEnum.ALL),
//// SYS_USER_MANAGE_ENABLE(SysBuiltinMenuEnum.SYS_USER_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_USER_ENABLE.getCode(), BindTypeEnum.ALL),
//
// // 发布管理
// SYS_PUBLISH_MANAGE(SysBuiltinMenuEnum.SYS_PUBLISH_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_PUBLISH_MANAGE.getCode(), BindTypeEnum.ALL),
//
// // 发布审核
//// SYS_PUBLISH_APPROVE_RESOURCE(SysBuiltinMenuEnum.SYS_PUBLISH_APPROVE.getCode(), SysBuiltinResourceEnum.SYS_PUBLISH_APPROVE.getCode(), BindTypeEnum.ALL),
//// SYS_PUBLISH_APPROVE_QUERY(SysBuiltinMenuEnum.SYS_PUBLISH_APPROVE.getCode(), SysBuiltinResourceEnum.SYS_PUBLISH_APPROVE_QUERY.getCode(), BindTypeEnum.ALL),
//// SYS_PUBLISH_APPROVE_SUBMIT(SysBuiltinMenuEnum.SYS_PUBLISH_APPROVE.getCode(), SysBuiltinResourceEnum.SYS_PUBLISH_APPROVE_SUBMIT.getCode(), BindTypeEnum.ALL),
//
// // 已发布管理
//// SYS_PUBLISHED_RESOURCE(SysBuiltinMenuEnum.SYS_PUBLISHED.getCode(), SysBuiltinResourceEnum.SYS_PUBLISHED.getCode(), BindTypeEnum.ALL),
//
// // 模型管理
// SYS_MODEL_MANAGE_RESOURCE(SysBuiltinMenuEnum.SYS_MODEL_MANAGE.getCode(), SysBuiltinResourceEnum.SYS_MODEL_MANAGE.getCode(), BindTypeEnum.ALL),
//
// // 首页
// HOMEPAGE_RESOURCE(SysBuiltinMenuEnum.HOMEPAGE.getCode(), SysBuiltinResourceEnum.HOMEPAGE.getCode(), BindTypeEnum.ALL),
//
// // 工作空间
// WORKSPACE_RESOURCE(SysBuiltinMenuEnum.WORKSPACE.getCode(), SysBuiltinResourceEnum.WORKSPACE.getCode(), BindTypeEnum.ALL),
//
// // 智能体开发
// AGENT_DEV_RESOURCE(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_DEV.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_ADD(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_ADD.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_EDIT(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_EDIT.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_DELETE(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_DELETE.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_IMPORT(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_IMPORT.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_EXPORT(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_EXPORT.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_PUBLISH(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_PUBLISH.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_COPY(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_COPY.getCode(), BindTypeEnum.ALL),
//// AGENT_DEV_MIGRATE(SysBuiltinMenuEnum.AGENT_DEV.getCode(), SysBuiltinResourceEnum.AGENT_MIGRATE.getCode(), BindTypeEnum.ALL),
//
// // 网页应用开发
// PAGE_APP_DEV_RESOURCE(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_DEV.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_ADD(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_ADD.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_EDIT(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_EDIT.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_DELETE(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_DELETE.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_IMPORT(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_IMPORT.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_EXPORT(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_EXPORT.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_PUBLISH(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_PUBLISH.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_COPY(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_COPY.getCode(), BindTypeEnum.ALL),
//// PAGE_APP_DEV_CONFIG(SysBuiltinMenuEnum.PAGE_APP_DEV.getCode(), SysBuiltinResourceEnum.PAGE_APP_CONFIG.getCode(), BindTypeEnum.ALL),
//
// // 组件库
// COMPONENT_DEV_RESOURCE(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_DEV.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_ADD(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_ADD.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_EDIT(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_EDIT.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_DELETE(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_DELETE.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_IMPORT(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_IMPORT.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_EXPORT(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_EXPORT.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_PUBLISH(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_PUBLISH.getCode(), BindTypeEnum.ALL),
//// COMPONENT_DEV_COPY(SysBuiltinMenuEnum.COMPONENT_DEV.getCode(), SysBuiltinResourceEnum.COMPONENT_COPY.getCode(), BindTypeEnum.ALL),
//
// // 技能管理
// SKILL_DEV_RESOURCE(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_DEV.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_ADD(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_ADD.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_EDIT(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_EDIT.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_DELETE(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_DELETE.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_IMPORT(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_IMPORT.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_EXPORT(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_EXPORT.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_PUBLISH(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_PUBLISH.getCode(), BindTypeEnum.ALL),
//// SKILL_DEV_COPY(SysBuiltinMenuEnum.SKILL_DEV.getCode(), SysBuiltinResourceEnum.SKILL_COPY.getCode(), BindTypeEnum.ALL),
//
// // MCP管理
// MCP_DEV_RESOURCE(SysBuiltinMenuEnum.MCP_DEV.getCode(), SysBuiltinResourceEnum.MCP_DEV.getCode(), BindTypeEnum.ALL),
//
// // 任务中心
// TASK_MANAGE_RESOURCE(SysBuiltinMenuEnum.TASK_MANAGE.getCode(), SysBuiltinResourceEnum.TASK_MANAGE.getCode(), BindTypeEnum.ALL),
//
// // 日志查询
// LOG_MANAGE_RESOURCE(SysBuiltinMenuEnum.LOG_MANAGE.getCode(), SysBuiltinResourceEnum.LOG_MANAGE.getCode(), BindTypeEnum.ALL),
//
// // 空间广场
// SPACE_SQUARE_RESOURCE(SysBuiltinMenuEnum.SPACE_SQUARE.getCode(), SysBuiltinResourceEnum.SPACE_SQUARE.getCode(), BindTypeEnum.ALL),
//
// // 广场
// SQUARE_RESOURCE(SysBuiltinMenuEnum.SQUARE.getCode(), SysBuiltinResourceEnum.SQUARE.getCode(), BindTypeEnum.ALL),
//
// // 生态市场
// ECO_MARKET_RESOURCE(SysBuiltinMenuEnum.ECO_MARKET.getCode(), SysBuiltinResourceEnum.ECO_MARKET.getCode(), BindTypeEnum.ALL);
//
// //PLACEHOLDER("__PLACEHOLDER__", "__PLACEHOLDER__", BindTypeEnum.NONE);
//
// /**
// * 菜单编码
// */
// private final String menuCode;
//
// /**
// * 资源编码
// */
// private final String resourceCode;
//
// /**
// * 资源绑定类型
// */
// private final BindTypeEnum resourceBindType;
//
// SysBuiltinMenuResourceEnum(String menuCode, String resourceCode, BindTypeEnum resourceBindType) {
// this.menuCode = menuCode;
// this.resourceCode = resourceCode;
// this.resourceBindType = resourceBindType;
// }
//
// /**
// * 根据菜单编码获取关联的资源列表
// */
// public static List<SysBuiltinMenuResourceEnum> getByMenuCode(String menuCode) {
// if (menuCode == null) {
// return List.of();
// }
// return Arrays.stream(values())
// .filter(enumItem -> enumItem.getMenuCode().equals(menuCode))
// .filter(enumItem -> !"__PLACEHOLDER__".equals(enumItem.getMenuCode()))
// .collect(Collectors.toList());
// }
//}

View File

@@ -0,0 +1,55 @@
//package com.xspaceagi.system.spec.enums;
//
//import lombok.Getter;
//
///**
// * 系统内置角色
// */
//@Getter
//public enum SysBuiltinRoleEnum {
//
// SUPER_ADMIN("super_admin", "超级管理员", "系统超级管理员,拥有所有权限", 1),
// NORMAL_USER("normal_user", "普通用户", "系统普通用户", 2);
//
// /**
// * 角色编码
// */
// private final String code;
//
// /**
// * 角色名称
// */
// private final String name;
//
// /**
// * 角色描述
// */
// private final String description;
//
// /**
// * 排序索引
// */
// private final Integer sortIndex;
//
// SysBuiltinRoleEnum(String code, String name, String description, Integer sortIndex) {
// this.code = code;
// this.name = name;
// this.description = description;
// this.sortIndex = sortIndex;
// }
//
// /**
// * 根据code获取枚举
// */
// public static SysBuiltinRoleEnum getByCode(String code) {
// if (code == null) {
// return null;
// }
// for (SysBuiltinRoleEnum roleEnum : values()) {
// if (roleEnum.getCode().equals(code)) {
// return roleEnum;
// }
// }
// return null;
// }
//}

View File

@@ -0,0 +1,53 @@
//package com.xspaceagi.system.spec.enums;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.stream.Collectors;
//
//import lombok.Getter;
//
///**
// * 系统内置角色-菜单关联
// */
//@Getter
//public enum SysBuiltinRoleMenuEnum {
//
// SUPER_ADMIN("super_admin", "root", BindTypeEnum.ALL),
// NORMAL_USER("normal_user", "root", BindTypeEnum.ALL);
//
// //PLACEHOLDER("__PLACEHOLDER__", "__PLACEHOLDER__", BindTypeEnum.NONE, BindTypeEnum.NONE);
//
// /**
// * 角色编码
// */
// private final String roleCode;
//
// /**
// * 菜单编码
// */
// private final String menuCode;
//
// /**
// * 子菜单绑定类型
// */
// private final BindTypeEnum menuBindType;
//
// SysBuiltinRoleMenuEnum(String roleCode, String menuCode, BindTypeEnum menuBindType) {
// this.roleCode = roleCode;
// this.menuCode = menuCode;
// this.menuBindType = menuBindType;
// }
//
// /**
// * 根据角色编码获取关联的菜单列表
// */
// public static List<SysBuiltinRoleMenuEnum> getByRoleCode(String roleCode) {
// if (roleCode == null) {
// return List.of();
// }
// return Arrays.stream(values())
// .filter(enumItem -> enumItem.getRoleCode().equals(roleCode))
// .filter(enumItem -> !"__PLACEHOLDER__".equals(enumItem.getRoleCode()))
// .collect(Collectors.toList());
// }
//}

View File

@@ -0,0 +1,5 @@
package com.xspaceagi.system.spec.enums;
public enum TenantStatus {
Pending, Enabled, Disabled // 确保枚举值与数据库中的ENUM值匹配
}

View File

@@ -0,0 +1,42 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
import java.util.Objects;
/**
* 角色类型1:管理员角色;2:普通角色
*/
@Getter
public enum UserRoleTypeEnum {
Manager(1, "管理员角色"),
Normal(2, "普通角色");
private final int key;
private final String value;
UserRoleTypeEnum(int key, String value) {
this.key = key;
this.value = value;
}
public static UserRoleTypeEnum getUserRoleTypeEnum(Integer key) {
if (Objects.isNull(key)) {
return null;
}
for (UserRoleTypeEnum userRoleTypeEnum : UserRoleTypeEnum.values()) {
if (userRoleTypeEnum.getKey() == key) {
return userRoleTypeEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,5 @@
package com.xspaceagi.system.spec.enums;
public enum UserStatus {
Enabled, Disabled // 确保枚举值与数据库中的ENUM值匹配
}

View File

@@ -0,0 +1,5 @@
package com.xspaceagi.system.spec.enums;
public enum UserTypeEnum {
Admin, User
}

View File

@@ -0,0 +1,29 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
public enum YesOrNoEnum {
N(0, "无效"),
Y(1, "有效");
@Getter
private final Integer key;
private final String value;
YesOrNoEnum(Integer key, String value) {
this.key = key;
this.value = value;
}
public static boolean isValid(Integer key) {
for (YesOrNoEnum value : YesOrNoEnum.values()) {
if (value.getKey().equals(key)) {
return true;
}
}
return false;
}
public static boolean isInValid(Integer key) {
return !isValid(key);
}
}

View File

@@ -0,0 +1,25 @@
package com.xspaceagi.system.spec.enums;
import lombok.Getter;
/**
* 逻辑删除标记
*/
@Getter
public enum YnEnum {
N(-1, "无效"), Y(1, "有效");
private final Integer key;
private final String value;
YnEnum(Integer key, String value) {
this.key = key;
this.value = value;
}
public static boolean isY(Integer key) {
return Y.getKey().equals(key);
}
}

View File

@@ -0,0 +1,35 @@
package com.xspaceagi.system.spec.event;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 消息拉取事件
* 用于EventBus事件传递
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PullMessageEvent implements Serializable{
/**
* 用户ID
*/
private Long userId;
/**
* 租户ID
*/
private Long tenantId;
/**
* 客户端ID
*/
private String clientId;
}

View File

@@ -0,0 +1,35 @@
package com.xspaceagi.system.spec.exception;
/**
* AI Agent 异常
*/
public class AgentException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "Agent";
public AgentException(String code, String message) {
super(code, message);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static AgentException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new AgentException(codeEnum.getCode(), errorMessage);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,23 @@
package com.xspaceagi.system.spec.exception;
/**
* agent执行中断
*/
public class AgentInterruptException extends RuntimeException {
public AgentInterruptException(String message) {
super(message);
}
public AgentInterruptException(String message, Throwable cause) {
super(message, cause);
}
public AgentInterruptException(Throwable cause) {
super(cause);
}
public AgentInterruptException() {
super();
}
}

View File

@@ -0,0 +1,129 @@
package com.xspaceagi.system.spec.exception;
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
import com.xspaceagi.system.spec.enums.HttpStatusEnum;
/**
* 业务异常
*/
public class BizException extends RuntimeException {
private static final long serialVersionUID = 1L;
private int status;
private String code = "0001";
private String msg;
/**
* {@link BizExceptionCodeEnum} 常量名({@link Enum#name()},小驼峰),用于响应阶段按语言重算文案。
* 对外 JSON 的 {@link #getCode()} 可能为 4000/4030 等,与本字段独立。
*/
private String msgName;
/**
* 与 {@link IBizExceptionCodeEnum#formatMessage(Object...)} 一致的占位参数,供全局异常处理按 {@code RequestContext.lang} 重算中英文。
*/
private Object[] messageFormatArgs;
public BizException(String msg) {
super(msg);
this.msg = msg;
}
public BizException(String code, String msg) {
this(code, msg, null);
}
public BizException(String code, String msg, String msgName) {
this(code, msg, msgName, null);
}
public BizException(String code, String msg, String msgName, Object[] messageFormatArgs) {
super(msg);
this.code = code;
this.msg = msg;
this.msgName = msgName;
this.messageFormatArgs = messageFormatArgs == null ? null : messageFormatArgs.clone();
this.status = HttpStatusEnum.OK.code();
}
public BizException(HttpStatusEnum status, ErrorCodeEnum code) {
super(code.getMsg());
this.code = code.getCode();
this.msg = code.getMsg();
this.status = status.code();
}
public BizException(HttpStatusEnum status, ErrorCodeEnum code, String message) {
super(message);
this.code = code.getCode();
this.msg = message;
this.status = status.code();
}
/**
* 对外契约码 + i18n msgName且保留 {@link HttpStatusEnum}(如 401供需要读取 {@link #getStatus()} 的场景。
*/
private BizException(HttpStatusEnum httpStatus, String apiCode, String message, String msgName,
Object[] messageFormatArgs) {
super(message);
this.code = apiCode;
this.msg = message;
this.msgName = msgName;
this.messageFormatArgs = messageFormatArgs == null ? null : messageFormatArgs.clone();
this.status = httpStatus.code();
}
/**
* 使用业务细分错误码(见 {@link BizExceptionCodeEnum})构造异常;响应中的 code 为枚举自带编码。
* 若对外必须固定为 4000/4011/4030 等,请使用 {@link #of(ErrorCodeEnum, IBizExceptionCodeEnum, Object...)}。
*/
public static BizException of(IBizExceptionCodeEnum codeEnum, Object... params) {
String message = codeEnum.formatMessage(params);
return new BizException(codeEnum.getCode(), message, ((Enum<?>) codeEnum).name(), params);
}
/**
* 使用对外统一错误码(须保留如 {@link ErrorCodeEnum#INVALID_PARAM 4000}、
* {@link ErrorCodeEnum#UNAUTHORIZED_REDIRECT 4011}、{@link ErrorCodeEnum#PERMISSION_DENIED 4030} 等契约)
* + 业务文案枚举构造异常;响应 code 取 {@code apiCode}message 取枚举模板(便于 i18n
*/
public static BizException of(ErrorCodeEnum apiCode, IBizExceptionCodeEnum messageEnum, Object... params) {
String message = messageEnum.formatMessage(params);
return new BizException(apiCode.getCode(), message, ((Enum<?>) messageEnum).name(), params);
}
/**
* 同 {@link #of(ErrorCodeEnum, IBizExceptionCodeEnum, Object...)},额外指定 HTTP 语义状态(如 {@link HttpStatusEnum#UNAUTHORIZED}
* 不改变对外 JSON 中的业务 {@code code}(仍取 {@code apiCode})。
*/
public static BizException of(HttpStatusEnum httpStatus, ErrorCodeEnum apiCode, IBizExceptionCodeEnum messageEnum,
Object... params) {
String message = messageEnum.formatMessage(params);
return new BizException(httpStatus, apiCode.getCode(), message, ((Enum<?>) messageEnum).name(), params);
}
public String getCode() {
return code;
}
/**
* 业务枚举常量名(用于 i18n未通过 {@link #of} 系列工厂构造时可能为 null。
*/
public String getMsgName() {
return msgName;
}
/**
* {@link #of(IBizExceptionCodeEnum, Object...)} 传入的占位参数副本;无则 null。
*/
public Object[] getMessageFormatArgs() {
return messageFormatArgs == null ? null : messageFormatArgs.clone();
}
public int getStatus() {
return status;
}
}

View File

@@ -0,0 +1,589 @@
package com.xspaceagi.system.spec.exception;
import lombok.Getter;
/**
* 异常枚举
*/
@Getter
public enum BizExceptionCodeEnum implements IBizExceptionCodeEnum {
/**
* 系统异常
*/
systemUnexpectedError("1000", "系统异常,请稍后再试", "A system error occurred. Please try again later.", "系统未预料统一捕获的异常,例如空指针、数组越界等"),
systemMissingRequiredParameter("1010", "系统异常,请稍后再试", "A system error occurred. Please try again later.", "参数异常,必填参数未传递"),
systemInternalRpcFailure("1020", "系统异常,请稍后再试", "A system error occurred. Please try again later.", "依赖服务内部系统RPC调用异常超时、服务不可用等"),
systemExternalHttpFailure("1030", "系统异常,请稍后再试", "A system error occurred. Please try again later.", "三方服务外部系统HTTP调用异常超时、对方系统异常等"),
systemDataLayerFailure("1040", "系统异常,请稍后再试", "A system error occurred. Please try again later.", "数据层MYSQL、ES等异常主键冲突、超时等"),
systemCacheFailure("1050", "系统异常,请稍后再试", "A system error occurred. Please try again later.", "缓存异常"),
//参数缺失:统一用「参数'xx'不能为空」,具体名称由调用方传入(与 i18n key fieldRequiredButEmpty 对应)
validationFailedWithDetail("2006", "%s", "%s", "参数校验失败"),
fieldRequiredButEmpty("2007", "参数'%s'不能为空", "Parameter '%s' is required.", "通用:必填项"),
/** 通用:数据/记录不存在知识库、Compose、自定义页等共用 */
resourceDataNotFound("5001", "数据不存在", "Data does not exist.", "通用"),
/** 通用配置记录不存在IM、沙箱、生态市场、Agent 组件等共用) */
configNotFound("8001", "配置不存在", "Configuration does not exist.", "通用"),
/** 通用:需要登录态 */
userNotLoggedIn("3177", "用户未登录", "User is not signed in.", "认证"),
/** 通用物理表不存在Compose DDL、助手查询等共用 */
tableNotFound("6013", "表不存在", "Table does not exist.", "通用"),
/** 通用:无权限(合并原 systemOperationDenied / systemOperationPermissionDenied / systemPermissionDeniedShort */
permissionDenied("3020", "无权限", "Permission denied.", "通用"),
//系统管理
systemGetTenantFailed("3202", "获取租户信息失败", "Failed to fetch tenant information.", "IM"),
systemUserNotFound("3001", "用户不存在", "User does not exist.", "用户不存在"),
systemUserStatusInvalid("3002", "用户启用状态标记异常", "Invalid user enabled status flag.", "用户启用状态标记异常"),
systemLoginCredentialsInvalid("3003", "用户或密码错误", "Invalid username or password.", "用户或密码错误"),
systemUserOrPhoneAlreadyExists("3004", "用户或手机号已存在", "Username or phone number already exists.", "用户或手机号已存在"),
systemOrgNotFound("3005", "机构不存在", "Organization does not exist.", "机构不存在"),
systemBackupFileNotFound("3006", "备份文件不存在,文件=%s", "Backup file not found, file=%s", "备份文件不存在"),
systemBackupRecordNotFound("3007", "备份记录不存在", "Backup record does not exist.", "备份记录不存在"),
systemBackupFileAlreadyExists("3008", "备份文件已存在,为避免覆盖文件,请重试备份操作", "Backup file already exists. Retry the backup to avoid overwriting.", "备份文件已存在,为避免覆盖文件,请重试备份操作"),
systemBackupDownloadIoError("3009", "下载备份文件时发生IO异常,%s", "I/O error while downloading backup file: %s", ""),
systemPasswordIncorrect("3010", "密码错误", "Incorrect password.", ""),
systemNewPasswordSameAsOld("3011", "新密码不能和旧密码相同", "New password must differ from the old password.", ""),
systemMenuNotFound("3012", "菜单不存在,KEY=%s", "Menu not found, KEY=%s", ""),
systemRegistrationClosed("3013", "注册已关闭", "Registration is disabled.", "认证"),
systemAccountDisabled("3014", "账号已被禁用", "Account has been disabled.", "认证"),
systemLoginIdentifierOrPasswordWrong("3015", "用户不存在或密码错误", "User does not exist or password is incorrect.", "认证"),
systemUserNotLoggedInWeb("3016", "用户未登陆", "User is not signed in.", "认证"),
systemMenuCodeAlreadyExists("3018", "已存在此菜单编码", "This menu code already exists.", "菜单"),
systemPersonalSpaceDeleteForbidden("3021", "个人空间不允许删除", "Personal space cannot be deleted.", "空间"),
systemParamRequired("3022", "参数不能为空", "Parameter cannot be empty.", "参数"),
systemCannotAddOwner("3023", "不能添加Owner", "Cannot add Owner.", "空间成员"),
systemCannotUpdateToOwner("3024", "不能更新为Owner", "Cannot change role to Owner.", "空间成员"),
systemCannotDeleteSelf("3025", "不能删除自己", "You cannot delete yourself.", "空间成员"),
systemSpaceNotFound("3026", "空间不存在", "Space does not exist.", "空间"),
systemCannotDeleteSpaceCreator("3027", "不能删除创建者", "Cannot remove the space creator.", "空间成员"),
systemEmailFormatInvalid("3028", "邮箱格式不正确", "Invalid email format.", "用户"),
systemEmailAlreadyInUse("3029", "邮箱已被占用", "Email is already in use.", "用户"),
systemPhoneAlreadyInUse("3030", "手机号已被占用", "Phone number is already in use.", "用户"),
systemSmsNotConfiguredDevHint("3031", "系统未配置短信服务,请直接输出本次验证码:%s", "SMS is not configured. Use this verification code: %s", "验证码"),
systemMailNotConfiguredDevHint("3032", "系统未配置邮件服务,请直接输出本次验证码:%s", "Mail is not configured. Use this verification code: %s", "验证码"),
systemApiKeyRateLimitPerMinute("4290", "每分钟请求次数超限", "Exceeded per-minute request frequency limit.", "API Key"),
systemApiKeyRateLimitPerDay("4290", "每日请求次数超限", "Exceeded daily request frequency limit.", "API Key"),
systemMailServiceNotConfigured("3033", "请在系统管理中配置邮件服务", "Configure mail service in system administration.", "邮件"),
systemMailSendFailed("3034", "邮件发送异常,请检查邮件服务配置", "Failed to send email. Check mail service configuration.", "邮件"),
systemSmsServiceNotConfigured("3035", "请在系统管理中配置短信服务", "Configure SMS service in system administration.", "短信"),
systemIdGenerateRetryFailed("3036", "%s失败请重试", "%s failed. Please try again.", "ID生成"),
/** 与 UNAUTHORIZED 契约一致;建议 {@code BizException.of(HttpStatusEnum.UNAUTHORIZED, ErrorCodeEnum.UNAUTHORIZED, …)} */
systemUnauthorizedOrSessionExpired("3037", "未登录或登录超时", "Not signed in or session expired.", "认证"),
/** RBAC角色 / 资源 / 用户组 domain 共用 */
systemRbacCodeFormatInvalid("3080", "编码只能包含字母、数字和下划线,且必须以字母开头", "Code may only contain letters, digits and underscores, and must start with a letter.", "RBAC"),
systemRbacResourceCodeFormatInvalid("3081", "资源码只能包含字母、数字和下划线,且必须以字母开头", "Resource code may only contain letters, digits and underscores, and must start with a letter.", "RBAC"),
systemRbacCodeLengthExceeded("3082", "编码长度不能超过100", "Code length cannot exceed 100.", "RBAC"),
systemRbacNameLengthExceeded("3083", "名称长度不能超过50", "Name length cannot exceed 50.", "RBAC"),
systemRbacDescLengthExceeded("3084", "描述长度不能超过500", "Description length cannot exceed 500.", "RBAC"),
systemRbacPathLengthExceeded("3085", "路径长度不能超过500", "Path length cannot exceed 500.", "RBAC"),
systemRoleCodeDuplicate("3086", "已存在此角色编码", "This role code already exists.", "RBAC"),
systemGroupCodeDuplicate("3087", "已存在此用户组编码", "This group code already exists.", "RBAC"),
systemResourceCodeDuplicate("3088", "已存在此资源编码", "This resource code already exists.", "RBAC"),
systemRbacSaveFailed("3089", "保存失败", "Save failed.", "RBAC"),
systemRoleNotFound("3090", "角色不存在", "Role does not exist.", "RBAC"),
systemResourceNotFound("3091", "资源不存在", "Resource does not exist.", "RBAC"),
systemGroupNotFound("3092", "用户组不存在", "User group does not exist.", "RBAC"),
systemBuiltinRoleCodeImmutable("3093", "系统内置角色编码不能修改", "Built-in role code cannot be changed.", "RBAC"),
systemBuiltinRoleNameImmutable("3094", "系统内置角色名称不能修改", "Built-in role name cannot be changed.", "RBAC"),
systemBuiltinRoleCannotDisable("3095", "系统内置角色不能禁用", "Built-in role cannot be disabled.", "RBAC"),
systemBuiltinResourceCodeImmutable("3096", "系统内置资源编码不能修改", "Built-in resource code cannot be changed.", "RBAC"),
systemBuiltinResourceNameImmutable("3097", "系统内置资源名称不能修改", "Built-in resource name cannot be changed.", "RBAC"),
systemBuiltinResourceCannotDisable("3098", "系统内置资源不能禁用", "Built-in resource cannot be disabled.", "RBAC"),
systemBuiltinGroupCodeImmutable("3099", "系统内置用户组编码不能修改", "Built-in group code cannot be changed.", "RBAC"),
systemBuiltinGroupNameImmutable("3100", "系统内置用户组名称不能修改", "Built-in group name cannot be changed.", "RBAC"),
systemBuiltinGroupCannotDisable("3101", "系统内置用户组不能禁用", "Built-in group cannot be disabled.", "RBAC"),
systemRbacDataPermissionRequired("3102", "数据权限配置不能为空", "Data permission configuration is required.", "RBAC"),
systemRbacTokenLimitMinInvalid("3103", "最大Token不能小于-1", "Max tokens cannot be less than -1.", "RBAC"),
systemRoleBindRequiresAdminUser("3104", "仅管理员类型用户才可以绑定角色 [%s]", "Only admin-type users may bind role [%s].", "RBAC"),
systemSuperAdminRequiresRoleMenuResources("3105", "超级管理员角色必须绑定必要 菜单[角色管理] 和 资源[查询、菜单权限]", "Super admin role must bind required menu [Role management] and resources [Query, menu permission].", "RBAC"),
systemRbacMenuIdNotFound("3106", "菜单ID[%s]不存在", "Menu ID [%s] does not exist.", "RBAC"),
systemSuperAdminRequiresRoleMenuResourcesAlt("3107", "超级管理员角色必须绑定必要 菜单[角色管理] 及资源 [查询、菜单权限]", "Super admin role must bind required menu [Role management] and resources [Query, menu permission].", "RBAC"),
systemSuperAdminRequiresMenuByName("3108", "超级管理员角色必须绑定必要菜单 [%s]", "Super admin role must bind required menu [%s].", "RBAC"),
systemSuperAdminResourceCodeMissing("3109", "超级管理员角色必须绑定必要菜单 [角色管理] 及资源 [查询、菜单权限],系统未找到资源[%s],请联系管理员检查配置", "Super admin must bind menu [Role management] and resources [Query, menu permission]. Resource [%s] not found. Contact an administrator.", "RBAC"),
systemSuperAdminResourceMenuOrphan("3110", "超级管理员角色必须绑定必要菜单 [角色管理] 及资源 [查询、菜单权限],资源[%s]未关联菜单,请联系管理员检查配置", "Super admin must bind menu [Role management] and resources [Query, menu permission]. Resource [%s] is not linked to a menu. Contact an administrator.", "RBAC"),
systemSuperAdminBindIncomplete("3111", "超级管理员角色必须绑定必要菜单 [角色管理] 及资源 [查询、菜单权限]", "Super admin role must bind menu [Role management] and resources [Query, menu permission].", "RBAC"),
systemRbacParentIdInvalid("3112", "父级ID无效", "Invalid parent ID.", "RBAC"),
systemRbacParentResourceNotFoundWithParentId("3113", "父级资源不存在,parentId=%s", "Parent resource not found, parentId=%s", "RBAC"),
systemRbacParentNameNotModule("3114", "[%s]不是模块,不能作为父级", "[%s] is not a module and cannot be used as a parent.", "RBAC"),
systemRbacParentSelfReferenceForbidden("3115", "父级节点不能是自身 [id:%s]", "Parent node cannot be itself [id:%s].", "RBAC"),
systemRbacParentResourceNotFound("3116", "父级资源不存在", "Parent resource does not exist.", "RBAC"),
systemRbacParentIdInvalidForResource("3117", "父级ID无效: resourceId=%s", "Invalid parent ID: resourceId=%s", "RBAC"),
systemRbacParentNodeNotFound("3118", "父级节点不存在 [parentId:%s]", "Parent node does not exist [parentId:%s].", "RBAC"),
systemResourceTreeJsonInvalid("3119", "resourceTreeJson 反序列化失败", "Failed to deserialize resourceTreeJson.", "RBAC"),
systemRoleNotFoundWithRowId("3120", "角色不存在: id=%s", "Role does not exist: id=%s", "RBAC"),
systemRbacUserNotFoundWithId("3121", "用户不存在,id=%s", "User does not exist, id=%s", "RBAC"),
systemRoleNotFoundWithRoleId("3122", "角色不存在,id=%s", "Role does not exist, id=%s", "RBAC"),
systemGroupMaxUsersBelowBound("3123", "最大用户数不能小于已绑定用户数,当前已绑定%s人", "Max users cannot be below the number already bound; currently %s user(s) bound.", "RBAC"),
systemGroupUserLimitExceeded("3124", "组用户数量超出限制", "Group user count exceeds the limit.", "RBAC"),
systemGroupNotFoundWithRowId("3125", "用户组不存在: id=%s", "User group does not exist: id=%s", "RBAC"),
systemGroupNotFoundWithGroupId("3126", "组不存在,id=%s", "Group does not exist, id=%s", "RBAC"),
systemGroupNotFoundWithGroupIdAlt("3127", "用户组不存在,id=%s", "User group does not exist, id=%s", "RBAC"),
systemDataPermissionTargetTypeInvalid("3128", "数据权限目标类型错误", "Invalid data permission target type.", "数据权限"),
systemDataPermissionTargetIdInvalid("3129", "数据权限目标ID错误", "Invalid data permission target ID.", "数据权限"),
systemMenuBindResourceNotFound("3130", "资源ID[%s]不存在", "Resource ID [%s] does not exist.", "菜单绑定"),
systemMenuBindResourceOutOfScope("3131", "资源ID[%s]不在菜单ID[%s]的绑定资源范围内", "Resource ID [%s] is outside the bound resources for menu ID [%s].", "菜单绑定"),
systemMenuBindResourceBindTypeInvalid("3132", "资源ID[%s]的绑定类型[%s]无效只能是0(NONE)、1(ALL)或2(PART)", "For resource ID [%s], bind type [%s] is invalid; must be 0 (NONE), 1 (ALL), or 2 (PART).", "菜单绑定"),
systemRbacResourceCodeLengthExceeded("3133", "资源码长度不能超过100", "Resource code length cannot exceed 100.", "RBAC"),
systemGroupCannotBindForbiddenMenu("3134", "用户组不能绑定「%s」菜单", "User group cannot bind menu \"%s\".", "RBAC"),
systemVerifyCodeIncorrect("3135", "验证码错误", "Incorrect verification code.", "验证码"),
systemVerifyParamInvalid("3136", "校验参数异常", "Invalid verification parameters.", "验证码"),
systemVerifyCodeCheckFailed("3137", "验证码校验失败", "Verification code check failed.", "验证码"),
systemUsernameDigitsOnlyForbidden("3138", "用户名不能为纯数字", "Username cannot be all digits.", "用户"),
systemUsernameAlreadyInUse("3139", "用户名已被占用", "Username is already taken.", "用户"),
systemUsernameFormatInvalid("3140", "用户名不符合规范", "Username does not meet the rules.", "用户"),
systemUsernameChangeDisallowedInCurrentAuthMode("3141", "当前认证模式不允许修改用户名", "Username cannot be changed in the current auth mode.", "用户"),
systemNicknameDigitsOnlyForbidden("3142", "昵称不能为纯数字", "Nickname cannot be all digits.", "用户"),
systemWeChatAccessTokenFetchFailed("3143", "获取微信 access_token 失败", "Failed to obtain WeChat access_token.", "微信"),
systemWeChatApiReturnedError("3144", "%s", "%s", "微信"),
systemWeChatPhoneNumberFetchFailed("3145", "获取微信手机号失败", "Failed to obtain WeChat phone number.", "微信"),
systemTenantDomainAlreadyInUse("3146", "域名%s已被占用", "Domain %s is already in use.", "租户"),
systemUserIdInvalid("3147", "错误的用户ID", "Invalid user ID.", "用户"),
systemMenuPermissionImportTenantInvalid("3148", "菜单权限导入失败,租户ID无效", "Menu permission import failed: invalid tenant ID.", "权限"),
systemMenuPermissionDiffImportTenantInvalid("3149", "菜单权限差异导入失败,租户ID无效", "Menu permission diff import failed: invalid tenant ID.", "权限"),
systemCategoryOperationDenied("3150", "无权限操作该分类", "No permission to operate this category.", "分类"),
systemMenuIdNullWithNodeName("3151", "菜单id不能为null,name:%s", "Menu id cannot be null, name:%s", "菜单"),
systemI18nExportRowCountExceeded("3152", "导出行数(%d超过上限%d请缩小筛选条件后重试", "Export row count (%d) exceeds the limit (%d). Narrow filters and try again.", "i18n"),
systemI18nTranslationFailedTargetLang("3153", "翻译失败。目标语言:%s", "Translation failed. Target language: %s", "i18n"),
systemI18nBatchTranslationSizeMismatch("3154", "批量翻译返回条数不匹配。目标语言:%s分块起始%s", "Batch translation count mismatch. Target language: %s, chunk start: %s", "i18n"),
systemI18nBatchTranslationResultEmpty("3155", "批量翻译结果为空。Key = %s目标语言 = %s", "Batch translation result is empty. Key = %s, target language = %s", "i18n"),
systemI18nLangTagInvalid("3156", "语言标识格式不正确,请使用合法的语言标签,如 zh-CN、en-US、zh-Hans-CN", "Invalid language tag. Use a valid BCP 47 tag such as zh-CN, en-US, or zh-Hans-CN.", "i18n"),
systemI18nLangTagDuplicate("3157", "该语言标签已存在,不允许重复", "This language tag already exists; duplicates are not allowed.", "i18n"),
systemI18nBatchTranslationNotJson("3158", "批量翻译返回非 JSON 对象:%s", "Batch translation returned a non-JSON object: %s", "i18n"),
systemI18nBatchTranslationKeyOrValueMissing("3159", "批量翻译缺少 key 或值为空: %s", "Batch translation missing key or empty value: %s", "i18n"),
systemI18nTranslationEmpty("3160", "翻译返回空结果", "Translation returned empty.", "i18n"),
systemI18nTranslationModelAuthFailed("3161", "翻译失败:模型鉴权失败,请检查默认模型的 API Key/鉴权配置。", "Translation failed: model authentication error. Check default model API key and auth settings.", "i18n"),
systemI18nTranslationFailedWithReason("3162", "翻译失败: %s", "Translation failed: %s", "i18n"),
systemI18nOriginalRecordNotFound("3163", "原始记录不存在", "The original record does not exist.", "i18n"),
bootstrapAuthRedirectUrl("3164", "%s", "%s", "登录跳转"),
bootstrapLicenseContentInvalid("3165", "许可证内容无效", "Invalid license content.", "License"),
systemNoPermissionForSystemApi("3166", "你没有权限", "You do not have permission.", "权限"),
apiKeyInvalid("3167", "无效的 API Key", "Invalid API Key.", "API Key"),
apiKeyExpired("3168", "API Key 已过期", "API Key expired.", "API Key"),
apiKeyAccessDenied("3169", "API Key 无访问权限", "API Key does not have access permissions.", "API Key"),
apiKeyMissing("3170", "缺少 API Key", "Missing API Key.", "API Key"),
apiKeyUserDisabled("3171", "用户已停用", "User disabled.", "API Key"),
apiKeyAgentApiDisabled("3172", "当前已禁用 API 调用", "The API calls are currently disabled.", "API Key"),
apiKeyOpenApiNotFound("3173", "API 不存在或无权限", "API not found or permission denied.", "API Key"),
apiKeyPermissionDenied("3174", "无权限", "Permission denied.", "API Key"),
imFeishuWebhookMissingAppId("3178", "飞书 Webhook 缺少必要参数: appId", "Feishu Webhook is missing required parameter: appId.", "IM"),
imFeishuBotNotBound("3179", "飞书机器人未绑定", "Feishu bot is not bound.", "IM"),
imDingtalkWebhookMissingRobotCode("3180", "钉钉 Webhook 缺少必要参数: robotCode", "DingTalk Webhook is missing required parameter: robotCode.", "IM"),
imDingtalkBotNotBound("3181", "钉钉机器人未绑定", "DingTalk bot is not bound.", "IM"),
imWechatQrFetchFailed("3182", "获取微信二维码失败: %s", "Failed to fetch WeChat QR code: %s", "IM"),
imWechatQrSessionExpired("3183", "扫码会话已过期或不存在", "Scan session has expired or does not exist.", "IM"),
imWechatQrSessionDataInvalid("3184", "会话数据异常", "Session data is invalid.", "IM"),
imWechatQrQueryStatusFailed("3185", "查询扫码状态失败: %s", "Failed to query scan status: %s", "IM"),
imWechatIlinkChannelOnly("3188", "仅支持微信 iLink 渠道配置", "Only WeChat iLink channel configuration is supported.", "IM"),
imWechatIlinkConfigDisabled("3189", "当前微信 iLink 配置未启用", "WeChat iLink configuration is not enabled.", "IM"),
imWechatIlinkConfigMissing("3190", "微信 iLink 配置缺失", "WeChat iLink configuration is missing.", "IM"),
imWechatIlinkBotTokenMissing("3191", "微信 iLink 配置缺少 botToken", "WeChat iLink configuration is missing botToken.", "IM"),
imWechatIlinkUserIdMissing("3192", "微信 iLink 配置缺少 ilinkUserId", "WeChat iLink configuration is missing ilinkUserId.", "IM"),
imWechatIlinkPushFailed("3193", "推送失败: %s", "Push failed: %s", "IM"),
imChannelConfigInvalidOrUnavailable("3194", "指定的 im_channel_config 不存在、未启用或不是当前空间下可用的微信 iLink 渠道", "The specified im_channel_config does not exist, is disabled, or is not an available WeChat iLink channel in this space.", "IM"),
imNoWechatIlinkInSpace("3195", "当前空间未配置可用的微信 iLink 渠道", "No available WeChat iLink channel is configured for this space.", "IM"),
imMultipleWechatIlinkNeedExplicitId("3196", "存在多条启用的微信 iLink 配置,主动/定时任务须显式指定 im_channel_config.id对齐 openclaw-weixin 1.0.3 delivery.accountId", "Multiple enabled WeChat iLink configs exist; proactive/scheduled tasks must specify im_channel_config.id explicitly (aligned with openclaw-weixin 1.0.3 delivery.accountId).", "IM"),
imTenantOrUserMissing("3197", "租户或用户信息缺失", "Tenant or user information is missing.", "IM"),
imWechatChannelNotFoundForBot("3198", "未找到与该 botId 对应的微信渠道配置", "No WeChat channel configuration found for this botId.", "IM"),
imWechatChannelNotFoundForUser("3199", "未找到当前用户的微信渠道配置", "No WeChat channel configuration found for the current user.", "IM"),
imWechatChannelDisabled("3200", "微信渠道配置已禁用", "WeChat channel configuration is disabled.", "IM"),
imWechatIlinkParseFailed("3201", "微信 iLink 配置解析失败", "Failed to parse WeChat iLink configuration.", "IM"),
imCannotResolveTargetId("3207", "无法从配置数据中解析目标唯一标识", "Cannot resolve target unique identifier from configuration data.", "IM"),
imChannelConfigDuplicate("3208", "该渠道配置已存在", "This channel configuration already exists.", "IM"),
imChannelConfigDuplicateDetail("3209", "该渠道配置已存在: %s %s %s", "This channel configuration already exists: %s %s %s", "IM"),
customPageMultimodalModelUnavailable("3212", "当前多模态模型不可用:%s", "Multimodal model is unavailable: %s", "自定义页面"),
customPageModelNotMultimodal("3213", "当前模型不支持多模态,无法解析图片,模型 id=%s", "This model does not support multimodal input; cannot parse images. Model id=%s", "自定义页面"),
customPageChatModelUnavailable("3214", "当前聊天模型不可用:%s", "Chat model is unavailable: %s", "自定义页面"),
customPageProxyProjectBuildNotFound("3215", "未找到项目构建信息", "Project build information not found.", "自定义页面"),
customPageProxyDevServerNotStarted("3216", "项目未启动开发服务器", "Dev server has not been started for this project.", "自定义页面"),
customPageProxyAuthFailed("3217", "认证失败", "Authentication failed.", "自定义页面"),
customPageProxyNoSpace("3218", "无空间信息", "No space information.", "自定义页面"),
customPageProxyNoAgentPermission("3219", "无Agent权限", "No Agent permission.", "自定义页面"),
customPageProxyNoAgentOrchestrationPermission("3220", "无Agent编排权限", "No Agent orchestration permission.", "自定义页面"),
sandboxClientAddressUnavailable("3222", "无法获取客户端服务地址", "Unable to obtain client service address.", "沙盒"),
sandboxUserProxyCreateFailed("3223", "创建用户沙盒代理失败", "Failed to create user sandbox proxy.", "沙盒"),
sandboxDeployFailedWithHelp("3225", "%s", "%s", "沙盒"),
sandboxConfigKeyDuplicate("3226", "配置键已存在,请使用其他配置键", "Configuration key already exists; use another key.", "沙盒"),
mcpNotFound("3227", "MCP不存在", "MCP does not exist.", "MCP"),
mcpServiceConfigJsonInvalid("3228", "服务配置格式错误请填写正确的JSON数据", "Invalid service configuration format; provide valid JSON.", "MCP"),
mcpNpxConfigInvalid("3229", "请输入正确的npx配置", "Enter a valid npx configuration.", "MCP"),
mcpUvxConfigInvalid("3230", "请输入正确的uvx配置", "Enter a valid uvx configuration.", "MCP"),
mcpStreamableHttpConfigInvalid("3231", "请输入正确的streamableHTTP配置", "Enter a valid streamable HTTP configuration.", "MCP"),
mcpSseConfigInvalid("3232", "请输入正确的sse配置", "Enter a valid SSE configuration.", "MCP"),
/** MCP / 插件参数校验共用 */
paramArgTypeInvalid("3234", "参数[%s]类型错误", "Parameter [%s] has an invalid type.", "参数"),
mcpDeployResponseNull("3235", "McpDeployStatusResponse 为空", "McpDeployStatusResponse is null.", "MCP"),
remoteServiceMessage("3236", "%s", "%s", "远程调用"),
customPageDomainBindPermissionDenied("3237", "无权限操作该域名绑定", "No permission to manage this domain binding.", "自定义页面"),
customPageProxyEnvPathExists("3238", "指定环境和路径的代理配置已存在,无法添加", "Proxy config for this environment and path already exists; cannot add.", "自定义页面"),
customPageProxyEnvPathNotFoundForEdit("3239", "指定环境和路径的代理配置不存在,无法编辑", "Proxy config for this environment and path does not exist; cannot edit.", "自定义页面"),
customPageProxyEnvPathNotFoundForDelete("3240", "指定环境和路径的代理配置不存在,无法删除", "Proxy config for this environment and path does not exist; cannot delete.", "自定义页面"),
customPagePathConfigExists("3241", "指定路径的配置已存在,无法添加", "Configuration for this path already exists; cannot add.", "自定义页面"),
customPagePathConfigNotFoundForEdit("3242", "指定路径的配置不存在,无法编辑", "Configuration for this path does not exist; cannot edit.", "自定义页面"),
customPagePathConfigNotFoundForDelete("3243", "指定路径的配置不存在,无法删除", "Configuration for this path does not exist; cannot delete.", "自定义页面"),
customPageProjectConfigNotFound("3244", "项目配置不存在", "Project configuration does not exist.", "自定义页面"),
customPageDuplicatePathConfig("3245", "存在重复的路径配置: %s:%s", "Duplicate path configuration: %s:%s", "自定义页面"),
customPageBackendListEmpty("3246", "后端地址列表不能为空: %s:%s", "Backend address list cannot be empty: %s:%s", "自定义页面"),
customPageBackendAddressEmpty("3247", "后端地址不能为空: %s:%s", "Backend address cannot be empty: %s:%s", "自定义页面"),
customPagePluginQueryFailed("3248", "查询插件失败,插件[%s:%s]", "Failed to query plugin [%s:%s]", "自定义页面"),
customPageWorkflowQueryFailed("3249", "查询工作流失败,工作流[%s:%s]", "Failed to query workflow [%s:%s]", "自定义页面"),
customPageDatasourceParamNameDuplicate("3251", "存在重复的参数名称: %s", "Duplicate parameter name: %s", "自定义页面"),
customPageConfigFileParseFailed("3252", "配置文件解析失败: %s", "Failed to parse configuration file: %s", "自定义页面"),
customPageWebAppCountExceeded("3253", "你的网页应用数量已经达到上限,网页应用上限数为%s", "You have reached the web app limit; maximum is %s.", "自定义页面"),
customPageCreateConfigFailed("3254", "创建自定义页面(config)失败: %s", "Failed to create custom page (config): %s", "自定义页面"),
customPageCreateBuildFailed("3255", "创建自定义页面(build)失败: %s", "Failed to create custom page (build): %s", "自定义页面"),
customPageCreateAgentFailed("3256", "创建智能体失败: %s", "Failed to create agent: %s", "自定义页面"),
customPageBindAgentFailed("3257", "绑定智能体到项目失败: %s", "Failed to bind agent to project: %s", "自定义页面"),
customPageCreateReverseProxyFailed("3258", "创建反向代理项目失败: %s", "Failed to create reverse proxy project: %s", "自定义页面"),
customPageDeleteReverseProxyFailed("3259", "删除反向代理配置失败: %s", "Failed to delete reverse proxy configuration: %s", "自定义页面"),
customPageConfigPageParamsFailed("3260", "配置页面参数失败: %s", "Failed to configure page parameters: %s", "自定义页面"),
customPageAddPathConfigFailed("3261", "添加路径配置失败: %s", "Failed to add path configuration: %s", "自定义页面"),
customPageEditPathConfigFailed("3262", "编辑路径配置失败: %s", "Failed to edit path configuration: %s", "自定义页面"),
customPageDeletePathConfigFailed("3263", "删除路径配置失败: %s", "Failed to delete path configuration: %s", "自定义页面"),
customPageBatchReverseProxyFailed("3264", "批量配置反向代理失败: %s", "Failed to batch configure reverse proxy: %s", "自定义页面"),
customPageSaveDataSourceFailed("3265", "保存数据源失败: %s", "Failed to save data source: %s", "自定义页面"),
customPageUnbindDataSourceFailed("3266", "解绑数据源失败: %s", "Failed to unbind data source: %s", "自定义页面"),
customPageUpdateProjectFailed("3267", "修改项目失败: %s", "Failed to update project: %s", "自定义页面"),
customPageUpdateAgentFailed("3268", "更新智能体失败: %s", "Failed to update agent: %s", "自定义页面"),
customPageUpdateProjectException("3269", "修改项目异常: %s", "Error while updating project: %s", "自定义页面"),
customPageDeleteProjectFailed("3270", "删除项目失败: %s", "Failed to delete project: %s", "自定义页面"),
customPageDeleteAgentFailed("3271", "删除智能体失败: %s", "Failed to delete agent: %s", "自定义页面"),
customPageDeleteProjectException("3272", "删除项目异常: %s", "Error while deleting project: %s", "自定义页面"),
customPageCopyPluginFailed("3273", "复制插件失败: %s", "Failed to copy plugin: %s", "自定义页面"),
customPageCopyWorkflowFailed("3274", "复制工作流失败: %s", "Failed to copy workflow: %s", "自定义页面"),
customPageProxyPathLoadFailed("3275", "获取页面配置失败", "Failed to load page configuration.", "自定义页面"),
customPageProxyPathNoAgent("3277", "页面没有绑定智能体", "No agent is bound to this page.", "自定义页面"),
customPageKeepAliveDbUpdateFailed("3278", "KeepAlive更新库表失败", "KeepAlive failed to update database tables.", "自定义页面"),
//加密解密异常
cipherDecryptFailed("4001", "解密失败", "Decryption failed.", "解密失败"),
cipherEncryptFailed("4002", "加密失败", "Encryption failed.", "加密失败"),
//知识库
knowledgeTemplateDirectiveTypeNotFound("5002", "模板指令类型不存在", "Template directive type does not exist.", "模板指令类型不存在"),
knowledgeUnknownAnalysisDimension("5005", "未识别的分析维度类型[%s]", "Unknown analysis dimension type [%s].", "未识别的分析维度类型"),
knowledgeDataMappingFailed("5006", "数据映射识别,异常=%s", "Data mapping failed, error=%s", "excel数据映射记录"),
knowledgeExcelDataRequired("5007", "Excel相关数据不能为空", "Excel-related data cannot be empty.", "Excel相关数据不能为空"),
knowledgeExcelHeaderRequired("5008", "Excel抬头字段信息不能为空", "Excel header field information cannot be empty.", "Excel抬头字段信息不能为空"),
knowledgeVectorDatabaseNotFound("5011", "向量数据库[{}]不存在", "Vector database [{}] does not exist.", ""),
knowledgeFileIdNotFound("5012", "文件ID不存在", "File ID does not exist.", ""),
knowledgeDocumentParseFailed("5014", "解析文档失败", "Failed to parse document.", ""),
knowledgeDocumentUnsupportedType("5015", "解析文档失败,错误:不支持的文件类型", "Failed to parse document: unsupported file type.", ""),
knowledgeLlmAnswerEmpty("5016", "大模型返回的答案为空,分段id=%s", "The model returned an empty answer, segment id=%s", ""),
knowledgeLlmQuestionEmpty("5017", "大模型返回的问题为空,分段id=%s", "The model returned an empty question, segment id=%s", ""),
knowledgeImportFileFailed("5019", "导入文件失败,%s", "Failed to import file, %s", ""),
knowledgeGenerateTemplateFailed("5020", "生成模板失败:,%s", "Failed to generate template: %s", ""),
knowledgeKbNotFoundById("5021", "知识库不存在,知识库ID=%s", "Knowledge base does not exist, id=%s", ""),
knowledgeVectorizationFailed("5022", "向量化失败,%s", "Vectorization failed, %s", ""),
knowledgeDeleteKbFulltextFailed("5023", "删除知识库全文检索数据失败", "Failed to delete knowledge base full-text index data.", ""),
knowledgeDeleteDocFulltextFailed("5024", "删除文档全文检索数据失败", "Failed to delete document full-text index data.", ""),
knowledgeDeleteSegmentFulltextFailed("5025", "删除原始分段全文检索数据失败", "Failed to delete original segment full-text index data.", ""),
knowledgeJsonParseUnsupported("5026", "解析JSON文档失败,JSON格式不支持,期望JSON数组或JSON对象", "Failed to parse JSON document: unsupported format; expected a JSON array or object.", ""),
knowledgeQaGenerationBusy("5027", "操作失败:当前数据正在生成问答,请稍后重试!", "Operation failed: Q&A generation is in progress for this data. Please try again later.", "知识库"),
knowledgeStorageUpperBound("5028", "操作失败,已超过知识库的存储上限!(最大%sGB)", "Operation failed: knowledge base storage limit exceeded (max %s GB).", "知识库"),
knowledgeKbCreateCountExceeded("5029", "操作失败,添加的知识库数量超过上限(%s", "Operation failed: number of knowledge bases exceeds the limit (%s).", "知识库"),
knowledgeNotFoundSimple("5030", "知识库不存在", "Knowledge base does not exist.", "知识库"),
memoryUnitNotFound("5031", "记忆单元不存在: %s", "Memory unit does not exist: %s", "记忆"),
modelProxyTokenLimitExceeded("5032", "超出 token 限制", "Token limit exceeded.", "模型代理"),
//组件模块
composeCannotGetCreateTableDdl("6002", "无法获取建表DDL语句", "Unable to obtain CREATE TABLE DDL.", ""),
composeDorisDbNameParseFailed("6003", "解析Doris数据库名称失败: %s", "Failed to parse Doris database name: %s", ""),
composeSqlOnlyDmlAllowed("6004", "只允许执行 SELECT/INSERT/UPDATE/DELETE 查询语句", "Only SELECT, INSERT, UPDATE, or DELETE statements are allowed.", ""),
composeSqlEmpty("6005", "执行的SQL语句不能为空", "SQL statement cannot be empty.", ""),
composeSqlExecuteFailed("6006", "执行SQL失败,%s", "SQL execution failed, %s", ""),
composeCreateTableFailed("6008", "创建表失败", "Failed to create table.", ""),
composeCannotBuildUpdateSet("6010", "无法构建更新的 SET 子句", "Unable to build UPDATE SET clause.", ""),
composeUpdateDataEmpty("6011", "更新的数据不能为空", "Update data cannot be empty.", ""),
composeSqlParseFailed("6015", "SQL解析失败,%s", "SQL parse failed, %s", ""),
composeSqlOnlyDdl("6016", "只允许DDL语句,sql=%s", "Only DDL statements are allowed, sql=%s", ""),
composeQueryAllDataFailed("6017", "查询全部数据失败", "Failed to query all data.", ""),
composeCannotDropFieldWithData("6018", "表中已有数据,不允许删除字段", "Cannot drop column: table already contains data.", ""),
composeCannotChangeUniqueWithData("6019", "字段[%s]已有数据,不允许修改唯一性约束", "Cannot change unique constraint on field [%s]: data already exists.", ""),
composeCannotChangeNullableWithData("6020", "字段[%s]已有数据,不允许修改非空约束", "Cannot change nullability on field [%s]: data already exists.", ""),
composeDbTypeNotConfigured("6021", "未配置数据库类型,配置:spring.datasource.sql-generator.type", "Database type not configured; set spring.datasource.sql-generator.type.", ""),
composeUnsupportedDbType("6022", "不支持的数据库类型: %s, 仅支持 mysql 或 doris", "Unsupported database type: %s; only mysql or doris is supported.", ""),
composeDorisUrlNotConfigured("6023", "未配置Doris数据源URL,配置:spring.datasource.dynamic.datasource.doris.url", "Doris datasource URL not configured; set spring.datasource.dynamic.datasource.doris.url.", ""),
composeInsertDataEmpty("6024", "插入的数据不能为空", "Insert data cannot be empty.", ""),
composeTableDefinitionNotFound("6025", "表定义不存在", "Table definition does not exist.", ""),
composeCreateIndexFailed("6026", "创建索引失败", "Failed to create index.", ""),
composeFieldNameTooLong("6028", "字段名长度不能超过64字符", "Field name cannot exceed 64 characters.", ""),
composeFieldNameMustStartWithLetter("6029", "字段名必须以英文字母开头", "Field name must start with a letter.", ""),
composeFieldNameInvalidChars("6030", "字段名只能包含字母、数字和下划线", "Field name may only contain letters, digits, and underscores.", ""),
composeCheckTableExistsFailed("6031", "检查表是否存在时发生错误,数据库,%s", "Error while checking if table exists, database %s", ""),
composeTruncateTableFailed("6032", "清空表数据时发生错误,数据库,%s", "Error while truncating table, database %s", ""),
composeGetTableDefinitionFailed("6033", "获取表定义信息时发生错误,数据库,%s", "Error while fetching table definition, database %s", ""),
composeRawSqlExecuteFailed("6034", "执行原始管理/DML/DDL的SQL异常,%s", "Error executing raw admin/DML/DDL SQL, %s", ""),
composeUnsupportedSqlType("6035", "不支持的SQL类型,SqlType=%s", "Unsupported SQL type, SqlType=%s", ""),
composeBuildConditionFailed("6036", "创建条件表达式失败,%s", "Failed to build condition expression, %s", ""),
composeDefaultValueMustBeNumber("6037", "字段[%s]的默认值必须为数值", "Default value for field [%s] must be numeric.", ""),
composeDefaultValueMustBeBoolean("6038", "字段[%s]的默认值必须为布尔值", "Default value for field [%s] must be boolean.", ""),
composeDefaultValueTooLong("6039", "字段[%s]的默认值长度不能超过255字符", "Default value for field [%s] cannot exceed 255 characters.", ""),
composeMediumtextNoDefault("6040", "MEDIUMTEXT类型字段[%s]不允许设置默认值", "MEDIUMTEXT field [%s] cannot have a default value.", "MEDIUMTEXT类型字段不允许设置默认值"),
composeExcelRowCountExceeded("6041", "Excel数据行数超过限制,最大支持[%s]行", "Excel row count exceeds limit; maximum [%s] rows.", ""),
composeTableRowCountExceeded("6042", "表总行数超过限制,最大支持[%s]行", "Total table row count exceeds limit; maximum [%s] rows.", ""),
composeTableDefMissingFields("6043", "表定义缺少字段定义", "Table definition is missing field definitions.", ""),
composeFieldAlreadyExists("6044", "字段[%s]已存在", "Field [%s] already exists.", ""),
composeDefaultValueOutOfRange("6045", "字段[%s]的默认值超出范围,范围区间:[%s,%s]", "Default value for field [%s] is out of range [%s, %s].", ""),
composeGenericMessage("6047", "%s", "%s", ""),
//日志平台
logPlatformSearchFailed("7001", "搜索失败,%s", "Search failed, %s", "搜索失败"),
logPlatformInsertFailed("7002", "新增失败,%s", "Insert failed, %s", "新增失败"),
logPlatformBatchInsertFailed("7003", "批量新增失败,%s", "Batch insert failed, %s", "批量新增失败"),
//生态市场
ecoMarketGetConfigFailed("8002", "获取配置异常,%s", "Failed to fetch configuration, %s", "获取配置详情异常"),
ecoMarketPublishConfigFailed("8003", "发布配置异常,%s", "Failed to publish configuration, %s", "发布配置异常"),
ecoMarketOfflineConfigFailed("8004", "下线配置异常,%s", "Failed to offline configuration, %s", "下线配置异常"),
ecoMarketQueryConfigStatusFailed("8005", "查询配置状态异常,%s", "Failed to query configuration status, %s", "查询配置状态异常"),
ecoMarketQueryPublishedDetailFailed("8006", "查询发布配置详情异常,%s", "Failed to query published configuration detail, %s", "查询发布配置详情异常"),
ecoMarketCannotDeleteRemotePublished("8010", "远程生态市场已上架的配置不能删除", "Cannot delete configuration that is listed on the remote marketplace.", ""),
ecoMarketClientSecretFetchFailed("8011", "获取客户端密钥失败,请稍后重试", "Failed to fetch client secret. Please try again later.", "获取客户端密钥失败"),
ecoMarketUpdateOnlyDraftOrRejected("8012", "只能更新草稿或被驳回状态的配置", "Only draft or rejected configurations can be updated.", "只能更新草稿或被驳回状态的配置"),
ecoMarketNoPermissionToUpdate("8013", "无权更新此配置", "No permission to update this configuration.", "无权更新此配置"),
ecoMarketConfigInfoNotFound("8014", "未找到对应的配置信息", "Configuration not found.", "未找到对应的配置信息"),
ecoMarketModelAndUidRequired("8016", "配置模型不能为空且UID必须指定", "Model is required and UID must be specified.", "配置模型不能为空且UID必须指定"),
ecoMarketPublishedConfigNotFound("8017", "未找到对应的发布配置信息", "Published configuration not found.", "未找到对应的发布配置信息"),
ecoMarketUnsupportedDataType("8019", "不支持的数据类型", "Unsupported data type.", ""),
ecoMarketReleaseFailed("8020", "发版失败,%s", "Release failed, %s", ""),
ecoMarketSaveConfigFailed("8021", "保存配置异常,%s", "Failed to save configuration, %s", ""),
ecoMarketEnableConfigFailed("8023", "启用配置失败", "Failed to enable configuration.", ""),
ecoMarketDuplicateShareNotAllowed("8025", "已有重复的配置,不允许新建我的分享", "Duplicate configuration exists; cannot create a new share.", ""),
ecoMarketCenterUpgrading("8026", "生态市场中心服务升级中,请稍后再试", "Eco marketplace center is upgrading. Please try again later.", ""),
ecoMarketConfigResultBodyEmpty("8027", "获取配置结果失败,Body为空", "Failed to get configuration result: empty body.", ""),
ecoMarketDeployMcpFailed("8030", "部署MCP失败", "Failed to deploy MCP.", "部署MCP失败"),
ecoMarketStopMcpFailed("8031", "停止MCP失败", "Failed to stop MCP.", "停止MCP失败"),
ecoMarketMcpConfigParseFailed("8032", "MCP配置解析失败", "Failed to parse MCP configuration.", "MCP配置解析失败"),
ecoMarketDisableConfigFailed("8033", "禁用配置失败", "Failed to disable configuration.", ""),
ecoMarketOfflineOnlyPublishedOrReviewing("8034", "只有已发布/审核中状态的配置可以下线", "Only published or under-review configurations can be taken offline.", ""),
ecoMarketOfflineServerConfigFailed("8035", "下线服务器配置失败,请稍后重试", "Failed to offline server configuration. Please try again later.", ""),
ecoMarketNotPublishedNoOffline("8036", "未发布,无需下线", "Not published; no need to offline.", ""),
ecoMarketRevokeOnlyReviewing("8037", "只有审核中状态的配置可以撤销发布", "Only under-review configurations can be revoked from publication.", ""),
ecoMarketCannotShareFromMarket("8038", "禁止分享生态市场获取的配置", "Sharing configurations obtained from the marketplace is not allowed.", ""),
ecoMarketAgentPageRequiredForShare("8039", "智能体未绑定页面,不能分享为应用页面", "Agent is not bound to a page; cannot share as an app page.", ""),
ecoMarketPageExportFailed("8040", "页面导出失败", "Failed to export page.", ""),
ecoMarketPageArchiveDownloadFailed("8042", "下载页面压缩包失败", "Failed to download page archive.", ""),
ecoMarketPageProjectCreateFailed("8043", "创建页面项目失败", "Failed to create page project.", ""),
ecoMarketPageArchiveUploadFailed("8044", "上传页面压缩包失败", "Failed to upload page archive.", ""),
ecoMarketPagePublishFailed("8045", "发布页面失败", "Failed to publish page.", ""),
ecoMarketAppPageEnableFailed("8046", "应用页面启用失败", "Failed to enable app page.", ""),
ecoMarketDeleteOnlyOwnShare("8047", "只能删除自己分享的配置", "You can only delete configurations you shared.", ""),
//AI 开发自定义页面
customPageAgentTaskInProgress("9010", "Agent正在执行任务请等待当前任务完成后再发送新请求", "Agent is running a task; wait for it to finish before sending another request.", "Agent正在执行任务请等待当前任务完成后再发送新请求;前端全局处理了这个错误码"),
/** 智能体模块内部/防御性:仅英文提示,不做多语言业务文案 */
agentDependencyServiceError("9198", "依赖服务返回错误", "The dependency service returned an error.", "RPC/内部透传"),
// 智能体 Agent 模块92009499
agentWorkflowIdInvalid("9201", "workflowId错误", "Invalid workflowId.", "参数"),
agentWorkflowHasInvalidNodesForPublish("9202", "工作流存在错误节点,不允许发布,请重新试运行", "Workflow has invalid nodes; publishing is not allowed. Re-run and fix.", "工作流"),
agentWorkflowCyclicDependency("9203", "你添加的节点存在工作流循环依赖,请重新选择", "The nodes you added create a cyclic dependency; choose again.", "工作流"),
agentTableIdInvalid("9204", "表ID错误", "Invalid table ID.", "参数"),
agentKnowledgeBaseRemovedOrMissing("9205", "知识库[%s]不存在或已删除,请移除", "Knowledge base [%s] does not exist or was removed; remove it.", "工作流/知识库"),
agentWorkflowNodeIdInvalid("9206", "节点ID错误", "Invalid node ID.", "参数"),
agentWorkflowNotFound("9207", "Workflow不存在", "Workflow does not exist.", "工作流"),
agentIdInvalid("9208", "agentId错误", "Invalid agentId.", "参数"),
agentModelComponentCannotAddManually("9209", "模型组件配置不能手动添加", "Model component cannot be added manually.", "智能体组件"),
agentPluginNotFoundOrUnpublished("9210", "插件不存在或未发布", "Plugin does not exist or is not published.", "组件"),
agentWorkflowNotFoundOrUnpublished("9211", "工作流不存在或未发布", "Workflow does not exist or is not published.", "组件"),
agentMcpConfigIncomplete("9213", "MCP缺少必要配置参数", "MCP is missing required configuration.", "组件"),
agentSkillNotFoundOrUnpublished("9214", "技能不存在或未发布", "Skill does not exist or is not published.", "组件"),
agentModelComponentCannotDelete("9216", "模型组件配置不能删除", "Model component cannot be deleted.", "组件"),
agentBoundModelOffline("9217", "智能体关联大模型已下线,请重新配置", "The bound LLM is offline; reconfigure the agent.", "智能体"),
agentNotPublishedOrOffline("9218", "该智能体未发布或已下架", "This agent is not published or has been taken offline.", "发布"),
agentDataNotFoundWithId("9219", "数据不存在,id=%s", "Data does not exist, id=%s", "数据"),
agentPluginNotFound("9220", "插件不存在", "Plugin does not exist.", "通用"),
agentWorkflowNotFoundSimple("9221", "工作流不存在", "Workflow does not exist.", "通用"),
agentNotFound("9222", "智能体不存在", "Agent does not exist.", "通用"),
agentTableSchemaQueryFailed("9223", "查询表结构定义失败", "Failed to query table schema.", "表结构"),
agentTemplateConfigInvalid("9224", "该模版配置异常,暂时不可用", "This template configuration is invalid and temporarily unavailable.", "模版"),
agentSandboxServerStoppedOrRemoved("9225", "关联的agent服务器已停止或已删除", "The associated agent server has stopped or been removed.", "沙箱/电脑"),
agentSandboxNotFound("9226", "未找到沙盒服务器", "Sandbox server not found.", "沙箱/电脑"),
agentPrivateComputerDeleteForbidden("9227", "私有电脑的智能体不允许在此删除", "Agents on a private computer cannot be deleted here.", "智能体"),
agentKnowledgeIdInvalid("9228", "知识ID错误", "Invalid knowledge ID.", "参数"),
agentPageIdInvalid("9229", "页面ID错误", "Invalid page ID.", "参数"),
agentArgBooleanDefaultInvalid("9230", "参数[%s]类型为Boolean默认值只能为true或false", "Parameter [%s] is Boolean; default must be true or false.", "变量"),
agentArgIntegerDefaultInvalid("9231", "参数[%s]类型为Integer默认值只能为整数", "Parameter [%s] is Integer; default must be an integer.", "变量"),
agentArgNumberDefaultInvalid("9232", "参数[%s]类型为Number默认值只能为数字", "Parameter [%s] is Number; default must be numeric.", "变量"),
agentVariableNameDuplicated("9233", "变量名[%s]重复", "Duplicate variable name [%s].", "变量"),
agentVariableSelectOptionsRequired("9234", "变量[%s]的输入类型为下拉选项,请设置下拉参数配置", "Variable [%s] uses a select input; configure dropdown options.", "变量"),
agentVariablePluginOffline("9235", "变量[%s]引用的插件不存在或已下线", "Plugin referenced by variable [%s] does not exist or is offline.", "变量"),
agentVariablePluginDataInvalid("9236", "变量[%s]引用的插件数据结构异常", "Invalid plugin data structure for variable [%s].", "变量"),
agentVariablePluginOutputEmpty("9237", "变量[%s]引用的插件[%s]的输出参数为空", "For variable [%s], output parameters of referenced plugin [%s] are empty.", "变量"),
agentVariablePluginOptionsMissing("9238", "变量[%s]引用的插件数据结构不符合规缺少options", "Plugin data for variable [%s] is invalid: missing options.", "变量"),
agentVariableWorkflowNotFound("9239", "变量[%s]引用的工作流不存在", "Workflow referenced by variable [%s] does not exist.", "变量"),
agentVariableWorkflowNoOutput("9240", "变量[%s]引用的工作流没有输出参数", "Workflow referenced by variable [%s] has no output parameters.", "变量"),
agentVariableWorkflowOptionsMissing("9241", "变量[%s]引用的工作流输出数据结构不符合规缺少options", "Workflow output data for variable [%s] is invalid: missing options.", "变量"),
agentVariableOptionsMissing("9242", "变量[%s]缺少选项", "Variable [%s] is missing options.", "变量"),
agentComponentNotFoundOrRemoved("9243", "组件不存在或已删除", "Component does not exist or was removed.", "组件"),
agentComponentTypeInvalid("9244", "组件类型错误,请检查是否使用了正确的接口", "Invalid component type; verify you are using the correct API.", "组件"),
agentNotFoundAlt("9245", "Agent不存在", "Agent does not exist.", "智能体"),
agentPublishedOffline("9246", "智能体未发布或已下架", "Agent is not published or has been taken offline.", "发布"),
agentPluginOffline("9247", "插件不存在或已下架", "Plugin does not exist or has been taken offline.", "发布"),
agentWorkflowOffline("9248", "工作流不存在或已下架", "Workflow does not exist or has been taken offline.", "发布"),
agentSkillOffline("9249", "技能不存在或已下架", "Skill does not exist or has been taken offline.", "发布"),
agentSkillDownloadDenied("9250", "无技能下载权限", "No permission to download skills.", "权限"),
agentUnpublishFailedNotPublished("9251", "下架失败,未发布", "Unpublish failed: not published.", "发布"),
agentViewDenied("9252", "无查看权限", "No permission to view.", "权限"),
agentConversationNotFound("9253", "会话不存在", "Conversation does not exist.", "会话"),
agentConversationPermissionDenied("9254", "无智能体会话权限", "No permission for this agent conversation.", "权限"),
agentOfflineOrNotFound("9255", "智能体不存在或已下架", "Agent does not exist or has been taken offline.", "会话"),
agentSelectedNotFound("9256", "选择的智能体不存在", "Selected agent does not exist.", "会话"),
agentScheduledTaskLimitExceeded("9257", "用户在每个智能体进行中的定时任务不能超过%s个", "In-progress scheduled tasks per agent cannot exceed %s.", "定时任务"),
agentOperationDenied("9258", "无操作权限", "Operation not permitted.", "权限"),
agentWebAppNotFound("9259", "网页应用不存在", "Web app does not exist.", "自定义页"),
agentEmbeddingModelDeleteForbidden("9260", "嵌入模型不允许删除", "Embedding model cannot be deleted.", "模型"),
agentApplyIdInvalid("9261", "applyId错误", "Invalid applyId.", "参数"),
agentPublishScopeNotSelected("9262", "未选择发布范围", "Publish scope not selected.", "发布"),
agentPrivateCannotPublishToSquare("9263", "私有电脑的智能体不允许发布到广场", "Agents on a private computer cannot be published to the square.", "发布"),
agentSpaceNotFound("9264", "空间[%s]不存在", "Space [%s] does not exist.", "发布"),
agentSpacePublishDenied("9265", "无空间[%s]发布权限", "No permission to publish to space [%s].", "发布"),
agentSpacePublishReceivingDisabled("9266", "空间[%s]未开启接收发布功能", "Space [%s] has not enabled receiving publications.", "发布"),
agentSkillConfigParseFailed("9267", "技能配置解析失败", "Failed to parse skill configuration.", "技能"),
agentUnpublishFailedAlreadyOffline("9268", "下架失败,未发布或已下架", "Unpublish failed: not published or already offline.", "发布"),
agentUserSpacePublishDenied("9269", "用户无空间发布权限", "User has no permission to publish to spaces.", "发布"),
agentUserPublishDenied("9270", "用户无发布权限", "User has no publish permission.", "发布"),
agentUserNoPersonalSpace("9271", "用户没有个人空间", "User has no personal space.", "发布"),
agentPluginIdInvalid("9272", "pluginId错误", "Invalid pluginId.", "参数"),
agentPluginIdError("9273", "插件ID错误", "Invalid plugin ID.", "参数"),
agentPageIdError("9274", "页面Id错误", "Invalid page ID.", "页面"),
agentPageAgentIdError("9275", "智能体Id错误", "Invalid agent ID.", "页面"),
agentPageEnvInvalid("9276", "环境错误", "Invalid environment.", "页面"),
agentPageDatasourceInvalid("9277", "页面数据源错误", "Invalid page data source.", "页面"),
agentAppAccessDenied("9279", "无应用访问权限", "No permission to access the app.", "权限"),
agentPageSpacePermissionDenied("9280", "用户无页面所在空间权限", "User has no permission for the page's space.", "权限"),
agentAgentPermissionDenied("9281", "用户无智能体权限", "User has no permission for this agent.", "权限"),
agentPageNotBoundToAgent("9282", "调用的智能体未绑定对应页面", "The invoked agent is not bound to the corresponding page.", "页面"),
agentPageDatasourceNotFound("9283", "请求的数据源不存在", "Requested data source does not exist.", "页面"),
agentPluginNotPublished("9284", "插件ID错误或未发布", "Invalid plugin ID or plugin not published.", "页面"),
agentPluginExecuteDenied("9285", "无插件执行权限", "No permission to execute plugin.", "权限"),
agentExportFileGenerationFailed("9286", "生成导出文件失败", "Failed to generate export file.", "导入导出"),
agentPermissionDeniedGeneric("9287", "没有权限", "Permission denied.", "权限"),
agentRelatedOfflineOrNotFound("9288", "相关智能体不存在或已下架", "Related agent does not exist or is offline.", "API"),
agentConversationIdInvalid("9289", "错误的conversationId", "Invalid conversationId.", "API"),
agentTempConversationNotFound("9290", "临时会话不存在", "Temporary conversation does not exist.", "临时会话"),
agentTempConversationExpired("9291", "临时会话已过期", "Temporary conversation has expired.", "临时会话"),
agentClientDisabled("9292", "智能体客户端已停用", "Agent client is disabled.", "沙箱"),
agentComputerServerDisabled("9293", "会话所在智能体电脑服务端已停用", "Agent computer server for this session is disabled.", "沙箱"),
agentClientOffline("9294", "智能体客户端已离线", "Agent client is offline.", "沙箱"),
agentSandboxCapacityExceeded("9295", "当前过于火爆,请稍后再试", "Service is busy. Please try again later.", "沙箱"),
agentNotPublishedOrOfflineAlt("9296", "未发布或已下架", "Not published or offline.", "收藏"),
agentPublishIdInvalid("9297", "发布ID错误", "Invalid publish ID.", "发布"),
agentMcpServiceNotFoundOrDenied("9298", "选择的MCP服务不存在或没有权限", "Selected MCP service does not exist or access denied.", "MCP"),
agentMcpToolNotFoundOrDenied("9299", "选择的工具不存在或没有权限", "Selected tool does not exist or access denied.", "MCP"),
agentPluginRequiredParamMissing("9300", "请填写必要参数[%s],便于获取返回参数", "Fill required parameter [%s] to obtain return values.", "插件"),
agentPluginOfflineReplaceRequired("9303", "插件[%s]未发布或已下线,请更换其他适合的插件", "Plugin [%s] is not published or is offline; choose another plugin.", "插件"),
agentPluginOfflineSimple("9304", "该插件未发布或已下线", "This plugin is not published or is offline.", "插件"),
agentPluginSpacePermissionDenied("9305", "当前空间没有插件权限", "No plugin permission in this space.", "插件"),
agentSessionNotFound("9306", "未找到当前会话", "Current session not found.", "文件"),
agentResourceAccessDenied("9307", "无权访问当前资源", "No permission to access this resource.", "文件"),
agentRequiredParamEmpty("9308", "必传参数为空", "Required parameter is empty.", "参数"),
agentContainerServiceCallFailed("9309", "容器服务调用失败", "Container service call failed.", "容器"),
agentWorkflowMissingStartNode("9313", "工作流缺少开始节点", "Workflow is missing a start node.", "工作流"),
agentWorkflowMissingEndNode("9314", "工作流缺少结束节点", "Workflow is missing an end node.", "工作流"),
agentWorkflowSelfReference("9315", "工作流不能引用自己", "Workflow cannot reference itself.", "工作流"),
agentWorkflowNotPublished("9316", "工作流未发布", "Workflow is not published.", "工作流"),
agentWorkflowPluginPermissionDenied("9317", "没有插件权限", "No plugin permission.", "工作流"),
agentWorkflowCannotDeleteTerminalNodes("9319", "不能删除起始节点和结束节点", "Cannot delete start or end nodes.", "工作流"),
agentWorkflowCannotDeleteLoopTerminalNodes("9320", "不能删除循环起始节点和结束节点", "Cannot delete loop start or end nodes.", "工作流"),
agentWorkflowStartNodeNotFound("9321", "未找到起始节点", "Start node not found.", "工作流"),
agentWorkflowCannotCopyTerminalNodes("9322", "不能复制起始节点和结束节点", "Cannot copy start or end nodes.", "工作流"),
agentWorkflowSpacePermissionDenied("9323", "当前空间没有工作流[%s]的权限", "No permission for workflow [%s] in this space.", "工作流"),
agentWorkflowNodeCycleEdge("9367", "节点<%s>与节点<%s>存在循环连线", "Cycle edge between node <%s> and node <%s>.", "工作流"),
agentSkillUploadFileRequired("9327", "请选择要上传的文件", "Please select a file to upload.", "技能"),
agentSkillFileFormatInvalid("9329", "文件必须是zip/.skill格式或者为SKILL.md文件", "File must be .zip/.skill or SKILL.md.", "技能"),
agentSkillTargetSpaceRequired("9330", "请选择目标空间", "Please select a target space.", "技能"),
agentSkillZipFormatInvalid("9331", "ZIP 文件格式错误或不兼容,请使用标准的 ZIP 压缩格式重新打包文件。错误详情: %s", "Invalid or incompatible ZIP; repack with standard ZIP. Details: %s", "技能"),
agentSkillFileFormatError("9332", "文件格式错误,请上传正确的技能文件。错误详情: %s", "Invalid file format; upload a valid skill file. Details: %s", "技能"),
agentSkillFileSizeExceeded100m("9333", "文件大小不能超过 100M", "File size cannot exceed 100 MB.", "技能"),
agentSkillReadSkillMdFailed("9334", "读取 SKILL.md 文件失败", "Failed to read SKILL.md.", "技能"),
agentSkillMdRequired("9335", "技能包中缺少必需的 SKILL.md 文件", "Required SKILL.md is missing from the skill package.", "技能"),
agentSkillMdNameDescRequired("9336", "SKILL.md 文件中必须包含 name 和 description 信息", "SKILL.md must include name and description.", "技能"),
agentSkillTemplateReadFailed("9337", "读取技能模板失败: %s", "Failed to read skill template: %s", "技能"),
agentSkillNotFoundOrDenied("9338", "技能不存在或无权限使用", "Skill does not exist or access denied.", "技能"),
agentSkillFilePathInvalid("9339", "filePath 无效", "Invalid filePath.", "技能"),
agentSkillUploadProcessFailed("9340", "处理上传文件失败: %s", "Failed to process uploaded file: %s", "技能"),
agentSkillMdDeleteForbidden("9343", "SKILL.md 文件不允许删除", "SKILL.md cannot be deleted.", "技能"),
agentSkillDirRenameFailed("9344", "目录重命名失败,源目录不存在或为空", "Failed to rename directory: source missing or empty.", "技能"),
agentSkillFileRenameFailed("9345", "文件重命名失败,源文件不存在", "Failed to rename file: source does not exist.", "技能"),
agentSkillRenameSourceMissing("9346", "缺少文件重命名的源文件名", "Source file name for rename is missing.", "技能"),
agentSkillUnknownFileOperation("9347", "未知的文件操作类型", "Unknown file operation type.", "技能"),
agentSkillSingleFileSizeExceeded("9348", "单个文件大小不能超过 100M", "Single file size cannot exceed 100 MB.", "技能"),
agentSkillExportFailed("9349", "导出技能失败", "Failed to export skill.", "技能"),
agentDefaultModelDeleteForbidden("9350", "默认模型不允许删除", "Default model cannot be deleted.", "模型"),
agentModelNotFound("9351", "模型不存在", "Model does not exist.", "模型"),
agentModelJsonInvalid("9352", "模型返回的JSON格式不正确请检查提示词", "Invalid JSON from model; check your prompt.", "模型"),
agentWorkspaceCreateFailed("9353", "创建工作空间失败", "Failed to create workspace.", "工作空间"),
agentSkillZipPackFailed("9354", "打包技能 zip 失败", "Failed to pack skill zip.", "工作空间"),
agentSkillFilePushFailed("9355", "推送技能文件失败", "Failed to push skill files.", "工作空间"),
agentSkillAgentPackFailed("9356", "打包 skill/agent 失败", "Failed to pack skill/agent.", "工作空间"),
agentCodeExecuteUnavailable("9357", "代码执行接口暂不可用,请稍后再试", "Code execution is temporarily unavailable. Try again later.", "代码执行"),
agentPluginTypeInvalid("9358", "插件类型错误", "Invalid plugin type.", "插件执行"),
agentSkillNotFound("9359", "技能不存在", "Skill does not exist.", "技能"),
agentOpenapiPluginIdInvalid("9360", "pluginId 错误", "Invalid pluginId.", "OpenAPI 英文"),
agentOpenapiExecutePermissionDenied("9361", "无执行权限", "Execute permission denied.", "OpenAPI 英文"),
agentOpenapiModelIdInvalid("9362", "model id 错误", "Invalid model id.", "OpenAPI 英文"),
agentOpenapiConversationIdInvalid("9363", "conversationId 错误", "Invalid conversationId.", "OpenAPI 英文"),
agentOpenapiPluginNotFound("9364", "Plugin不存在", "Plugin does not exist.", "英文资源名"),
agentOpenapiSkillNotFound("9366", "Skill不存在", "Skill does not exist.", "英文资源名"),
/** 沙箱 / 电脑连接与状态 */
agentComputerConnectFailed("9371", "智能体电脑连接失败", "Failed to connect to agent computer.", "沙箱"),
agentStatusQueryResponseInvalid("9372", "状态查询返回数据结构异常", "Invalid status query response structure.", "沙箱"),
agentComputerStartupFailed("9373", "智能体电脑启动失败,请重试", "Failed to start agent computer. Please retry.", "沙箱"),
/** 助手 / 表查询(与「表结构定义」文案区分) */
agentAssistantTableSchemaQueryFailed("9375", "查询表结构失败", "Failed to query table schema.", "助手"),
/** 工作流节点执行 */
agentWorkflowMcpReferenceRemoved("9377", "节点引用的MCP服务已被删除", "MCP service referenced by the node has been deleted.", "工作流"),
agentWorkflowLoopNotFullyConnected("9378", "循环节点未完整连接", "Loop nodes are not fully connected.", "工作流"),
agentWorkflowLoopMaxCountInvalid("9379", "循环节点最大循环次数不能小于等于0", "Loop max iterations must be greater than 0.", "工作流"),
agentWorkflowConditionBranchesEmpty("9380", "条件分支列表不能为空", "Condition branch list cannot be empty.", "工作流"),
pay_order_not_found("9381", "支付订单不存在", "Payment order not found", "支付"),
pay_developer_account_not_found("9382", "开发者账户信息不存在", "Developer account not found", "支付");
/**
* 错误码
*/
private final String code;
/**
* 中文提示模板(与 {@link String#format} 占位一致)
*/
private final String messageZh;
/**
* 英文提示模板
*/
private final String messageEn;
/**
* 分类备注,方便看异常定义,不参与错误提示
*/
private final String remark;
BizExceptionCodeEnum(String code, String messageZh, String messageEn, String remark) {
this.code = code;
this.messageZh = messageZh;
this.messageEn = messageEn;
this.remark = remark;
}
}

View File

@@ -0,0 +1,36 @@
package com.xspaceagi.system.spec.exception;
/**
* 知识库异常
*/
public class ComposeException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "Compose";
public ComposeException(String code, String message) {
super(code, message);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static ComposeException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new ComposeException(codeEnum.getCode(), errorMessage);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,36 @@
package com.xspaceagi.system.spec.exception;
/**
* 知识库异常
*/
public class CustomPageException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "CustomPage";
public CustomPageException(String code, String message) {
super(code, message);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static CustomPageException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new CustomPageException(codeEnum.getCode(), errorMessage);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,36 @@
package com.xspaceagi.system.spec.exception;
/**
* 生态市场异常
*/
public class EcoMarketException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "EcoMarket";
public EcoMarketException(String code, String message) {
super(code, message);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static EcoMarketException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new EcoMarketException(codeEnum.getCode(), errorMessage);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,48 @@
package com.xspaceagi.system.spec.exception;
import com.xspaceagi.system.spec.common.RequestContext;
public interface IBizExceptionCodeEnum {
String getCode();
/**
* 中文错误信息模板(与 {@link String#format} 占位一致)
*/
String getMessageZh();
/**
* 英文错误信息模板
*/
String getMessageEn();
/**
* 分类备注,方便看异常定义,不参与错误提示
*/
String getRemark();
/**
* 按当前请求 {@link RequestContext#getLang()} 选择模板:仅 {@code zh-CN}(忽略大小写)使用中文,其余(含未设置 lang使用英文。
*/
default String pickMessageTemplateForRequest() {
RequestContext<?> ctx = RequestContext.get();
if (ctx != null) {
String lang = ctx.getLang();
if (lang != null && !lang.isBlank() && "zh-CN".equalsIgnoreCase(lang.trim())) {
return getMessageZh();
}
}
return getMessageEn();
}
/**
* 使用 {@link #pickMessageTemplateForRequest()} 的模板做 {@link String#format}。
*/
default String formatMessage(Object... params) {
String tpl = pickMessageTemplateForRequest();
if (params == null || params.length == 0) {
return tpl;
}
return String.format(tpl, params);
}
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.exception;
import lombok.Getter;
/**
* 通用抽象
*/
public abstract class KindlyException extends RuntimeException {
@Getter
private final String code;
private String displayCode;
public KindlyException(String code, String message) {
super(message);
this.code = code;
}
public KindlyException(String code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
public String getDisplayCode() {
if (null == getModule()) {
return this.code;
}
return getModule() + this.code;
}
/**
* 模块名称简拼
*
* @return
*/
public abstract String getModule();
}

View File

@@ -0,0 +1,51 @@
package com.xspaceagi.system.spec.exception;
/**
* 知识库异常
*/
public class KnowledgeException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "Knowledge";
public KnowledgeException(String code, String message) {
super(code, message);
}
public KnowledgeException(String code, String message, Throwable cause) {
super(code, message, cause);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static KnowledgeException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new KnowledgeException(codeEnum.getCode(), errorMessage);
}
/**
* 根据定义好的异常枚举,构建异常信息(带原始异常)
*
* @param codeEnum 异常枚举
* @param cause 原始异常
* @return 异常
*/
public static KnowledgeException build(BizExceptionCodeEnum codeEnum, Throwable cause) {
return new KnowledgeException(codeEnum.getCode(), codeEnum.formatMessage(), cause);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,36 @@
package com.xspaceagi.system.spec.exception;
/**
* 日志平台异常
*/
public class LogPlatformException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "LogPlatform";
public LogPlatformException(String code, String message) {
super(code, message);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static LogPlatformException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new LogPlatformException(codeEnum.getCode(), errorMessage);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,15 @@
package com.xspaceagi.system.spec.exception;
/**
* 资源权限异常
*/
public class ResourcePermissionException extends RuntimeException {
public ResourcePermissionException(String message) {
super(message);
}
public ResourcePermissionException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,26 @@
package com.xspaceagi.system.spec.exception;
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
import lombok.Getter;
public class SpacePermissionException extends RuntimeException {
@Getter
private String code = ErrorCodeEnum.PERMISSION_DENIED.getCode();
public SpacePermissionException() {
super("您没有此空间数据的访问权限!");
}
public SpacePermissionException(String message) {
super(message);
}
public SpacePermissionException(String message, Throwable cause) {
super(message, cause);
}
public SpacePermissionException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,35 @@
package com.xspaceagi.system.spec.exception;
/**
* 系统管理异常,如人员,机构,角色等管理异常
*/
public class SystemManagerException extends KindlyException {
/**
* 默认配置前缀
*/
private static final String DISPLAY_CODE = "SystemManager";
public SystemManagerException(String code, String message) {
super(code, message);
}
/**
* 根据定义好的异常枚举,构建异常信息
*
* @param codeEnum 异常枚举
* @param params 占位参数
* @return 异常
*/
public static SystemManagerException build(BizExceptionCodeEnum codeEnum, Object... params) {
String errorMessage = codeEnum.formatMessage(params);
return new SystemManagerException(codeEnum.getCode(), errorMessage);
}
@Override
public String getModule() {
return DISPLAY_CODE;
}
}

View File

@@ -0,0 +1,66 @@
package com.xspaceagi.system.spec.file;
import org.springframework.core.io.FileSystemResource;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FileSystemMultipartFile implements MultipartFile {
private final File file;
private final String name;
private final String contentType;
public FileSystemMultipartFile(File file, String name, String contentType) {
this.file = file;
this.name = name;
this.contentType = contentType;
}
@Override
public String getName() {
return name;
}
@Override
public String getOriginalFilename() {
return name;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return file.length() == 0;
}
@Override
public long getSize() {
return file.length();
}
@Override
public byte[] getBytes() throws IOException {
return java.nio.file.Files.readAllBytes(file.toPath());
}
@Override
public InputStream getInputStream() throws IOException {
return new FileInputStream(file);
}
@Override
public org.springframework.core.io.Resource getResource() {
return new FileSystemResource(file);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
java.nio.file.Files.copy(file.toPath(), dest.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
}
}

View File

@@ -0,0 +1,65 @@
package com.xspaceagi.system.spec.file;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InMemoryMultipartFile implements MultipartFile {
private final String name;
private final String originalFilename;
private final String contentType;
private final byte[] content;
public InMemoryMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
this.name = name;
this.originalFilename = originalFilename;
this.contentType = contentType;
this.content = (content != null ? content : new byte[0]);
}
@Override
public String getName() {
return name;
}
@Override
public String getOriginalFilename() {
return originalFilename;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return content.length == 0;
}
@Override
public long getSize() {
return content.length;
}
@Override
public byte[] getBytes() {
return content;
}
@Override
public InputStream getInputStream() {
return new ByteArrayInputStream(content);
}
@Override
public void transferTo(java.io.File dest) throws IOException {
try (java.io.FileOutputStream fos = new java.io.FileOutputStream(dest)) {
fos.write(content);
}
}
}

View File

@@ -0,0 +1,27 @@
package com.xspaceagi.system.spec.id;
/**
* ID生成器
*/
public interface IdGenerator {
/**
* 生成唯一ID
*/
long nextId();
/**
* 生成唯一ID,指定位数
*/
long nextId(int digits);
/**
* 生成唯一ID字符串
*/
String nextIdStr();
/**
* 生成唯一ID字符串,指定位数
*/
String nextIdStr(int digits);
}

View File

@@ -0,0 +1,82 @@
package com.xspaceagi.system.spec.id;
import org.springframework.stereotype.Component;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import jakarta.annotation.PostConstruct;
/**
* 基于雪花算法的分布式ID生成器
*/
@Component
public class SnowflakeIdGenerator implements IdGenerator {
// 数据中心ID目前单实例不配置直接写死
// @Value("${id.snowflake.datacenter-id:1}")
private long datacenterId = 1L;
// 数据中心内的机器/实例ID目前单实例不配置直接写死
// @Value("${id.snowflake.worker-id:1}")
private long workerId = 1L;
private Snowflake snowflake;
@PostConstruct
public void init() {
this.snowflake = IdUtil.getSnowflake(workerId, datacenterId);
}
@Override
public long nextId() {
return snowflake.nextId();
}
/**
* 生成指定位数的ID
* 注意:位数越少,重复风险越高!
*
* 建议:
* - 19位完全不重复原始雪花ID
* - 16-18位截取后N位基本不重复
* - 13-15位中等并发场景可用有一定重复风险
* - ≤12位高并发场景下重复概率较高不推荐
*/
@Override
public long nextId(int digits) {
if (digits < 1 || digits > 19) {
throw new IllegalArgumentException("Bit count must be between 1 and 19");
}
long id = snowflake.nextId();
if (digits >= 19) {
return id;
}
id = Math.abs(id);
String idStr = String.valueOf(id);
// 如果本身不足指定位数,直接返回
if (idStr.length() <= digits) {
return id;
}
// 截取后N位保留时间戳的后部分+序列号)
String truncated = idStr.substring(idStr.length() - digits);
return Long.parseLong(truncated);
}
@Override
public String nextIdStr() {
return snowflake.nextIdStr();
}
@Override
public String nextIdStr(int digits) {
long id = nextId(digits);
return String.valueOf(id);
}
}

View File

@@ -0,0 +1,35 @@
package com.xspaceagi.system.spec.jackson;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import java.io.IOException;
import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class FixedLocalDateTimeDeserializer extends LocalDateTimeDeserializer {
private static final DateTimeFormatter DEFAULT_FORMATTER;
public FixedLocalDateTimeDeserializer(DateTimeFormatter formatter) {
super(formatter);
}
protected LocalDateTime _fromString(JsonParser p, DeserializationContext ctxt, String string0) throws IOException {
String string = string0.trim();
if (string.length() == 0) {
return (LocalDateTime)this._fromEmptyString(p, ctxt, string);
} else {
try {
return string.length() > 10 && string.charAt(10) == 'T' ? LocalDateTime.parse(string, DEFAULT_FORMATTER) : LocalDateTime.parse(string, this._formatter);
} catch (DateTimeException var6) {
return (LocalDateTime)this._handleDateTimeException(ctxt, var6, string);
}
}
}
static {
DEFAULT_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
}
}

View File

@@ -0,0 +1,31 @@
package com.xspaceagi.system.spec.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdKeySerializers;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FixedNumberKeySerializer extends StdKeySerializers.Default {
private static final Logger log = LoggerFactory.getLogger(FixedNumberKeySerializer.class);
private Class<?> cls;
public FixedNumberKeySerializer(int typeId, Class<?> type) {
super(typeId, type);
this.cls = type;
}
public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
if (this.isNumber() && !(value instanceof Number)) {
log.warn("javaType:{},valueType:{} 不匹配,请检查!", this.cls.getName(), value.getClass().getName());
g.writeFieldName(value.toString());
} else {
super.serialize(value, g, provider);
}
}
private boolean isNumber() {
return this._typeId == 5 || this._typeId == 6;
}
}

View File

@@ -0,0 +1,126 @@
package com.xspaceagi.system.spec.jackson;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import org.springframework.util.ObjectUtils;
public class JacksonBuilder {
private ObjectMapper objectMapper;
private final JacksonProperties jacksonProperties;
private final SimpleModule customModule;
private JacksonBuilder() {
this(new JacksonProperties());
}
private JacksonBuilder(JacksonProperties jacksonProperties) {
this.jacksonProperties = jacksonProperties;
this.customModule = new SimpleModule();
this.defaultObjectMapper();
}
private void defaultObjectMapper() {
DefaultSerializerProvider provider = new DefaultSerializerProvider.Impl();
provider.setNullKeySerializer(new NullKeySerializer());
this.customModule.addKeySerializer(Integer.class, new FixedNumberKeySerializer(5, Integer.class));
this.customModule.addKeySerializer(Long.class, new FixedNumberKeySerializer(6, Integer.class));
this.objectMapper = (new ObjectMapper()).setSerializationInclusion(Include.NON_NULL).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false).setVisibility(PropertyAccessor.ALL, Visibility.ANY).registerModule(this.javaTimeModule()).registerModule(new Jdk8Module());
String utilDateFormat = this.jacksonProperties.getUtilDateFormat();
if (!ObjectUtils.isEmpty(utilDateFormat)) {
this.objectMapper.setDateFormat(new SimpleDateFormat(utilDateFormat));
}
}
private Module javaTimeModule() {
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(this.localDateTimeSerializer());
module.addSerializer(this.localDateSerializer());
module.addSerializer(this.localTimeSerializer());
module.addDeserializer(LocalDateTime.class, this.fixedLocalDateTimeDeserializer());
module.addDeserializer(LocalDate.class, this.localDateDeserializer());
module.addDeserializer(LocalTime.class, this.localTimeDeserializer());
return module;
}
private LocalDateTimeSerializer localDateTimeSerializer() {
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getDateTimeFormat()));
}
private FixedLocalDateTimeDeserializer fixedLocalDateTimeDeserializer() {
return new FixedLocalDateTimeDeserializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getDateTimeFormat()));
}
private LocalDateSerializer localDateSerializer() {
return new LocalDateSerializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getDateFormat()));
}
private LocalTimeSerializer localTimeSerializer() {
return new LocalTimeSerializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getTimeFormat()));
}
private LocalDateTimeDeserializer localDateTimeDeserializer() {
return new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getDateTimeFormat()));
}
private LocalDateDeserializer localDateDeserializer() {
return new LocalDateDeserializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getDateFormat()));
}
private LocalTimeDeserializer localTimeDeserializer() {
return new LocalTimeDeserializer(DateTimeFormatter.ofPattern(this.jacksonProperties.getTimeFormat()));
}
public JacksonBuilder writeNull() {
this.objectMapper.setSerializationInclusion(Include.ALWAYS);
return this;
}
public JacksonBuilder withJavaType() {
this.objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, DefaultTyping.NON_FINAL, As.PROPERTY);
return this;
}
public JacksonBuilder addSerializer(JsonSerializer<?> ser) {
this.customModule.addSerializer(ser);
return this;
}
public ObjectMapper build() {
this.objectMapper.registerModule(this.customModule);
return this.objectMapper;
}
public static JacksonBuilder builder() {
return new JacksonBuilder();
}
public static JacksonBuilder builder(JacksonProperties jacksonProperties) {
return new JacksonBuilder(jacksonProperties);
}
}

View File

@@ -0,0 +1,43 @@
package com.xspaceagi.system.spec.jackson;
public class JacksonProperties {
private String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
private String dateFormat = "yyyy-MM-dd";
private String timeFormat = "HH:mm:ss";
private String utilDateFormat;
public JacksonProperties() {
}
public String getDateTimeFormat() {
return this.dateTimeFormat;
}
public void setDateTimeFormat(String dateTimeFormat) {
this.dateTimeFormat = dateTimeFormat;
}
public String getDateFormat() {
return this.dateFormat;
}
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
public String getTimeFormat() {
return this.timeFormat;
}
public void setTimeFormat(String timeFormat) {
this.timeFormat = timeFormat;
}
public String getUtilDateFormat() {
return this.utilDateFormat;
}
public void setUtilDateFormat(String utilDateFormat) {
this.utilDateFormat = utilDateFormat;
}
}

View File

@@ -0,0 +1,110 @@
package com.xspaceagi.system.spec.jackson;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
public class JsonSerializeUtil {
// 包含类型信息的ObjectMapper
private static ObjectMapper objectMapper;
// 不包含类型信息的ObjectMapper
private static ObjectMapper objectMapperWithoutType;
private static final LinkedHashMap<String, String> PACKAGE_MAP = new LinkedHashMap<String, String>() {{
put("com.xspaceagi.platform.ui.web.dto", "com.xspaceagi.system.web.dto");
put("com.xspaceagi.domain.log", "com.xspaceagi.system.domain.log");
put("com.xspaceagi.platform", "com.xspaceagi.system");
}};
static {
objectMapper = JacksonBuilder.builder(new JacksonProperties()).withJavaType().build();
objectMapperWithoutType = JacksonBuilder.builder(new JacksonProperties()).build();
}
/**
* 反序列化JSON字符串为对象包含类型信息@class字段
*/
public static Object parseObjectGeneric(String json) {
if (json == null) {
return null;
}
try {
return objectMapper.readValue(json, Object.class);
} catch (IOException e) {
try {
String newJson = json;
for (Map.Entry<String, String> entry : PACKAGE_MAP.entrySet()) {
newJson = newJson.replace(entry.getKey(), entry.getValue());
}
return objectMapper.readValue(newJson, Object.class);
} catch (IOException retryException) {
throw new RuntimeException("反序列化失败,原始异常: " + e.getMessage() +
", 迁移后异常: " + retryException.getMessage(), e);
}
}
}
/**
* 序列化对象为JSON字符串包含类型信息@class字段
*/
public static String toJSONStringGeneric(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 序列化对象为JSON字符串不包含类型信息@class字段
*/
public static String toJSONString(Object obj) {
if (obj == null) {
return null;
}
try {
return objectMapperWithoutType.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException("序列化失败: " + e.getMessage(), e);
}
}
/**
* 反序列化JSON字符串为指定类型的对象用于不包含类型信息的JSON
*/
public static <T> T parseObject(String json, Class<T> clazz) {
if (json == null) {
return null;
}
try {
return objectMapperWithoutType.readValue(json, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException("反序列化失败: " + e.getMessage(), e);
}
}
/**
* 反序列化JSON字符串为指定类型的对象用于不包含类型信息的JSON支持泛型
*/
public static <T> T parseObject(String json, TypeReference<T> typeReference) {
if (json == null) {
return null;
}
try {
return objectMapperWithoutType.readValue(json, typeReference);
} catch (JsonProcessingException e) {
throw new RuntimeException("反序列化失败: " + e.getMessage(), e);
}
}
public static Object deepCopy(Object obj) {
return parseObjectGeneric(toJSONStringGeneric(obj));
}
}

View File

@@ -0,0 +1,23 @@
package com.xspaceagi.system.spec.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.NumberType;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.NumberSerializers;
import java.io.IOException;
public class LongToStringSerializer extends NumberSerializers.Base<Object> {
public LongToStringSerializer() {
super(Long.class, NumberType.LONG, "number");
}
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
long number = (Long)value;
if (number >= 10000000000000000L) {
gen.writeString(number + "");
} else {
gen.writeNumber(number);
}
}
}

View File

@@ -0,0 +1,24 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.xspaceagi.system.spec.jackson;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.Objects;
public class NullKeySerializer extends JsonSerializer {
public NullKeySerializer() {
}
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (Objects.isNull(value)) {
gen.writeFieldName("null");
}
}
}

View File

@@ -0,0 +1,48 @@
package com.xspaceagi.system.spec.mail;
import com.xspaceagi.system.spec.enums.ErrorCodeEnum;
import com.xspaceagi.system.spec.exception.BizException;
import com.xspaceagi.system.spec.exception.BizExceptionCodeEnum;
import org.apache.commons.lang3.StringUtils;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
public class MailSender {
public static void sendEmail(String host, String port, String username, String password, String toAddress, String subject, String message) {
if (StringUtils.isBlank(host)) {
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.systemMailServiceNotConfigured);
}
// 设置邮件服务器属性
Properties properties = new Properties();
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", port);
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.ssl.enable", "true");
// 创建会话对象
Session session = Session.getInstance(properties, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
// 创建邮件消息
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(username));
InternetAddress[] toAddresses = {new InternetAddress(toAddress)};
msg.setRecipients(Message.RecipientType.TO, toAddresses);
msg.setSubject(subject);
msg.setSentDate(new java.util.Date());
msg.setText(message);
// 发送邮件
Transport.send(msg);
} catch (MessagingException e) {
throw BizException.of(ErrorCodeEnum.INVALID_PARAM, BizExceptionCodeEnum.systemMailSendFailed);
}
}
}

View File

@@ -0,0 +1,58 @@
package com.xspaceagi.system.spec.page;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
public class ColumnExt implements Serializable {
/**
* 列固定设置
*/
private String fixed;
/**
* 是否可见
*/
private boolean visible = true;
/**
* 列的副标题
*/
private String subLabel;
/**
* 列宽
*/
private String width;
/**
* 列宽最小值
*/
private String minWidth;
/**
* 是否允许自定义
*/
private boolean settable = true;
/**
* 对齐 'left' | 'center' | 'right'
*/
private String align;
/**
* 组件格式化类型:日期dateTime、数量quantity)、单价(unitPrice)、金额(amount)
*/
private String formatter;
/**
* 字段提示信息
*/
private String tips;
/**
* 超长则自动省略号隐藏,hover提示
*/
private Boolean ellipsis;
}

View File

@@ -0,0 +1,31 @@
package com.xspaceagi.system.spec.page;
import lombok.Data;
import java.io.Serializable;
/**
* 筛选字段
*
* @author soddy
*/
@Data
public class ComparisonExpression implements Serializable {
/**
* 字段
*/
private String column;
/**
* 筛选方式 ,比如: "=",">"
*/
private String operator;
/**
* 字段值
*/
private Object value;
}

View File

@@ -0,0 +1,147 @@
package com.xspaceagi.system.spec.page;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.xspaceagi.system.spec.utils.Pojo2MapUtil;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 列表查询参数
*
* @author soddy
*/
@Data
@Slf4j
public class PageQueryParamVo implements Serializable {
/**
* 租户id,显示传递
*/
private Long tenantId;
/**
* 是否查询明细表
*/
private boolean queryDetailFlag = false;
/**
* 排序字段
*/
private List<OrderItem> orderItemList;
/**
* 列筛选字段条件,不是查询条件
*/
private List<ComparisonExpression> comparisonExpressionList;
/**
* 页码,页大小,位置偏移定义
*/
private PageQueryDto pageQueryDto;
/**
* 抬头筛选条件
*/
private Map<String, Object> queryMap = new HashMap<>(0);
public PageQueryParamVo(long pageNo, long pageSize) {
this.pageQueryDto = new PageQueryDto(pageNo, pageSize);
}
/**
* request请求条件,转换为后端查询对象map
* <p>和前端对象隔离开,参数(名称)等字段定义互不影响</p>
*
* @param superPage 公共属性
*/
public <T> PageQueryParamVo(PageQueryVo<T> superPage) {
PageQueryParamVo pageQueryParamVo = new PageQueryParamVo(superPage.getCurrent(), superPage.getPageSize());
pageQueryParamVo.setComparisonExpressionList(superPage.getFilters());
pageQueryParamVo.setOrderItemList(superPage.getOrders());
Map<String, Object> queryMap = Pojo2MapUtil.object2Map(superPage.getQueryFilter());
pageQueryParamVo.setQueryMap(queryMap);
this.pageQueryDto = new PageQueryDto(superPage.getCurrent(), superPage.getPageSize());
this.comparisonExpressionList = superPage.getFilters();
this.orderItemList = superPage.getOrders();
this.queryMap = queryMap;
}
public Long getPageNo() {
return this.pageQueryDto.pageNo;
}
public Long getPageSize() {
return this.pageQueryDto.pageSize;
}
public Long getStartIndex() {
return this.pageQueryDto.startIndex;
}
/**
* 转换为查询条件mapper
* <p>不使用operator来动态控制,后端</p>
*
* @return 查询条件
*/
public Map<String, Object> convertQueryFilterParamMap() {
Map<String, Object> queryMap = new HashMap<>(8);
if (null == comparisonExpressionList || comparisonExpressionList.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("列筛选条件为空,继续组装抬头查询条件");
}
} else {
//列筛选条件
queryMap = new HashMap<>(this.comparisonExpressionList.size());
for (ComparisonExpression item : this.comparisonExpressionList) {
queryMap.put(item.getColumn(), item.getValue());
}
}
//抬头查询条件,追加到map里
queryMap.putAll(this.queryMap);
return queryMap;
}
@Getter
@Setter
public static class PageQueryDto {
/**
* 当前页码
*/
private final Long pageNo;
/**
* 页大小
*/
private Long pageSize;
/**
* 偏移位置
*/
private Long startIndex;
public PageQueryDto(long pageNo, long pageSize) {
if (pageNo <= 0) {
this.pageNo = 1L;
} else {
this.pageNo = pageNo;
}
this.pageSize = pageSize;
this.startIndex = (this.pageNo - 1) * this.pageSize;
}
}
}

View File

@@ -0,0 +1,52 @@
package com.xspaceagi.system.spec.page;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 分页查询VO
* </p>
*/
@Getter
@Setter
@Schema(description = "分页查询VO")
public class PageQueryVo<T> {
@Schema(description = "分页查询过滤条件", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private T queryFilter;
@Schema(description = "当前页", requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "1", example = "1")
private Long current = 1L;
@Schema(description = "分页pageSize", requiredMode = Schema.RequiredMode.NOT_REQUIRED, defaultValue = "10", example = "10")
private Long pageSize = 10L;
/**
* 排序字段信息,可空,一般没有默认为创建时间排序
*/
@Schema(description = "排序字段信息,可空,一般没有默认为创建时间排序", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private List<OrderItem> orders = new ArrayList<>();
/**
* 列的筛选条件,可空
*/
@Schema(description = "列的筛选条件,可空", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private List<ComparisonExpression> filters = new ArrayList<>();
/**
* 表格的列信息,可空
*/
@Schema(description = "表格的列信息,可空", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private List<SuperTableColumn> columns = new ArrayList<>();
}

View File

@@ -0,0 +1,61 @@
package com.xspaceagi.system.spec.page;
import java.util.Objects;
/**
* 给页码,页大小,计算开始索引,结束索引,用于mysql查询limit使用
*/
public class PageUtils {
/**
* 获取开始索引
*
* @param pageNum 页码
* @param pageSize 页大小
* @return 开始索引
*/
public static long getStartIndex(long pageNum, long pageSize) {
if (Objects.isNull(pageNum) || pageNum < 1) {
pageNum = 1;
}
if (Objects.isNull(pageSize) || pageSize < 1) {
pageSize = 100;
}
return (pageNum - 1) * pageSize;
}
/**
* 获取结束索引
*
* @param pageNum 页码
* @param pageSize 页大小
* @return 结束索引
*/
public static long getEndIndex(long pageNum, long pageSize) {
if (Objects.isNull(pageNum) || pageNum < 1) {
pageNum = 1;
}
if (Objects.isNull(pageSize) || pageSize < 1) {
pageSize = 100;
}
return (pageNum - 1) * pageSize + pageSize;
}
/**
* 根据总条数,和页大小,获取 页数 pages
*
* @param total 总条数
* @param pageSize 页大小
* @return 页数
*/
public static int getPages(long total, long pageSize) {
if (Objects.isNull(total) || total < 1) {
return 1;
}
if (Objects.isNull(pageSize) || pageSize < 1) {
pageSize = 100;
}
return (int) Math.ceil((double) total / pageSize);
}
}

View File

@@ -0,0 +1,34 @@
package com.xspaceagi.system.spec.page;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
/**
* 时间范围对象,承接前端一个范围时间的数值
*
* @author soddy
*/
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class RangeTimeVo extends ArrayList<String> implements Serializable {
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
}

View File

@@ -0,0 +1,78 @@
package com.xspaceagi.system.spec.page;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 前端list交互规范结构
*/
@Setter
@Getter
@NoArgsConstructor
public class SuperPage<T> extends Page<T> implements Serializable {
/**
* 表格的列定义
*/
private List<SuperTableColumn> columns = new ArrayList<>();
/**
* @param current 当前页
* @param size 每页显示条数
*/
public SuperPage(long current, long size) {
super(current, size);
}
/**
* @param current 当前页
* @param size 每页显示条数
* @param orders 排序字段
*/
public SuperPage(long current, long size, List<OrderItem> orders) {
super(current, size);
if (!CollectionUtils.isEmpty(orders)) {
this.addOrder(orders);
}
}
/**
* @param pageNo 当前页
* @param pageSize 页大小
* @param total 总条数
*/
public SuperPage(long pageNo, long pageSize, long total) {
super(pageNo, pageSize, total);
}
/**
* @param pageNo 当前页
* @param pageSize 页大小
* @param total 总条数
* @param records 数据
*/
public SuperPage(long pageNo, long pageSize, long total, List<T> records) {
super(pageNo, pageSize, total);
this.setRecords(records);
}
/**
* 替换 IPage 的对象类型
*/
public static <O> SuperPage<O> build(IPage<?> in, List<O> records) {
return new SuperPage<>(in.getCurrent(), in.getSize(), in.getTotal(), records);
}
}

View File

@@ -0,0 +1,100 @@
package com.xspaceagi.system.spec.page;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
@Getter
@Setter
@AllArgsConstructor
public class SuperTableColumn implements Serializable {
/**
* 序号
*/
private int serialNumber;
/**
* 列的标题
*/
private String label;
/**
* 列字段名称
*/
private String name;
/**
* 是否开启列排序
*/
private boolean sortable;
/**
* 列提示
*/
private String tips;
/**
* 列扩展信息
*/
private ColumnExt ext;
private List<SuperTableColumn> children = Collections.emptyList();
public SuperTableColumn(String label, String name, boolean sortable) {
this.label = label;
this.name = name;
this.sortable = sortable;
}
public SuperTableColumn(String label, String name) {
this.label = label;
this.name = name;
this.sortable = false;
}
public SuperTableColumn(int serialNumber, String label, String name) {
this.serialNumber = serialNumber;
this.label = label;
this.name = name;
this.sortable = false;
}
public SuperTableColumn(String label, String name, boolean sortable, ColumnExt ext) {
this.label = label;
this.name = name;
this.sortable = sortable;
this.ext = ext;
}
public SuperTableColumn(int serialNumber, String label, String name, boolean sortable, ColumnExt ext) {
this.serialNumber = serialNumber;
this.label = label;
this.name = name;
this.sortable = sortable;
this.ext = ext;
}
public SuperTableColumn(String label, String name, ColumnExt ext) {
this.label = label;
this.name = name;
this.sortable = false;
this.ext = ext;
}
public SuperTableColumn(int serialNumber, String label, String name, ColumnExt ext) {
this.serialNumber = serialNumber;
this.label = label;
this.name = name;
this.sortable = false;
this.ext = ext;
}
public SuperTableColumn() {
}
}

Some files were not shown because too many files have changed in this diff Show More