feat:统一公共审计填充并调整系统枚举接口风格
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package com.bruce.common.config;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class EntityAuditMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
private static final String SYSTEM_USER = "system";
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
Date now = new Date();
|
||||
strictInsertFill(metaObject, "createTime", Date.class, now);
|
||||
strictInsertFill(metaObject, "updateTime", Date.class, now);
|
||||
strictInsertFill(metaObject, "createBy", String.class, SYSTEM_USER);
|
||||
strictInsertFill(metaObject, "updateBy", String.class, SYSTEM_USER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
|
||||
strictUpdateFill(metaObject, "updateBy", String.class, SYSTEM_USER);
|
||||
}
|
||||
}
|
||||
@@ -9,64 +9,88 @@ 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;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "系统枚举管理")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/sys-enums")
|
||||
@RequestMapping("/api/sys-enum")
|
||||
public class SysEnumController {
|
||||
|
||||
@Autowired
|
||||
private ISysEnumService sysEnumService;
|
||||
|
||||
@Operation(summary = "查询全部系统枚举")
|
||||
@GetMapping
|
||||
@PostMapping("/list")
|
||||
public RequestResult<List<SysEnumResponse>> list() {
|
||||
return RequestResult.success(sysEnumService.listResponses());
|
||||
log.info("SysEnumController.list start");
|
||||
List<SysEnumResponse> responses = sysEnumService.listResponses();
|
||||
log.info("SysEnumController.list success, count={}", responses.size());
|
||||
return RequestResult.success(responses);
|
||||
}
|
||||
|
||||
@Operation(summary = "根据模块和类型查询系统枚举")
|
||||
@PostMapping("/query")
|
||||
public RequestResult<List<SysEnumResponse>> queryByCatalogAndType(@RequestBody SysEnumQueryRequest request) {
|
||||
return RequestResult.success(sysEnumService.listByCatalogAndTypeResponses(request));
|
||||
log.info("SysEnumController.queryByCatalogAndType start, request={}", request);
|
||||
List<SysEnumResponse> responses = sysEnumService.listByCatalogAndTypeResponses(request);
|
||||
log.info("SysEnumController.queryByCatalogAndType success, count={}", responses.size());
|
||||
return RequestResult.success(responses);
|
||||
}
|
||||
|
||||
@Operation(summary = "管理端查询系统枚举")
|
||||
@PostMapping("/manage/query")
|
||||
@PostMapping("/queryForManagement")
|
||||
public RequestResult<List<SysEnumResponse>> queryForManagement(@RequestBody(required = false) SysEnumManageQueryRequest request) {
|
||||
return RequestResult.success(sysEnumService.listForManagement(request));
|
||||
log.info("SysEnumController.queryForManagement start, request={}", request);
|
||||
List<SysEnumResponse> responses = sysEnumService.listForManagement(request);
|
||||
log.info("SysEnumController.queryForManagement success, count={}", responses.size());
|
||||
return RequestResult.success(responses);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询系统枚举详情")
|
||||
@GetMapping("/{id}")
|
||||
public RequestResult<SysEnumResponse> getById(@PathVariable Long id) {
|
||||
return RequestResult.success(sysEnumService.getResponseById(id));
|
||||
@GetMapping("/detail")
|
||||
public RequestResult<SysEnumResponse> getById(@RequestParam("id") Long id) {
|
||||
log.info("SysEnumController.getById start, id={}", id);
|
||||
SysEnumResponse response = sysEnumService.getResponseById(id);
|
||||
log.info("SysEnumController.getById success, id={}, found={}", id, response != null);
|
||||
return RequestResult.success(response);
|
||||
}
|
||||
|
||||
@Operation(summary = "新增或修改系统枚举")
|
||||
@PostMapping
|
||||
@PostMapping("/save")
|
||||
public RequestResult<Boolean> saveOrUpdate(@RequestBody SysEnumSaveRequest request) {
|
||||
return RequestResult.success(sysEnumService.saveOrUpdate(request));
|
||||
log.info("SysEnumController.saveOrUpdate start, request={}", request);
|
||||
Boolean result = sysEnumService.saveOrUpdate(request);
|
||||
log.info("SysEnumController.saveOrUpdate success, id={}, catalog={}, type={}, value={}, result={}",
|
||||
request.getId(), request.getCatalog(), request.getType(), request.getValue(), result);
|
||||
return RequestResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "批量新增系统枚举")
|
||||
@PostMapping("/batch")
|
||||
@PostMapping("/batchSave")
|
||||
public RequestResult<Boolean> batchSave(@RequestBody SysEnumBatchSaveRequest request) {
|
||||
return RequestResult.success(sysEnumService.batchSave(request));
|
||||
log.info("SysEnumController.batchSave start, request={}", request);
|
||||
Boolean result = sysEnumService.batchSave(request);
|
||||
log.info("SysEnumController.batchSave success, catalog={}, type={}, itemCount={}, result={}",
|
||||
request.getCatalog(), request.getType(), request.getItems() == null ? 0 : request.getItems().size(), result);
|
||||
return RequestResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除系统枚举")
|
||||
@DeleteMapping("/{id}")
|
||||
public RequestResult<Boolean> deleteById(@PathVariable Long id) {
|
||||
return RequestResult.success(sysEnumService.removeById(id));
|
||||
@PostMapping("/delete")
|
||||
public RequestResult<Boolean> deleteById(@RequestParam("id") Long id) {
|
||||
log.info("SysEnumController.deleteById start, id={}", id);
|
||||
Boolean result = sysEnumService.removeById(id);
|
||||
log.info("SysEnumController.deleteById success, id={}, result={}", id, result);
|
||||
return RequestResult.success(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bruce.common.domain.model;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -19,21 +20,21 @@ public class BaseEntity {
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建者")
|
||||
@TableField(value = "create_by")
|
||||
@TableField(value = "create_by", fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
@Schema(description = "创建时间", example = "2026-05-18 20:00:00")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(value = "create_time")
|
||||
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
@Schema(description = "更新者")
|
||||
@TableField(value = "update_by")
|
||||
@TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
@Schema(description = "更新时间", example = "2026-05-18 20:00:00")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@TableField(value = "update_time")
|
||||
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
@Schema(description = "版本")
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.bruce.common.handler;
|
||||
|
||||
import com.bruce.common.domain.model.RequestResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<RequestResult<Void>> handleIllegalArgumentException(IllegalArgumentException exception) {
|
||||
log.warn("GlobalExceptionHandler.handleIllegalArgumentException, message={}", exception.getMessage(), exception);
|
||||
return buildResponse(HttpStatus.BAD_REQUEST, exception.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<RequestResult<Void>> handleException(Exception exception) {
|
||||
log.error("GlobalExceptionHandler.handleException", exception);
|
||||
return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR, "系统内部错误,请稍后重试");
|
||||
}
|
||||
|
||||
private ResponseEntity<RequestResult<Void>> buildResponse(HttpStatus status, String message) {
|
||||
return ResponseEntity.status(status)
|
||||
.body(RequestResult.fail(String.valueOf(status.value()), message));
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ 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 lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -16,36 +17,47 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> implements ISysEnumService {
|
||||
|
||||
@Override
|
||||
public List<SysEnum> listByCatalogAndType(SysEnumQueryRequest request) {
|
||||
log.info("SysEnumServiceImpl.listByCatalogAndType start, request={}", request);
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("查询请求不能为空");
|
||||
}
|
||||
return lambdaQuery()
|
||||
List<SysEnum> result = lambdaQuery()
|
||||
.eq(StringUtils.hasText(request.getCatalog()), SysEnum::getCatalog, request.getCatalog())
|
||||
.eq(StringUtils.hasText(request.getType()), SysEnum::getType, request.getType())
|
||||
.orderByAsc(SysEnum::getSort)
|
||||
.list();
|
||||
log.info("SysEnumServiceImpl.listByCatalogAndType success, count={}", result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysEnumResponse> listResponses() {
|
||||
return toResponses(list());
|
||||
log.info("SysEnumServiceImpl.listResponses start");
|
||||
List<SysEnumResponse> responses = toResponses(list());
|
||||
log.info("SysEnumServiceImpl.listResponses success, count={}", responses.size());
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysEnumResponse> listByCatalogAndTypeResponses(SysEnumQueryRequest request) {
|
||||
return toResponses(listByCatalogAndType(request));
|
||||
log.info("SysEnumServiceImpl.listByCatalogAndTypeResponses start");
|
||||
List<SysEnumResponse> responses = toResponses(listByCatalogAndType(request));
|
||||
log.info("SysEnumServiceImpl.listByCatalogAndTypeResponses success, count={}", responses.size());
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysEnumResponse> listForManagement(SysEnumManageQueryRequest request) {
|
||||
log.info("SysEnumServiceImpl.listForManagement start, request={}", request);
|
||||
SysEnumManageQueryRequest queryRequest = request == null ? new SysEnumManageQueryRequest() : request;
|
||||
String keyword = queryRequest.getKeyword();
|
||||
return toResponses(lambdaQuery()
|
||||
List<SysEnumResponse> responses = 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
|
||||
@@ -63,15 +75,21 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
|
||||
.orderByAsc(SysEnum::getSort)
|
||||
.orderByAsc(SysEnum::getId)
|
||||
.list());
|
||||
log.info("SysEnumServiceImpl.listForManagement success, count={}", responses.size());
|
||||
return responses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysEnumResponse getResponseById(Long id) {
|
||||
return SysEnumResponse.fromEntity(getById(id));
|
||||
log.info("SysEnumServiceImpl.getResponseById start, id={}", id);
|
||||
SysEnumResponse response = SysEnumResponse.fromEntity(getById(id));
|
||||
log.info("SysEnumServiceImpl.getResponseById success, id={}, found={}", id, response != null);
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveOrUpdate(SysEnumSaveRequest request) {
|
||||
log.info("SysEnumServiceImpl.saveOrUpdate start, request={}", request);
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("保存请求不能为空");
|
||||
}
|
||||
@@ -85,11 +103,15 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
|
||||
sysEnum.setStrvalue(request.getStrvalue());
|
||||
sysEnum.setSort(request.getSort());
|
||||
sysEnum.setRemark(request.getRemark());
|
||||
return super.saveOrUpdate(sysEnum);
|
||||
boolean result = super.saveOrUpdate(sysEnum);
|
||||
log.info("SysEnumServiceImpl.saveOrUpdate success, id={}, catalog={}, type={}, value={}, result={}",
|
||||
request.getId(), request.getCatalog(), request.getType(), request.getValue(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean batchSave(SysEnumBatchSaveRequest request) {
|
||||
log.info("SysEnumServiceImpl.batchSave start, request={}", request);
|
||||
List<SysEnum> 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())
|
||||
@@ -109,10 +131,14 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
|
||||
return sysEnum;
|
||||
})
|
||||
.toList();
|
||||
return saveBatch(enums);
|
||||
boolean result = saveBatch(enums);
|
||||
log.info("SysEnumServiceImpl.batchSave success, catalog={}, type={}, itemCount={}, result={}",
|
||||
request.getCatalog(), request.getType(), enums.size(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void validateBatchSaveRequest(SysEnumBatchSaveRequest request, List<SysEnum> existingEnums) {
|
||||
log.info("SysEnumServiceImpl.validateBatchSaveRequest start");
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("批量保存请求不能为空");
|
||||
}
|
||||
@@ -153,6 +179,8 @@ public class SysEnumServiceImpl extends ServiceImpl<SysEnumMapper, SysEnum> impl
|
||||
throw new IllegalArgumentException("枚举值已存在: " + value);
|
||||
}
|
||||
}
|
||||
log.info("SysEnumServiceImpl.validateBatchSaveRequest success, catalog={}, type={}, requestValueCount={}, existingValueCount={}",
|
||||
request.getCatalog(), request.getType(), requestValues.size(), existingValues.size());
|
||||
}
|
||||
|
||||
private List<SysEnumResponse> toResponses(List<SysEnum> enums) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.bruce.common.config;
|
||||
|
||||
import com.bruce.rag.entity.RagStore;
|
||||
import org.apache.ibatis.reflection.SystemMetaObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
class EntityAuditMetaObjectHandlerTests {
|
||||
|
||||
@Test
|
||||
void insertFillShouldPopulateAuditFields() {
|
||||
EntityAuditMetaObjectHandler handler = new EntityAuditMetaObjectHandler();
|
||||
RagStore entity = new RagStore();
|
||||
|
||||
handler.insertFill(SystemMetaObject.forObject(entity));
|
||||
|
||||
assertNotNull(entity.getCreateTime());
|
||||
assertNotNull(entity.getUpdateTime());
|
||||
assertEquals("system", entity.getCreateBy());
|
||||
assertEquals("system", entity.getUpdateBy());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateFillShouldRefreshUpdateAuditFields() {
|
||||
EntityAuditMetaObjectHandler handler = new EntityAuditMetaObjectHandler();
|
||||
RagStore entity = new RagStore();
|
||||
entity.setUpdateBy("oldUser");
|
||||
|
||||
handler.updateFill(SystemMetaObject.forObject(entity));
|
||||
|
||||
assertNotNull(entity.getUpdateTime());
|
||||
assertEquals("system", entity.getUpdateBy());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.bruce.common.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.Version;
|
||||
import com.bruce.common.domain.model.BaseEntity;
|
||||
@@ -65,4 +67,21 @@ class EntityStructureTests {
|
||||
assertTrue(Arrays.stream(SysEnum.class.getDeclaredFields()).noneMatch(field -> "version".equals(field.getName())));
|
||||
assertTrue(Arrays.stream(SysAttachment.class.getDeclaredFields()).noneMatch(field -> "version".equals(field.getName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void auditFieldsShouldUseMybatisPlusAutoFill() throws NoSuchFieldException {
|
||||
TableField createBy = BaseEntity.class.getDeclaredField("createBy").getAnnotation(TableField.class);
|
||||
TableField createTime = BaseEntity.class.getDeclaredField("createTime").getAnnotation(TableField.class);
|
||||
TableField updateBy = BaseEntity.class.getDeclaredField("updateBy").getAnnotation(TableField.class);
|
||||
TableField updateTime = BaseEntity.class.getDeclaredField("updateTime").getAnnotation(TableField.class);
|
||||
|
||||
assertNotNull(createBy);
|
||||
assertNotNull(createTime);
|
||||
assertNotNull(updateBy);
|
||||
assertNotNull(updateTime);
|
||||
assertEquals(FieldFill.INSERT, createBy.fill());
|
||||
assertEquals(FieldFill.INSERT, createTime.fill());
|
||||
assertEquals(FieldFill.INSERT_UPDATE, updateBy.fill());
|
||||
assertEquals(FieldFill.INSERT_UPDATE, updateTime.fill());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.bruce.common.handler;
|
||||
|
||||
import com.bruce.common.domain.model.RequestResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
class GlobalExceptionHandlerTests {
|
||||
|
||||
@Test
|
||||
void shouldReturnStructuredBadRequestForIllegalArgumentException() {
|
||||
GlobalExceptionHandler handler = new GlobalExceptionHandler();
|
||||
ResponseEntity<RequestResult<Void>> response = handler.handleIllegalArgumentException(
|
||||
new IllegalArgumentException("知识库编码已存在: TEST-1"));
|
||||
|
||||
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
|
||||
assertNotNull(response.getBody());
|
||||
assertEquals("400", response.getBody().getResultcode());
|
||||
assertEquals("知识库编码已存在: TEST-1", response.getBody().getMessage());
|
||||
assertEquals(null, response.getBody().getData());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user