refactor(modules): 拆分多模块工程并收口common基础模块

This commit is contained in:
2026-06-01 03:26:18 +08:00
parent 6fe1209801
commit 07ad8bb36b
231 changed files with 1690 additions and 172 deletions

View File

@@ -0,0 +1,60 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bruce</groupId>
<artifactId>common-agent-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common-agent-agent</artifactId>
<name>common-agent-agent</name>
<dependencies>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-rag</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-modelprovider</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

85
common-agent-boot/pom.xml Normal file
View File

@@ -0,0 +1,85 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bruce</groupId>
<artifactId>common-agent-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common-agent-boot</artifactId>
<name>common-agent-boot</name>
<dependencies>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-rag</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-modelprovider</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-agent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-workflow</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-mcp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-skill</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-observability</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,11 +1,22 @@
package com.bruce; package com.bruce;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication @SpringBootApplication
@EnableAsync @EnableAsync
@MapperScan(basePackages = {
"com.bruce.common.mapper",
"com.bruce.rag.mapper",
"com.bruce.modelprovider.mapper",
"com.bruce.agent.mapper",
"com.bruce.workflow.mapper",
"com.bruce.mcp.mapper",
"com.bruce.skill.mapper",
"com.bruce.observability.mapper"
})
public class CommonAgentApplication { public class CommonAgentApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@@ -0,0 +1,15 @@
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://110.42.106.130:5431/common_agent?currentSchema=common_agent
username: common_agent
password: common_agent
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
configuration:
map-underscore-to-camel-case: true
common:
attachment:
base-path: /data/common-agent/attachments

View File

@@ -1,5 +1,6 @@
package com.bruce.common.config; package com.bruce.integration.config;
import com.bruce.common.config.EntityAuditMetaObjectHandler;
import com.bruce.rag.entity.RagStore; import com.bruce.rag.entity.RagStore;
import org.apache.ibatis.reflection.SystemMetaObject; import org.apache.ibatis.reflection.SystemMetaObject;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@@ -1,4 +1,4 @@
package com.bruce.common.enumconfig; package com.bruce.integration.enumconfig;
import com.bruce.common.enums.CommonStatusEnum; import com.bruce.common.enums.CommonStatusEnum;
import com.bruce.common.enums.EnableStatusEnum; import com.bruce.common.enums.EnableStatusEnum;

View File

@@ -1,4 +1,4 @@
package com.bruce.common.enumconfig; package com.bruce.integration.enumconfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bruce.common.domain.entity.SysEnum; import com.bruce.common.domain.entity.SysEnum;

View File

@@ -0,0 +1,90 @@
package com.bruce.integration.enumconfig;
import com.bruce.common.domain.entity.SysEnum;
import com.bruce.common.enums.PersistableSysEnumDefinition;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* sys_enum 初始化测试的辅助工具。
* <p>
* 该类只服务于测试入口,用于把代码里的枚举定义组装成可落库的数据结构,
* 并在真正写库前完成组级唯一性校验。
*/
final class SysEnumDefinitionSyncSupport {
private SysEnumDefinitionSyncSupport() {
}
static EnumGroup groupOf(List<? extends PersistableSysEnumDefinition> definitions) {
if (definitions == null || definitions.isEmpty()) {
throw new IllegalArgumentException("枚举定义不能为空");
}
PersistableSysEnumDefinition first = definitions.getFirst();
validateGroupMembers(first, definitions);
validateUniqueValuesAndSorts(first, definitions);
return new EnumGroup(first.getCatalog(), first.getType(), List.copyOf(definitions));
}
static void validateUniqueGroupKeys(List<EnumGroup> groups) {
Set<String> keys = new HashSet<>();
for (EnumGroup group : groups) {
String key = group.catalog() + "/" + group.type();
if (!keys.add(key)) {
throw new IllegalArgumentException("存在重复的枚举分组: " + key);
}
}
}
static List<SysEnum> toEntities(EnumGroup group) {
return group.definitions().stream()
.map(item -> {
SysEnum sysEnum = new SysEnum();
sysEnum.setCatalog(group.catalog());
sysEnum.setType(group.type());
sysEnum.setName(item.getName());
sysEnum.setValue(item.getValue());
sysEnum.setStrvalue(item.getStrvalue());
sysEnum.setSort(item.getSort());
sysEnum.setRemark(item.getRemark());
return sysEnum;
})
.toList();
}
private static void validateGroupMembers(
PersistableSysEnumDefinition first,
List<? extends PersistableSysEnumDefinition> definitions
) {
for (PersistableSysEnumDefinition item : definitions) {
if (!first.getCatalog().equals(item.getCatalog()) || !first.getType().equals(item.getType())) {
throw new IllegalArgumentException("同一枚举组中的 catalog/type 必须一致");
}
}
}
private static void validateUniqueValuesAndSorts(
PersistableSysEnumDefinition first,
List<? extends PersistableSysEnumDefinition> definitions
) {
Set<Integer> values = new HashSet<>();
Set<Integer> sorts = new HashSet<>();
for (PersistableSysEnumDefinition item : definitions) {
if (!values.add(item.getValue())) {
throw new IllegalArgumentException("枚举值重复: " + first.getCatalog() + "/" + first.getType() + "/" + item.getValue());
}
if (!sorts.add(item.getSort())) {
throw new IllegalArgumentException("枚举排序重复: " + first.getCatalog() + "/" + first.getType() + "/" + item.getSort());
}
}
}
record EnumGroup(
String catalog,
String type,
List<? extends PersistableSysEnumDefinition> definitions
) {
}
}

View File

@@ -1,4 +1,4 @@
package com.bruce.common.enumconfig; package com.bruce.integration.enumconfig;
import com.bruce.common.domain.entity.SysEnum; import com.bruce.common.domain.entity.SysEnum;
import com.bruce.common.enums.EnableStatusEnum; import com.bruce.common.enums.EnableStatusEnum;

View File

@@ -0,0 +1,61 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bruce</groupId>
<artifactId>common-agent-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common-agent-common</artifactId>
<name>common-agent-common</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<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>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -3,26 +3,39 @@ package com.bruce.common.controller;
import com.bruce.common.domain.model.RequestResult; import com.bruce.common.domain.model.RequestResult;
import com.bruce.common.dto.request.SysAttachmentUploadRequest; import com.bruce.common.dto.request.SysAttachmentUploadRequest;
import com.bruce.common.dto.response.SysAttachmentResponse; import com.bruce.common.dto.response.SysAttachmentResponse;
import com.bruce.common.factory.SysAttachmentFactory;
import com.bruce.common.service.ISysAttachmentService; import com.bruce.common.service.ISysAttachmentService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@Tag(name = "系统附件管理") @Tag(name = "系统附件管理")
@Slf4j
@RestController @RestController
@RequestMapping("/api/attachments") @RequestMapping("/api/attachments")
@RequiredArgsConstructor
public class SysAttachmentController { public class SysAttachmentController {
@Autowired private final ISysAttachmentService sysAttachmentService;
private ISysAttachmentService sysAttachmentService;
private final SysAttachmentFactory sysAttachmentFactory;
@Operation(summary = "上传附件") @Operation(summary = "上传附件")
@PostMapping("/upload") @PostMapping("/upload")
public RequestResult<SysAttachmentResponse> upload(@ModelAttribute SysAttachmentUploadRequest request) { public RequestResult<SysAttachmentResponse> upload(@ModelAttribute SysAttachmentUploadRequest request) {
return RequestResult.success(SysAttachmentResponse.fromEntity(sysAttachmentService.upload(request))); log.info("上传附件开始sourceType={}, sourceId={}",
request == null ? null : request.getSourceType(),
request == null ? null : request.getSourceId());
SysAttachmentResponse response = sysAttachmentFactory.toResponse(sysAttachmentService.upload(request));
log.info("上传附件结束attachmentId={}, sourceType={}, sourceId={}",
response == null ? null : response.getId(),
request == null ? null : request.getSourceType(),
request == null ? null : request.getSourceId());
return RequestResult.success(response);
} }
} }

View File

@@ -1,9 +1,7 @@
package com.bruce.common.dto.response; package com.bruce.common.dto.response;
import com.bruce.common.domain.entity.SysAttachment;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.beans.BeanUtils;
@Data @Data
@Schema(description = "系统附件响应") @Schema(description = "系统附件响应")
@@ -41,13 +39,4 @@ public class SysAttachmentResponse {
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;
public static SysAttachmentResponse fromEntity(SysAttachment entity) {
if (entity == null) {
return null;
}
SysAttachmentResponse response = new SysAttachmentResponse();
BeanUtils.copyProperties(entity, response);
return response;
}
} }

