From 7188dd49b5d63cc6b2a6a3d1e14142426e33f86c Mon Sep 17 00:00:00 2001 From: bruce Date: Wed, 20 May 2026 23:25:30 +0800 Subject: [PATCH] feat: add enum dto APIs and batch save --- .../controller/SysAttachmentController.java | 6 +- .../common/controller/SysEnumController.java | 30 ++++- .../dto/request/SysEnumBatchSaveRequest.java | 40 ++++++ .../request/SysEnumManageQueryRequest.java | 18 +++ .../dto/response/SysAttachmentResponse.java | 53 ++++++++ .../common/dto/response/SysEnumResponse.java | 44 +++++++ .../bruce/common/service/ISysEnumService.java | 13 ++ .../service/impl/SysEnumServiceImpl.java | 117 ++++++++++++++++++ .../rag/controller/RagDocumentController.java | 8 +- .../rag/controller/RagStoreController.java | 8 +- .../rag/dto/response/RagDocumentResponse.java | 50 ++++++++ .../rag/dto/response/RagStoreResponse.java | 38 ++++++ .../rag/service/IRagDocumentService.java | 5 +- .../bruce/rag/service/IRagStoreService.java | 5 +- .../service/impl/RagDocumentServiceImpl.java | 18 ++- .../rag/service/impl/RagStoreServiceImpl.java | 18 ++- .../SysAttachmentComponentStructureTests.java | 3 + .../SysEnumBatchSaveValidationTests.java | 68 ++++++++++ .../SysEnumComponentStructureTests.java | 39 ++++++ .../bruce/rag/RagComponentStructureTests.java | 14 +++ 20 files changed, 571 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/bruce/common/dto/request/SysEnumBatchSaveRequest.java create mode 100644 src/main/java/com/bruce/common/dto/request/SysEnumManageQueryRequest.java create mode 100644 src/main/java/com/bruce/common/dto/response/SysAttachmentResponse.java create mode 100644 src/main/java/com/bruce/common/dto/response/SysEnumResponse.java create mode 100644 src/main/java/com/bruce/rag/dto/response/RagDocumentResponse.java create mode 100644 src/main/java/com/bruce/rag/dto/response/RagStoreResponse.java create mode 100644 src/test/java/com/bruce/common/enumconfig/SysEnumBatchSaveValidationTests.java diff --git a/src/main/java/com/bruce/common/controller/SysAttachmentController.java b/src/main/java/com/bruce/common/controller/SysAttachmentController.java index 5ecc8da..6dfd4de 100644 --- a/src/main/java/com/bruce/common/controller/SysAttachmentController.java +++ b/src/main/java/com/bruce/common/controller/SysAttachmentController.java @@ -1,8 +1,8 @@ package com.bruce.common.controller; -import com.bruce.common.domain.entity.SysAttachment; import com.bruce.common.domain.model.RequestResult; import com.bruce.common.dto.request.SysAttachmentUploadRequest; +import com.bruce.common.dto.response.SysAttachmentResponse; import com.bruce.common.service.ISysAttachmentService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,7 +22,7 @@ public class SysAttachmentController { @Operation(summary = "上传附件") @PostMapping("/upload") - public RequestResult upload(@ModelAttribute SysAttachmentUploadRequest request) { - return RequestResult.success(sysAttachmentService.upload(request)); + public RequestResult upload(@ModelAttribute SysAttachmentUploadRequest request) { + return RequestResult.success(SysAttachmentResponse.fromEntity(sysAttachmentService.upload(request))); } } diff --git a/src/main/java/com/bruce/common/controller/SysEnumController.java b/src/main/java/com/bruce/common/controller/SysEnumController.java index 84ff8e4..4c48a14 100644 --- a/src/main/java/com/bruce/common/controller/SysEnumController.java +++ b/src/main/java/com/bruce/common/controller/SysEnumController.java @@ -1,9 +1,11 @@ package com.bruce.common.controller; -import com.bruce.common.domain.entity.SysEnum; import com.bruce.common.domain.model.RequestResult; +import com.bruce.common.dto.request.SysEnumBatchSaveRequest; +import com.bruce.common.dto.request.SysEnumManageQueryRequest; import com.bruce.common.dto.request.SysEnumQueryRequest; import com.bruce.common.dto.request.SysEnumSaveRequest; +import com.bruce.common.dto.response.SysEnumResponse; import com.bruce.common.service.ISysEnumService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -28,14 +30,26 @@ public class SysEnumController { @Operation(summary = "查询全部系统枚举") @GetMapping - public RequestResult> list() { - return RequestResult.success(sysEnumService.list()); + public RequestResult> list() { + return RequestResult.success(sysEnumService.listResponses()); } @Operation(summary = "根据模块和类型查询系统枚举") @PostMapping("/query") - public RequestResult> queryByCatalogAndType(@RequestBody SysEnumQueryRequest request) { - return RequestResult.success(sysEnumService.listByCatalogAndType(request)); + public RequestResult> queryByCatalogAndType(@RequestBody SysEnumQueryRequest request) { + return RequestResult.success(sysEnumService.listByCatalogAndTypeResponses(request)); + } + + @Operation(summary = "管理端查询系统枚举") + @PostMapping("/manage/query") + public RequestResult> queryForManagement(@RequestBody(required = false) SysEnumManageQueryRequest request) { + return RequestResult.success(sysEnumService.listForManagement(request)); + } + + @Operation(summary = "查询系统枚举详情") + @GetMapping("/{id}") + public RequestResult getById(@PathVariable Long id) { + return RequestResult.success(sysEnumService.getResponseById(id)); } @Operation(summary = "新增或修改系统枚举") @@ -44,6 +58,12 @@ public class SysEnumController { return RequestResult.success(sysEnumService.saveOrUpdate(request)); } + @Operation(summary = "批量新增系统枚举") + @PostMapping("/batch") + public RequestResult batchSave(@RequestBody SysEnumBatchSaveRequest request) { + return RequestResult.success(sysEnumService.batchSave(request)); + } + @Operation(summary = "删除系统枚举") @DeleteMapping("/{id}") public RequestResult deleteById(@PathVariable Long id) { diff --git a/src/main/java/com/bruce/common/dto/request/SysEnumBatchSaveRequest.java b/src/main/java/com/bruce/common/dto/request/SysEnumBatchSaveRequest.java new file mode 100644 index 0000000..ca6d75b --- /dev/null +++ b/src/main/java/com/bruce/common/dto/request/SysEnumBatchSaveRequest.java @@ -0,0 +1,40 @@ +package com.bruce.common.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +@Schema(description = "系统枚举批量保存请求") +public class SysEnumBatchSaveRequest { + + @Schema(description = "模块目录") + private String catalog; + + @Schema(description = "枚举类型") + private String type; + + @Schema(description = "枚举项") + private List items; + + @Data + @Schema(description = "系统枚举批量保存项") + public static class Item { + + @Schema(description = "枚举名称") + private String name; + + @Schema(description = "整型值") + private Integer value; + + @Schema(description = "字符串值") + private String strvalue; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "备注") + private String remark; + } +} diff --git a/src/main/java/com/bruce/common/dto/request/SysEnumManageQueryRequest.java b/src/main/java/com/bruce/common/dto/request/SysEnumManageQueryRequest.java new file mode 100644 index 0000000..d56afb3 --- /dev/null +++ b/src/main/java/com/bruce/common/dto/request/SysEnumManageQueryRequest.java @@ -0,0 +1,18 @@ +package com.bruce.common.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "系统枚举管理查询请求") +public class SysEnumManageQueryRequest { + + @Schema(description = "模块目录") + private String catalog; + + @Schema(description = "枚举类型") + private String type; + + @Schema(description = "关键字,匹配目录、类型、名称、字符串值或备注") + private String keyword; +} diff --git a/src/main/java/com/bruce/common/dto/response/SysAttachmentResponse.java b/src/main/java/com/bruce/common/dto/response/SysAttachmentResponse.java new file mode 100644 index 0000000..d68b76f --- /dev/null +++ b/src/main/java/com/bruce/common/dto/response/SysAttachmentResponse.java @@ -0,0 +1,53 @@ +package com.bruce.common.dto.response; + +import com.bruce.common.domain.entity.SysAttachment; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +@Data +@Schema(description = "系统附件响应") +public class SysAttachmentResponse { + + @Schema(description = "主键ID") + private Long id; + + @Schema(description = "来源业务类型") + private String sourceType; + + @Schema(description = "来源业务ID") + private Long sourceId; + + @Schema(description = "原始文件名") + private String originalName; + + @Schema(description = "存储文件名") + private String fileName; + + @Schema(description = "文件后缀") + private String fileSuffix; + + @Schema(description = "文件MIME类型") + private String contentType; + + @Schema(description = "文件大小(字节)") + private Long fileSize; + + @Schema(description = "存储类型") + private String storageType; + + @Schema(description = "文件访问地址") + private String fileUrl; + + @Schema(description = "备注") + private String remark; + + public static SysAttachmentResponse fromEntity(SysAttachment entity) { + if (entity == null) { + return null; + } + SysAttachmentResponse response = new SysAttachmentResponse(); + BeanUtils.copyProperties(entity, response); + return response; + } +} diff --git a/src/main/java/com/bruce/common/dto/response/SysEnumResponse.java b/src/main/java/com/bruce/common/dto/response/SysEnumResponse.java new file mode 100644 index 0000000..78f0c0b --- /dev/null +++ b/src/main/java/com/bruce/common/dto/response/SysEnumResponse.java @@ -0,0 +1,44 @@ +package com.bruce.common.dto.response; + +import com.bruce.common.domain.entity.SysEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +@Data +@Schema(description = "系统枚举响应") +public class SysEnumResponse { + + @Schema(description = "主键ID") + private Long id; + + @Schema(description = "模块目录") + private String catalog; + + @Schema(description = "枚举类型") + private String type; + + @Schema(description = "枚举名称") + private String name; + + @Schema(description = "整型值") + private Integer value; + + @Schema(description = "字符串值") + private String strvalue; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "备注") + private String remark; + + public static SysEnumResponse fromEntity(SysEnum entity) { + if (entity == null) { + return null; + } + SysEnumResponse response = new SysEnumResponse(); + BeanUtils.copyProperties(entity, response); + return response; + } +} diff --git a/src/main/java/com/bruce/common/service/ISysEnumService.java b/src/main/java/com/bruce/common/service/ISysEnumService.java index 52de7f7..7bff5b8 100644 --- a/src/main/java/com/bruce/common/service/ISysEnumService.java +++ b/src/main/java/com/bruce/common/service/ISysEnumService.java @@ -2,8 +2,11 @@ package com.bruce.common.service; import com.baomidou.mybatisplus.extension.service.IService; import com.bruce.common.domain.entity.SysEnum; +import com.bruce.common.dto.request.SysEnumBatchSaveRequest; +import com.bruce.common.dto.request.SysEnumManageQueryRequest; import com.bruce.common.dto.request.SysEnumQueryRequest; import com.bruce.common.dto.request.SysEnumSaveRequest; +import com.bruce.common.dto.response.SysEnumResponse; import java.util.List; @@ -11,5 +14,15 @@ public interface ISysEnumService extends IService { List listByCatalogAndType(SysEnumQueryRequest request); + List listResponses(); + + List listByCatalogAndTypeResponses(SysEnumQueryRequest request); + + List listForManagement(SysEnumManageQueryRequest request); + + SysEnumResponse getResponseById(Long id); + boolean saveOrUpdate(SysEnumSaveRequest request); + + boolean batchSave(SysEnumBatchSaveRequest request); } diff --git a/src/main/java/com/bruce/common/service/impl/SysEnumServiceImpl.java b/src/main/java/com/bruce/common/service/impl/SysEnumServiceImpl.java index 170ad17..866cc87 100644 --- a/src/main/java/com/bruce/common/service/impl/SysEnumServiceImpl.java +++ b/src/main/java/com/bruce/common/service/impl/SysEnumServiceImpl.java @@ -2,14 +2,19 @@ package com.bruce.common.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bruce.common.domain.entity.SysEnum; +import com.bruce.common.dto.request.SysEnumBatchSaveRequest; +import com.bruce.common.dto.request.SysEnumManageQueryRequest; import com.bruce.common.dto.request.SysEnumQueryRequest; import com.bruce.common.dto.request.SysEnumSaveRequest; +import com.bruce.common.dto.response.SysEnumResponse; import com.bruce.common.mapper.SysEnumMapper; import com.bruce.common.service.ISysEnumService; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Service public class SysEnumServiceImpl extends ServiceImpl implements ISysEnumService { @@ -26,6 +31,45 @@ public class SysEnumServiceImpl extends ServiceImpl impl .list(); } + @Override + public List listResponses() { + return toResponses(list()); + } + + @Override + public List listByCatalogAndTypeResponses(SysEnumQueryRequest request) { + return toResponses(listByCatalogAndType(request)); + } + + @Override + public List listForManagement(SysEnumManageQueryRequest request) { + SysEnumManageQueryRequest queryRequest = request == null ? new SysEnumManageQueryRequest() : request; + String keyword = queryRequest.getKeyword(); + return toResponses(lambdaQuery() + .eq(StringUtils.hasText(queryRequest.getCatalog()), SysEnum::getCatalog, queryRequest.getCatalog()) + .eq(StringUtils.hasText(queryRequest.getType()), SysEnum::getType, queryRequest.getType()) + .and(StringUtils.hasText(keyword), wrapper -> wrapper + .like(SysEnum::getCatalog, keyword) + .or() + .like(SysEnum::getType, keyword) + .or() + .like(SysEnum::getName, keyword) + .or() + .like(SysEnum::getStrvalue, keyword) + .or() + .like(SysEnum::getRemark, keyword)) + .orderByAsc(SysEnum::getCatalog) + .orderByAsc(SysEnum::getType) + .orderByAsc(SysEnum::getSort) + .orderByAsc(SysEnum::getId) + .list()); + } + + @Override + public SysEnumResponse getResponseById(Long id) { + return SysEnumResponse.fromEntity(getById(id)); + } + @Override public boolean saveOrUpdate(SysEnumSaveRequest request) { if (request == null) { @@ -43,4 +87,77 @@ public class SysEnumServiceImpl extends ServiceImpl impl sysEnum.setRemark(request.getRemark()); return super.saveOrUpdate(sysEnum); } + + @Override + public boolean batchSave(SysEnumBatchSaveRequest request) { + List existingEnums = lambdaQuery() + .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()) + .list(); + validateBatchSaveRequest(request, existingEnums); + + List enums = request.getItems().stream() + .map(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(); + return saveBatch(enums); + } + + public void validateBatchSaveRequest(SysEnumBatchSaveRequest request, List existingEnums) { + if (request == null) { + throw new IllegalArgumentException("批量保存请求不能为空"); + } + if (!StringUtils.hasText(request.getCatalog())) { + throw new IllegalArgumentException("模块目录不能为空"); + } + if (!StringUtils.hasText(request.getType())) { + throw new IllegalArgumentException("枚举类型不能为空"); + } + if (request.getItems() == null || request.getItems().isEmpty()) { + throw new IllegalArgumentException("枚举项不能为空"); + } + + Set requestValues = new HashSet<>(); + for (SysEnumBatchSaveRequest.Item item : request.getItems()) { + if (item == null) { + throw new IllegalArgumentException("枚举项不能为空"); + } + if (!StringUtils.hasText(item.getName())) { + throw new IllegalArgumentException("枚举名称不能为空"); + } + if (item.getValue() == null) { + throw new IllegalArgumentException("枚举整型值不能为空"); + } + if (!requestValues.add(item.getValue())) { + throw new IllegalArgumentException("批量保存请求中存在重复枚举值: " + item.getValue()); + } + } + + Set existingValues = new HashSet<>(); + if (existingEnums != null) { + existingEnums.stream() + .map(SysEnum::getValue) + .forEach(existingValues::add); + } + for (Integer value : requestValues) { + if (existingValues.contains(value)) { + throw new IllegalArgumentException("枚举值已存在: " + value); + } + } + } + + private List toResponses(List enums) { + return enums.stream() + .map(SysEnumResponse::fromEntity) + .toList(); + } } diff --git a/src/main/java/com/bruce/rag/controller/RagDocumentController.java b/src/main/java/com/bruce/rag/controller/RagDocumentController.java index 11908df..408d239 100644 --- a/src/main/java/com/bruce/rag/controller/RagDocumentController.java +++ b/src/main/java/com/bruce/rag/controller/RagDocumentController.java @@ -2,7 +2,7 @@ package com.bruce.rag.controller; import com.bruce.common.domain.model.RequestResult; import com.bruce.rag.dto.request.RagDocumentQueryRequest; -import com.bruce.rag.entity.RagDocument; +import com.bruce.rag.dto.response.RagDocumentResponse; import com.bruce.rag.service.IRagDocumentService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -25,13 +25,13 @@ public class RagDocumentController { @Operation(summary = "查询全部知识库文档") @GetMapping - public RequestResult> list() { - return RequestResult.success(ragDocumentService.list()); + public RequestResult> list() { + return RequestResult.success(ragDocumentService.listResponses()); } @Operation(summary = "按条件查询知识库文档") @PostMapping("/query") - public RequestResult> query(@RequestBody RagDocumentQueryRequest request) { + public RequestResult> query(@RequestBody RagDocumentQueryRequest request) { return RequestResult.success(ragDocumentService.query(request)); } } diff --git a/src/main/java/com/bruce/rag/controller/RagStoreController.java b/src/main/java/com/bruce/rag/controller/RagStoreController.java index 505a923..a8797dc 100644 --- a/src/main/java/com/bruce/rag/controller/RagStoreController.java +++ b/src/main/java/com/bruce/rag/controller/RagStoreController.java @@ -2,7 +2,7 @@ package com.bruce.rag.controller; import com.bruce.common.domain.model.RequestResult; import com.bruce.rag.dto.request.RagStoreQueryRequest; -import com.bruce.rag.entity.RagStore; +import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.service.IRagStoreService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -25,13 +25,13 @@ public class RagStoreController { @Operation(summary = "查询全部知识库") @GetMapping - public RequestResult> list() { - return RequestResult.success(ragStoreService.list()); + public RequestResult> list() { + return RequestResult.success(ragStoreService.listResponses()); } @Operation(summary = "按条件查询知识库") @PostMapping("/query") - public RequestResult> query(@RequestBody RagStoreQueryRequest request) { + public RequestResult> query(@RequestBody RagStoreQueryRequest request) { return RequestResult.success(ragStoreService.query(request)); } } diff --git a/src/main/java/com/bruce/rag/dto/response/RagDocumentResponse.java b/src/main/java/com/bruce/rag/dto/response/RagDocumentResponse.java new file mode 100644 index 0000000..925cb27 --- /dev/null +++ b/src/main/java/com/bruce/rag/dto/response/RagDocumentResponse.java @@ -0,0 +1,50 @@ +package com.bruce.rag.dto.response; + +import com.bruce.rag.entity.RagDocument; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +@Data +@Schema(description = "RAG知识库文档响应") +public class RagDocumentResponse { + + @Schema(description = "主键ID") + private Long id; + + @Schema(description = "知识库ID") + private Long storeId; + + @Schema(description = "附件ID") + private Long attachmentId; + + @Schema(description = "文档标题") + private String documentTitle; + + @Schema(description = "文档摘要") + private String documentSummary; + + @Schema(description = "解析状态") + private String parseStatus; + + @Schema(description = "索引状态") + private String indexStatus; + + @Schema(description = "是否启用") + private Boolean enabled; + + @Schema(description = "失败原因") + private String errorMessage; + + @Schema(description = "备注") + private String remark; + + public static RagDocumentResponse fromEntity(RagDocument entity) { + if (entity == null) { + return null; + } + RagDocumentResponse response = new RagDocumentResponse(); + BeanUtils.copyProperties(entity, response); + return response; + } +} diff --git a/src/main/java/com/bruce/rag/dto/response/RagStoreResponse.java b/src/main/java/com/bruce/rag/dto/response/RagStoreResponse.java new file mode 100644 index 0000000..95877e8 --- /dev/null +++ b/src/main/java/com/bruce/rag/dto/response/RagStoreResponse.java @@ -0,0 +1,38 @@ +package com.bruce.rag.dto.response; + +import com.bruce.rag.entity.RagStore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +@Data +@Schema(description = "RAG知识库响应") +public class RagStoreResponse { + + @Schema(description = "主键ID") + private Long id; + + @Schema(description = "知识库编码") + private String storeCode; + + @Schema(description = "知识库名称") + private String storeName; + + @Schema(description = "知识库描述") + private String description; + + @Schema(description = "状态") + private String status; + + @Schema(description = "备注") + private String remark; + + public static RagStoreResponse fromEntity(RagStore entity) { + if (entity == null) { + return null; + } + RagStoreResponse response = new RagStoreResponse(); + BeanUtils.copyProperties(entity, response); + return response; + } +} diff --git a/src/main/java/com/bruce/rag/service/IRagDocumentService.java b/src/main/java/com/bruce/rag/service/IRagDocumentService.java index f82d8a1..6f59825 100644 --- a/src/main/java/com/bruce/rag/service/IRagDocumentService.java +++ b/src/main/java/com/bruce/rag/service/IRagDocumentService.java @@ -2,11 +2,14 @@ package com.bruce.rag.service; import com.baomidou.mybatisplus.extension.service.IService; import com.bruce.rag.dto.request.RagDocumentQueryRequest; +import com.bruce.rag.dto.response.RagDocumentResponse; import com.bruce.rag.entity.RagDocument; import java.util.List; public interface IRagDocumentService extends IService { - List query(RagDocumentQueryRequest request); + List listResponses(); + + List query(RagDocumentQueryRequest request); } diff --git a/src/main/java/com/bruce/rag/service/IRagStoreService.java b/src/main/java/com/bruce/rag/service/IRagStoreService.java index 0e74cfb..8ec3a4e 100644 --- a/src/main/java/com/bruce/rag/service/IRagStoreService.java +++ b/src/main/java/com/bruce/rag/service/IRagStoreService.java @@ -2,11 +2,14 @@ package com.bruce.rag.service; import com.baomidou.mybatisplus.extension.service.IService; import com.bruce.rag.dto.request.RagStoreQueryRequest; +import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.entity.RagStore; import java.util.List; public interface IRagStoreService extends IService { - List query(RagStoreQueryRequest request); + List listResponses(); + + List query(RagStoreQueryRequest request); } diff --git a/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java b/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java index 2fd2a96..4399bc8 100644 --- a/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java +++ b/src/main/java/com/bruce/rag/service/impl/RagDocumentServiceImpl.java @@ -2,6 +2,7 @@ package com.bruce.rag.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bruce.rag.dto.request.RagDocumentQueryRequest; +import com.bruce.rag.dto.response.RagDocumentResponse; import com.bruce.rag.entity.RagDocument; import com.bruce.rag.mapper.RagDocumentMapper; import com.bruce.rag.service.IRagDocumentService; @@ -13,17 +14,28 @@ import java.util.List; public class RagDocumentServiceImpl extends ServiceImpl implements IRagDocumentService { @Override - public List query(RagDocumentQueryRequest request) { + public List listResponses() { + return toResponses(list()); + } + + @Override + public List query(RagDocumentQueryRequest request) { if (request == null) { throw new IllegalArgumentException("查询请求不能为空"); } - return lambdaQuery() + return toResponses(lambdaQuery() .eq(request.getStoreId() != null, RagDocument::getStoreId, request.getStoreId()) .eq(request.getAttachmentId() != null, RagDocument::getAttachmentId, request.getAttachmentId()) .eq(request.getParseStatus() != null, RagDocument::getParseStatus, request.getParseStatus()) .eq(request.getIndexStatus() != null, RagDocument::getIndexStatus, request.getIndexStatus()) .eq(request.getEnabled() != null, RagDocument::getEnabled, request.getEnabled()) .orderByDesc(RagDocument::getId) - .list(); + .list()); + } + + private List toResponses(List documents) { + return documents.stream() + .map(RagDocumentResponse::fromEntity) + .toList(); } } diff --git a/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java b/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java index ceb042d..986b9c0 100644 --- a/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java +++ b/src/main/java/com/bruce/rag/service/impl/RagStoreServiceImpl.java @@ -2,6 +2,7 @@ package com.bruce.rag.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bruce.rag.dto.request.RagStoreQueryRequest; +import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.entity.RagStore; import com.bruce.rag.mapper.RagStoreMapper; import com.bruce.rag.service.IRagStoreService; @@ -14,15 +15,26 @@ import java.util.List; public class RagStoreServiceImpl extends ServiceImpl implements IRagStoreService { @Override - public List query(RagStoreQueryRequest request) { + public List listResponses() { + return toResponses(list()); + } + + @Override + public List query(RagStoreQueryRequest request) { if (request == null) { throw new IllegalArgumentException("查询请求不能为空"); } - return lambdaQuery() + return toResponses(lambdaQuery() .eq(StringUtils.hasText(request.getStoreCode()), RagStore::getStoreCode, request.getStoreCode()) .like(StringUtils.hasText(request.getStoreName()), RagStore::getStoreName, request.getStoreName()) .eq(StringUtils.hasText(request.getStatus()), RagStore::getStatus, request.getStatus()) .orderByAsc(RagStore::getStoreCode) - .list(); + .list()); + } + + private List toResponses(List stores) { + return stores.stream() + .map(RagStoreResponse::fromEntity) + .toList(); } } diff --git a/src/test/java/com/bruce/common/attachment/SysAttachmentComponentStructureTests.java b/src/test/java/com/bruce/common/attachment/SysAttachmentComponentStructureTests.java index ede0ab1..07bfdde 100644 --- a/src/test/java/com/bruce/common/attachment/SysAttachmentComponentStructureTests.java +++ b/src/test/java/com/bruce/common/attachment/SysAttachmentComponentStructureTests.java @@ -8,6 +8,7 @@ import com.bruce.common.controller.SysAttachmentController; import com.bruce.common.domain.model.RequestResult; import com.bruce.common.dto.request.SysAttachmentUploadRequest; import com.bruce.common.domain.entity.SysAttachment; +import com.bruce.common.dto.response.SysAttachmentResponse; import com.bruce.common.mapper.SysAttachmentMapper; import com.bruce.common.service.ISysAttachmentService; import com.bruce.common.service.impl.SysAttachmentServiceImpl; @@ -45,6 +46,8 @@ class SysAttachmentComponentStructureTests { assertNotNull(controllerMethod); assertEquals(SysAttachment.class, serviceMethod.getReturnType()); assertEquals(RequestResult.class, controllerMethod.getReturnType()); + assertTrue(controllerMethod.getGenericReturnType().getTypeName().contains("SysAttachmentResponse")); + assertEquals(SysAttachmentResponse.class, SysAttachmentResponse.class.getMethod("fromEntity", SysAttachment.class).getReturnType()); } @Test diff --git a/src/test/java/com/bruce/common/enumconfig/SysEnumBatchSaveValidationTests.java b/src/test/java/com/bruce/common/enumconfig/SysEnumBatchSaveValidationTests.java new file mode 100644 index 0000000..07d7d8d --- /dev/null +++ b/src/test/java/com/bruce/common/enumconfig/SysEnumBatchSaveValidationTests.java @@ -0,0 +1,68 @@ +package com.bruce.common.enumconfig; + +import com.bruce.common.domain.entity.SysEnum; +import com.bruce.common.dto.request.SysEnumBatchSaveRequest; +import com.bruce.common.service.impl.SysEnumServiceImpl; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class SysEnumBatchSaveValidationTests { + + @Test + void batchSaveShouldRejectDuplicateValuesInsideRequest() { + SysEnumServiceImpl service = new SysEnumServiceImpl(); + SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest(); + request.setCatalog("common"); + request.setType("enable_status"); + request.setItems(List.of( + item("启用", 1), + item("可用", 1) + )); + + assertThrows(IllegalArgumentException.class, () -> service.validateBatchSaveRequest(request, List.of())); + } + + @Test + void batchSaveShouldRejectDuplicateValuesFromExistingEnums() { + SysEnumServiceImpl service = new SysEnumServiceImpl(); + SysEnum existing = new SysEnum(); + existing.setCatalog("common"); + existing.setType("enable_status"); + existing.setValue(1); + + SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest(); + request.setCatalog("common"); + request.setType("enable_status"); + request.setItems(List.of(item("启用", 1))); + + assertThrows( + IllegalArgumentException.class, + () -> service.validateBatchSaveRequest(request, List.of(existing)) + ); + } + + @Test + void batchSaveShouldAcceptUniqueValues() { + SysEnumServiceImpl service = new SysEnumServiceImpl(); + SysEnumBatchSaveRequest request = new SysEnumBatchSaveRequest(); + request.setCatalog("common"); + request.setType("enable_status"); + request.setItems(List.of( + item("禁用", 0), + item("启用", 1) + )); + + assertDoesNotThrow(() -> service.validateBatchSaveRequest(request, List.of())); + } + + private SysEnumBatchSaveRequest.Item item(String name, Integer value) { + SysEnumBatchSaveRequest.Item item = new SysEnumBatchSaveRequest.Item(); + item.setName(name); + item.setValue(value); + return item; + } +} diff --git a/src/test/java/com/bruce/common/enumconfig/SysEnumComponentStructureTests.java b/src/test/java/com/bruce/common/enumconfig/SysEnumComponentStructureTests.java index b98ff85..02e5a2c 100644 --- a/src/test/java/com/bruce/common/enumconfig/SysEnumComponentStructureTests.java +++ b/src/test/java/com/bruce/common/enumconfig/SysEnumComponentStructureTests.java @@ -6,8 +6,11 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bruce.common.controller.SysEnumController; import com.bruce.common.domain.entity.SysEnum; import com.bruce.common.domain.model.RequestResult; +import com.bruce.common.dto.request.SysEnumBatchSaveRequest; +import com.bruce.common.dto.request.SysEnumManageQueryRequest; import com.bruce.common.dto.request.SysEnumQueryRequest; import com.bruce.common.dto.request.SysEnumSaveRequest; +import com.bruce.common.dto.response.SysEnumResponse; import com.bruce.common.mapper.SysEnumMapper; import com.bruce.common.service.ISysEnumService; import com.bruce.common.service.impl.SysEnumServiceImpl; @@ -45,20 +48,56 @@ class SysEnumComponentStructureTests { @Test void sysEnumShouldExposeSaveOrUpdateAndDeleteInterfaces() throws NoSuchMethodException { Method saveOrUpdateMethod = ISysEnumService.class.getMethod("saveOrUpdate", SysEnumSaveRequest.class); + Method batchSaveMethod = ISysEnumService.class.getMethod("batchSave", SysEnumBatchSaveRequest.class); Method controllerSaveOrUpdateMethod = SysEnumController.class.getMethod("saveOrUpdate", SysEnumSaveRequest.class); + Method controllerBatchSaveMethod = SysEnumController.class.getMethod("batchSave", SysEnumBatchSaveRequest.class); Method deleteMethod = SysEnumController.class.getMethod("deleteById", Long.class); Method listMethod = SysEnumController.class.getMethod("list"); assertNotNull(saveOrUpdateMethod); + assertNotNull(batchSaveMethod); assertNotNull(controllerSaveOrUpdateMethod); + assertNotNull(controllerBatchSaveMethod); assertNotNull(deleteMethod); assertNotNull(listMethod); assertEquals(boolean.class, saveOrUpdateMethod.getReturnType()); + assertEquals(boolean.class, batchSaveMethod.getReturnType()); assertEquals(RequestResult.class, controllerSaveOrUpdateMethod.getReturnType()); + assertEquals(RequestResult.class, controllerBatchSaveMethod.getReturnType()); assertEquals(RequestResult.class, deleteMethod.getReturnType()); assertEquals(RequestResult.class, listMethod.getReturnType()); } + @Test + void sysEnumShouldExposeManagementQueryWithoutChangingCatalogTypeQuery() throws NoSuchMethodException { + Method serviceMethod = ISysEnumService.class.getMethod("listForManagement", SysEnumManageQueryRequest.class); + Method controllerMethod = SysEnumController.class.getMethod("queryForManagement", SysEnumManageQueryRequest.class); + Method catalogTypeMethod = ISysEnumService.class.getMethod("listByCatalogAndType", SysEnumQueryRequest.class); + + assertNotNull(serviceMethod); + assertNotNull(controllerMethod); + assertNotNull(catalogTypeMethod); + assertEquals(List.class, serviceMethod.getReturnType()); + assertEquals(RequestResult.class, controllerMethod.getReturnType()); + assertEquals(List.class, catalogTypeMethod.getReturnType()); + assertTrue(serviceMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); + } + + @Test + void sysEnumControllerShouldReturnDtoContracts() throws NoSuchMethodException { + Method listMethod = SysEnumController.class.getMethod("list"); + Method manageQueryMethod = SysEnumController.class.getMethod("queryForManagement", SysEnumManageQueryRequest.class); + Method detailMethod = SysEnumController.class.getMethod("getById", Long.class); + Method serviceListMethod = ISysEnumService.class.getMethod("listResponses"); + Method responseFactory = SysEnumResponse.class.getMethod("fromEntity", SysEnum.class); + + assertTrue(serviceListMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); + assertTrue(listMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); + assertTrue(manageQueryMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); + assertTrue(detailMethod.getGenericReturnType().getTypeName().contains("SysEnumResponse")); + assertEquals(SysEnumResponse.class, responseFactory.getReturnType()); + } + @Test void sysEnumShouldProvideManualInitTestEntry() throws NoSuchMethodException { Method initMethod = SysEnumDataInitTests.class.getMethod("initDefaultEnums"); diff --git a/src/test/java/com/bruce/rag/RagComponentStructureTests.java b/src/test/java/com/bruce/rag/RagComponentStructureTests.java index 327416d..6e31d57 100644 --- a/src/test/java/com/bruce/rag/RagComponentStructureTests.java +++ b/src/test/java/com/bruce/rag/RagComponentStructureTests.java @@ -9,6 +9,8 @@ import com.bruce.rag.controller.RagDocumentController; import com.bruce.rag.controller.RagStoreController; import com.bruce.rag.dto.request.RagDocumentQueryRequest; import com.bruce.rag.dto.request.RagStoreQueryRequest; +import com.bruce.rag.dto.response.RagDocumentResponse; +import com.bruce.rag.dto.response.RagStoreResponse; import com.bruce.rag.entity.RagDocument; import com.bruce.rag.entity.RagStore; import com.bruce.rag.mapper.RagDocumentMapper; @@ -42,19 +44,31 @@ class RagComponentStructureTests { void ragControllersShouldExposeRequestResultAndQueryDtoMethods() throws NoSuchMethodException { Method storeListMethod = RagStoreController.class.getMethod("list"); Method storeQueryMethod = RagStoreController.class.getMethod("query", RagStoreQueryRequest.class); + Method storeResponseListMethod = IRagStoreService.class.getMethod("listResponses"); Method storeServiceQueryMethod = IRagStoreService.class.getMethod("query", RagStoreQueryRequest.class); Method documentListMethod = RagDocumentController.class.getMethod("list"); Method documentQueryMethod = RagDocumentController.class.getMethod("query", RagDocumentQueryRequest.class); + Method documentResponseListMethod = IRagDocumentService.class.getMethod("listResponses"); Method documentServiceQueryMethod = IRagDocumentService.class.getMethod("query", RagDocumentQueryRequest.class); assertEquals(RequestResult.class, storeListMethod.getReturnType()); assertEquals(RequestResult.class, storeQueryMethod.getReturnType()); assertEquals(List.class, storeServiceQueryMethod.getReturnType()); + assertTrue(storeResponseListMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); + assertTrue(storeServiceQueryMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); + assertTrue(storeListMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); + assertTrue(storeQueryMethod.getGenericReturnType().getTypeName().contains("RagStoreResponse")); + assertEquals(RagStoreResponse.class, RagStoreResponse.class.getMethod("fromEntity", RagStore.class).getReturnType()); assertEquals(RequestResult.class, documentListMethod.getReturnType()); assertEquals(RequestResult.class, documentQueryMethod.getReturnType()); assertEquals(List.class, documentServiceQueryMethod.getReturnType()); + assertTrue(documentResponseListMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); + assertTrue(documentServiceQueryMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); + assertTrue(documentListMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); + assertTrue(documentQueryMethod.getGenericReturnType().getTypeName().contains("RagDocumentResponse")); + assertEquals(RagDocumentResponse.class, RagDocumentResponse.class.getMethod("fromEntity", RagDocument.class).getReturnType()); } @Test