View File

@@ -1,9 +1,7 @@
package com.bruce.common.dto.response; package com.bruce.common.dto.response;
import com.bruce.common.domain.entity.SysEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import org.springframework.beans.BeanUtils;
@Data @Data
@Schema(description = "系统枚举响应") @Schema(description = "系统枚举响应")
@@ -32,13 +30,4 @@ public class SysEnumResponse {
@Schema(description = "备注") @Schema(description = "备注")
private String remark; private String remark;
public static SysEnumResponse fromEntity(SysEnum entity) {
if (entity == null) {
return null;
}
SysEnumResponse response = new SysEnumResponse();
BeanUtils.copyProperties(entity, response);
return response;
}
} }

View File

@@ -0,0 +1,22 @@
package com.bruce.common.factory;
import com.bruce.common.domain.entity.SysAttachment;
import com.bruce.common.dto.response.SysAttachmentResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
/**
* 系统附件工厂,集中处理附件元数据出参转换。
*/
@Component
public class SysAttachmentFactory {
public SysAttachmentResponse toResponse(SysAttachment entity) {
if (entity == null) {
return null;
}
SysAttachmentResponse response = new SysAttachmentResponse();
BeanUtils.copyProperties(entity, response);
return response;
}
}

View File

@@ -0,0 +1,63 @@
package com.bruce.common.factory;
import com.bruce.common.domain.entity.SysEnum;
import com.bruce.common.dto.request.SysEnumBatchSaveRequest;
import com.bruce.common.dto.request.SysEnumSaveRequest;
import com.bruce.common.dto.response.SysEnumResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 系统枚举工厂,统一负责请求对象、实体对象和响应对象之间的转换。
*/
@Component
public class SysEnumFactory {
/**
* 将保存请求转换为实体,避免在服务层散落字段拷贝逻辑。
*/
public SysEnum toEntity(SysEnumSaveRequest request) {
if (request == null) {
return null;
}
SysEnum entity = new SysEnum();
BeanUtils.copyProperties(request, entity);
return entity;
}
/**
* 将批量请求中的单个枚举项转换为实体catalog/type 由外层分组统一提供。
*/
public SysEnum toEntity(String catalog, String type, SysEnumBatchSaveRequest.Item item) {
if (item == null) {
return null;
}
SysEnum entity = new SysEnum();
entity.setCatalog(catalog);
entity.setType(type);
entity.setName(item.getName());
entity.setValue(item.getValue());
entity.setStrvalue(item.getStrvalue());
entity.setSort(item.getSort());
entity.setRemark(item.getRemark());
return entity;
}
/**
* 将实体转换为返回对象,保持接口层不直接暴露实体。
*/
public SysEnumResponse toResponse(SysEnum entity) {
if (entity == null) {
return null;
}
SysEnumResponse response = new SysEnumResponse();
BeanUtils.copyProperties(entity, response);
return response;
}
public List<SysEnumResponse> toResponses(List<SysEnum> entities) {
return entities == null ? List.of() : entities.stream().map(this::toResponse).toList();
}
}

View File

@@ -28,6 +28,7 @@ public class SysAttachmentServiceImpl extends ServiceImpl<SysAttachmentMapper, S
@Override @Override
public SysAttachment upload(SysAttachmentUploadRequest request) { public SysAttachment upload(SysAttachmentUploadRequest request) {
// 这里先完成上传校验和本地落盘后续如接入对象存储也只需替换该流程内部实现
if (request == null) { if (request == null) {
throw new IllegalArgumentException("上传请求不能为空"); throw new IllegalArgumentException("上传请求不能为空");
} }

View File

@@ -7,8 +7,10 @@ import com.bruce.common.dto.request.SysEnumManageQueryRequest;
import com.bruce.common.dto.request.SysEnumQueryRequest; import com.bruce.common.dto.request.SysEnumQueryRequest;
import com.bruce.common.dto.request.SysEnumSaveRequest; import com.bruce.common.dto.request.SysEnumSaveRequest;
import com.bruce.common.dto.response.SysEnumResponse; import com.bruce.common.dto.response.SysEnumResponse;
import com.bruce.common.factory.SysEnumFactory;
import com.bruce.common.mapper.SysEnumMapper; import com.bruce.common.mapper.SysEnumMapper;
import com.bruce.common.service.ISysEnumService; import com.bruce.common.service.ISysEnumService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -20,8 +22,11 @@ import java.util.Set;
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor
public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> implements ISysEnumService { public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> implements ISysEnumService {
private final SysEnumFactory sysEnumFactory;
@Override @Override
public List<SysEnum> listByCatalogAndType(SysEnumQueryRequest request) { public List<SysEnum> listByCatalogAndType(SysEnumQueryRequest request) {
log.info("SysEnumServiceImpl.listByCatalogAndType start, request={}", request); log.info("SysEnumServiceImpl.listByCatalogAndType start, request={}", request);
@@ -39,17 +44,19 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
@Override @Override
public List<SysEnumResponse> listResponses() { public List<SysEnumResponse> listResponses() {
log.info("SysEnumServiceImpl.listResponses start"); log.info("查询系统枚举列表开始");
List<SysEnumResponse> responses = toResponses(list()); List<SysEnumResponse> responses = sysEnumFactory.toResponses(list());
log.info("SysEnumServiceImpl.listResponses success, count={}", responses.size()); log.info("查询系统枚举列表结束,count={}", responses.size());
return responses; return responses;
} }
@Override @Override
public List<SysEnumResponse> listByCatalogAndTypeResponses(SysEnumQueryRequest request) { public List<SysEnumResponse> listByCatalogAndTypeResponses(SysEnumQueryRequest request) {
log.info("SysEnumServiceImpl.listByCatalogAndTypeResponses start"); log.info("按模块和类型查询系统枚举开始catalog={}, type={}",
List<SysEnumResponse> responses = toResponses(listByCatalogAndType(request)); request == null ? null : request.getCatalog(),
log.info("SysEnumServiceImpl.listByCatalogAndTypeResponses success, count={}", responses.size()); request == null ? null : request.getType());
List<SysEnumResponse> responses = sysEnumFactory.toResponses(listByCatalogAndType(request));
log.info("按模块和类型查询系统枚举结束count={}", responses.size());
return responses; return responses;
} }
@@ -58,7 +65,7 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
log.info("SysEnumServiceImpl.listForManagement start, request={}", request); log.info("SysEnumServiceImpl.listForManagement start, request={}", request);
SysEnumManageQueryRequest queryRequest = request == null ? new SysEnumManageQueryRequest() : request; SysEnumManageQueryRequest queryRequest = request == null ? new SysEnumManageQueryRequest() : request;
String keyword = queryRequest.getKeyword(); String keyword = queryRequest.getKeyword();
List<SysEnumResponse> responses = toResponses(lambdaQuery() List<SysEnumResponse> responses = sysEnumFactory.toResponses(lambdaQuery()
.eq(StringUtils.hasText(queryRequest.getCatalog()), SysEnum::getCatalog, queryRequest.getCatalog()) .eq(StringUtils.hasText(queryRequest.getCatalog()), SysEnum::getCatalog, queryRequest.getCatalog())
.eq(StringUtils.hasText(queryRequest.getType()), SysEnum::getType, queryRequest.getType()) .eq(StringUtils.hasText(queryRequest.getType()), SysEnum::getType, queryRequest.getType())
.and(StringUtils.hasText(keyword), wrapper -> wrapper .and(StringUtils.hasText(keyword), wrapper -> wrapper
@@ -82,37 +89,35 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
@Override @Override
public SysEnumResponse getResponseById(Long id) { public SysEnumResponse getResponseById(Long id) {
log.info("SysEnumServiceImpl.getResponseById start, id={}", id); log.info("查询系统枚举详情开始,id={}", id);
SysEnumResponse response = SysEnumResponse.fromEntity(getById(id)); SysEnumResponse response = sysEnumFactory.toResponse(getById(id));
log.info("SysEnumServiceImpl.getResponseById success, id={}, found={}", id, response != null); log.info("查询系统枚举详情结束,id={}, found={}", id, response != null);
return response; return response;
} }
@Override @Override
public boolean saveOrUpdate(SysEnumSaveRequest request) { public boolean saveOrUpdate(SysEnumSaveRequest request) {
log.info("SysEnumServiceImpl.saveOrUpdate start, request={}", request); log.info("保存系统枚举开始id={}, catalog={}, type={}, value={}",
request == null ? null : request.getId(),
request == null ? null : request.getCatalog(),
request == null ? null : request.getType(),
request == null ? null : request.getValue());
if (request == null) { if (request == null) {
throw new IllegalArgumentException("保存请求不能为空"); throw new IllegalArgumentException("保存请求不能为空");
} }
SysEnum sysEnum = new SysEnum(); SysEnum sysEnum = sysEnumFactory.toEntity(request);
sysEnum.setId(request.getId());
sysEnum.setCatalog(request.getCatalog());
sysEnum.setType(request.getType());
sysEnum.setName(request.getName());
sysEnum.setValue(request.getValue());
sysEnum.setStrvalue(request.getStrvalue());
sysEnum.setSort(request.getSort());
sysEnum.setRemark(request.getRemark());
boolean result = super.saveOrUpdate(sysEnum); boolean result = super.saveOrUpdate(sysEnum);
log.info("SysEnumServiceImpl.saveOrUpdate success, id={}, catalog={}, type={}, value={}, result={}", log.info("保存系统枚举结束,id={}, catalog={}, type={}, value={}, result={}",
request.getId(), request.getCatalog(), request.getType(), request.getValue(), result); request.getId(), request.getCatalog(), request.getType(), request.getValue(), result);
return result; return result;
} }
@Override @Override
public boolean batchSave(SysEnumBatchSaveRequest request) { public boolean batchSave(SysEnumBatchSaveRequest request) {
log.info("SysEnumServiceImpl.batchSave start, request={}", request); log.info("批量保存系统枚举开始catalog={}, type={}",
request == null ? null : request.getCatalog(),
request == null ? null : request.getType());
List<SysEnum> existingEnums = lambdaQuery() List<SysEnum> existingEnums = lambdaQuery()
.eq(request != null && StringUtils.hasText(request.getCatalog()), SysEnum::getCatalog, request == null ? null : request.getCatalog()) .eq(request != null && StringUtils.hasText(request.getCatalog()), SysEnum::getCatalog, request == null ? null : request.getCatalog())
.eq(request != null && StringUtils.hasText(request.getType()), SysEnum::getType, request == null ? null : request.getType()) .eq(request != null && StringUtils.hasText(request.getType()), SysEnum::getType, request == null ? null : request.getType())
@@ -120,20 +125,10 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
validateBatchSaveRequest(request, existingEnums); validateBatchSaveRequest(request, existingEnums);
List<SysEnum> enums = request.getItems().stream() List<SysEnum> enums = request.getItems().stream()
.map(item -> { .map(item -> sysEnumFactory.toEntity(request.getCatalog(), request.getType(), item))
SysEnum sysEnum = new SysEnum();
sysEnum.setCatalog(request.getCatalog());
sysEnum.setType(request.getType());
sysEnum.setName(item.getName());
sysEnum.setValue(item.getValue());
sysEnum.setStrvalue(item.getStrvalue());
sysEnum.setSort(item.getSort());
sysEnum.setRemark(item.getRemark());
return sysEnum;
})
.toList(); .toList();
boolean result = saveBatch(enums); boolean result = saveBatch(enums);
log.info("SysEnumServiceImpl.batchSave success, catalog={}, type={}, itemCount={}, result={}", log.info("批量保存系统枚举结束,catalog={}, type={}, itemCount={}, result={}",
request.getCatalog(), request.getType(), enums.size(), result); request.getCatalog(), request.getType(), enums.size(), result);
return result; return result;
} }
@@ -240,9 +235,4 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
} }
} }
private List<SysEnumResponse> toResponses(List<SysEnum> enums) {
return enums.stream()
.map(SysEnumResponse::fromEntity)
.toList();
}
} }

View File

@@ -1,4 +1,4 @@
package com.bruce.rag.typehandler; package com.bruce.common.typehandler;
import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.JdbcType;

View File

@@ -9,6 +9,7 @@ import com.bruce.common.domain.model.RequestResult;
import com.bruce.common.dto.request.SysAttachmentUploadRequest; import com.bruce.common.dto.request.SysAttachmentUploadRequest;
import com.bruce.common.domain.entity.SysAttachment; import com.bruce.common.domain.entity.SysAttachment;
import com.bruce.common.dto.response.SysAttachmentResponse; import com.bruce.common.dto.response.SysAttachmentResponse;
import com.bruce.common.factory.SysAttachmentFactory;
import com.bruce.common.mapper.SysAttachmentMapper; import com.bruce.common.mapper.SysAttachmentMapper;
import com.bruce.common.service.ISysAttachmentService; import com.bruce.common.service.ISysAttachmentService;
import com.bruce.common.service.impl.SysAttachmentServiceImpl; import com.bruce.common.service.impl.SysAttachmentServiceImpl;
@@ -47,7 +48,7 @@ class SysAttachmentComponentStructureTests {
assertEquals(SysAttachment.class, serviceMethod.getReturnType()); assertEquals(SysAttachment.class, serviceMethod.getReturnType());
assertEquals(RequestResult.class, controllerMethod.getReturnType()); assertEquals(RequestResult.class, controllerMethod.getReturnType());
assertTrue(controllerMethod.getGenericReturnType().getTypeName().contains("SysAttachmentResponse")); assertTrue(controllerMethod.getGenericReturnType().getTypeName().contains("SysAttachmentResponse"));
assertEquals(SysAttachmentResponse.class, SysAttachmentResponse.class.getMethod("fromEntity", SysAttachment.class).getReturnType()); assertEquals(SysAttachmentResponse.class, SysAttachmentFactory.class.getMethod("toResponse", SysAttachment.class).getReturnType());
} }
@Test @Test

View File

@@ -2,6 +2,7 @@ package com.bruce.common.enumconfig;
import com.bruce.common.domain.entity.SysEnum; import com.bruce.common.domain.entity.SysEnum;
import com.bruce.common.dto.request.SysEnumBatchSaveRequest; import com.bruce.common.dto.request.SysEnumBatchSaveRequest;
import com.bruce.common.factory.SysEnumFactory;
import com.bruce.common.service.impl.SysEnumServiceImpl; import com.bruce.common.service.impl.SysEnumServiceImpl;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -12,9 +13,11 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
class SysEnumBatchSaveValidationTests { class SysEnumBatchSaveValidationTests {
private final SysEnumFactory sysEnumFactory = new SysEnumFactory();
@Test @Test
void batchSaveShouldRejectDuplicateValuesInsideRequest() { void batchSaveShouldRejectDuplicateValuesInsideRequest() {
SysEnumServiceImpl service = new SysEnumServiceImpl(); SysEnumServiceImpl service = new SysEnumServiceImpl(sysEnumFactory);
SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest(); SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest();
request.setCatalog("common"); request.setCatalog("common");
request.setType("enable_status"); request.setType("enable_status");
@@ -28,7 +31,7 @@ class SysEnumBatchSaveValidationTests {
@Test @Test
void batchSaveShouldRejectDuplicateValuesFromExistingEnums() { void batchSaveShouldRejectDuplicateValuesFromExistingEnums() {
SysEnumServiceImpl service = new SysEnumServiceImpl(); SysEnumServiceImpl service = new SysEnumServiceImpl(sysEnumFactory);
SysEnum existing = new SysEnum(); SysEnum existing = new SysEnum();
existing.setCatalog("common"); existing.setCatalog("common");
existing.setType("enable_status"); existing.setType("enable_status");
@@ -47,7 +50,7 @@ class SysEnumBatchSaveValidationTests {
@Test @Test
void batchSaveShouldAcceptUniqueValues() { void batchSaveShouldAcceptUniqueValues() {
SysEnumServiceImpl service = new SysEnumServiceImpl(); SysEnumServiceImpl service = new SysEnumServiceImpl(sysEnumFactory);
SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest(); SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest();
request.setCatalog("common"); request.setCatalog("common");
request.setType("enable_status"); request.setType("enable_status");

View File

@@ -11,6 +11,7 @@ import com.bruce.common.dto.request.SysEnumManageQueryRequest;
import com.bruce.common.dto.request.SysEnumQueryRequest; import com.bruce.common.dto.request.SysEnumQueryRequest;
import com.bruce.common.dto.request.SysEnumSaveRequest; import com.bruce.common.dto.request.SysEnumSaveRequest;
import com.bruce.common.dto.response.SysEnumResponse; import com.bruce.common.dto.response.SysEnumResponse;
import com.bruce.common.factory.SysEnumFactory;
import com.bruce.common.mapper.SysEnumMapper; import com.bruce.common.mapper.SysEnumMapper;
import com.bruce.common.service.ISysEnumService; import com.bruce.common.service.ISysEnumService;
import com.bruce.common.service.impl.SysEnumServiceImpl; import com.bruce.common.service.impl.SysEnumServiceImpl;
@@ -89,7 +90,7 @@ class SysEnumComponentStructureTests {
Method manageQueryMethod = SysEnumController.class.getMethod("queryForManagement", SysEnumManageQueryRequest.class); Method manageQueryMethod = SysEnumController.class.getMethod("queryForManagement", SysEnumManageQueryRequest.class);
Method detailMethod = SysEnumController.class.getMethod("getById", Long.class); Method detailMethod = SysEnumController.class.getMethod("getById", Long.class);
Method serviceListMethod = ISysEnumService.class.getMethod("listResponses"); Method serviceListMethod = ISysEnumService.class.getMethod("listResponses");
Method responseFactory = SysEnumResponse.class.getMethod("fromEntity", SysEnum.class); Method responseFactory = SysEnumFactory.class.getMethod("toResponse", SysEnum.class);
assertTrue(serviceListMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); assertTrue(serviceListMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse"));
assertTrue(listMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); assertTrue(listMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse"));
@@ -99,10 +100,12 @@ class SysEnumComponentStructureTests {
} }
@Test @Test
void sysEnumShouldProvideManualInitTestEntry() throws NoSuchMethodException { void sysEnumShouldProvideDefinitionSyncSupportEntry() throws NoSuchMethodException {
Method initMethod = SysEnumDataInitTests.class.getMethod("initDefaultEnums"); Method groupMethod = SysEnumDefinitionSyncSupport.class.getDeclaredMethod("groupOf", List.class);
Method uniqueKeyMethod = SysEnumDefinitionSyncSupport.class.getDeclaredMethod("validateUniqueGroupKeys", List.class);
assertNotNull(initMethod); assertNotNull(groupMethod);
assertNotNull(uniqueKeyMethod);
} }
@Test @Test

View File

@@ -0,0 +1,43 @@
package com.bruce.common.factory;
import com.bruce.common.domain.entity.SysAttachment;
import com.bruce.common.dto.response.SysAttachmentResponse;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class SysAttachmentFactoryTests {
@Test
void shouldConvertEntityToResponse() {
SysAttachment entity = new SysAttachment();
entity.setId(3003L);
entity.setSourceType("RAG");
entity.setSourceId(1001L);
entity.setOriginalName("知识库说明.pdf");
entity.setFileName("uuid.pdf");
entity.setFileSuffix("pdf");
entity.setContentType("application/pdf");
entity.setFileSize(1024L);
entity.setStorageType("LOCAL");
entity.setFilePath("20260601/uuid.pdf");
entity.setFileUrl(null);
entity.setRemark("上传附件");
SysAttachmentFactory factory = new SysAttachmentFactory();
SysAttachmentResponse response = factory.toResponse(entity);
assertNotNull(response);
assertEquals(3003L, response.getId());
assertEquals("RAG", response.getSourceType());
assertEquals(1001L, response.getSourceId());
assertEquals("知识库说明.pdf", response.getOriginalName());
assertEquals("uuid.pdf", response.getFileName());
assertEquals("pdf", response.getFileSuffix());
assertEquals("application/pdf", response.getContentType());
assertEquals(1024L, response.getFileSize());
assertEquals("LOCAL", response.getStorageType());
assertEquals("上传附件", response.getRemark());
}
}

View File

@@ -0,0 +1,64 @@
package com.bruce.common.factory;
import com.bruce.common.domain.entity.SysEnum;
import com.bruce.common.dto.request.SysEnumSaveRequest;
import com.bruce.common.dto.response.SysEnumResponse;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class SysEnumFactoryTests {
@Test
void shouldConvertSaveRequestToEntity() {
SysEnumSaveRequest request = new SysEnumSaveRequest();
request.setId(1001L);
request.setCatalog("common");
request.setType("enable_status");
request.setName("启用");
request.setValue(1);
request.setStrvalue("ENABLED");
request.setSort(1);
request.setRemark("启停状态");
SysEnumFactory factory = new SysEnumFactory();
SysEnum entity = factory.toEntity(request);
assertNotNull(entity);
assertEquals(1001L, entity.getId());
assertEquals("common", entity.getCatalog());
assertEquals("enable_status", entity.getType());
assertEquals("启用", entity.getName());
assertEquals(1, entity.getValue());
assertEquals("ENABLED", entity.getStrvalue());
assertEquals(1, entity.getSort());
assertEquals("启停状态", entity.getRemark());
}
@Test
void shouldConvertEntityToResponse() {
SysEnum entity = new SysEnum();
entity.setId(2002L);
entity.setCatalog("rag");
entity.setType("parse_status");
entity.setName("已解析");
entity.setValue(2);
entity.setStrvalue("PARSED");
entity.setSort(2);
entity.setRemark("解析状态");
SysEnumFactory factory = new SysEnumFactory();
SysEnumResponse response = factory.toResponse(entity);
assertNotNull(response);
assertEquals(2002L, response.getId());
assertEquals("rag", response.getCatalog());
assertEquals("parse_status", response.getType());
assertEquals("已解析", response.getName());
assertEquals(2, response.getValue());
assertEquals("PARSED", response.getStrvalue());
assertEquals(2, response.getSort());
assertEquals("解析状态", response.getRemark());
}
}

50
common-agent-mcp/pom.xml Normal file
View File

@@ -0,0 +1,50 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bruce</groupId>
<artifactId>common-agent-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common-agent-mcp</artifactId>
<name>common-agent-mcp</name>
<dependencies>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,30 @@
package com.bruce.mcp.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.bruce.common.domain.model.BaseEntity;
import com.bruce.common.typehandler.PgJsonbStringTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* MCP 能力实体,对应 mcp_capability 表。
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mcp_capability")
public class McpCapability extends BaseEntity {
private Long serverId;
private String capabilityCode;
private String capabilityName;
private String capabilityType;
@TableField(typeHandler = PgJsonbStringTypeHandler.class)
private String schemaJson;
private Boolean enabled;
}

View File

@@ -0,0 +1,38 @@
package com.bruce.mcp.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.bruce.common.domain.model.BaseEntity;
import com.bruce.common.typehandler.PgJsonbStringTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* MCP 服务实体,对应 mcp_server 表。
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mcp_server")
public class McpServer extends BaseEntity {
private String serverCode;
private String serverName;
private String importType;
private String endpointUrl;
private String packageName;
@TableField(typeHandler = PgJsonbStringTypeHandler.class)
private String manifestJson;
private String authType;
private String secretRef;
private String healthStatus;
private Boolean enabled;
}

View File

@@ -0,0 +1,45 @@
package com.bruce.mcp.enums;
import com.bruce.common.enums.PersistableSysEnumDefinition;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum McpHealthStatusEnum implements PersistableSysEnumDefinition {
UNKNOWN(1, "未知", "UNKNOWN"),
HEALTHY(2, "健康", "HEALTHY"),
UNHEALTHY(3, "异常", "UNHEALTHY");
private final Integer value;
private final String label;
private final String strvalue;
@Override
public String getCatalog() {
return "mcp";
}
@Override
public String getType() {
return "health_status";
}
@Override
public String getName() {
return label;
}
@Override
public Integer getSort() {
return value;
}
@Override
public String getRemark() {
return "MCP健康状态";
}
}

View File

@@ -0,0 +1,50 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bruce</groupId>
<artifactId>common-agent-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>common-agent-modelprovider</artifactId>
<name>common-agent-modelprovider</name>
<dependencies>
<dependency>
<groupId>com.bruce</groupId>
<artifactId>common-agent-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

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