feat: 添加异常日志功能并优化UI样式
refactor: 重构后端查询逻辑和API响应处理 fix: 修复用户角色更新和文件上传问题 test: 添加前端性能测试脚本和E2E测试用例 chore: 更新依赖版本和配置文件 docs: 添加环境检查脚本和测试文档 style: 统一表格标签样式和路由命名 perf: 优化前端页面加载速度和响应时间
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
package cn.novalon.manage.notify.core.query;
|
||||
|
||||
/**
|
||||
* 用户消息查询对象
|
||||
*
|
||||
* @author 张翔
|
||||
* @date 2026-03-13
|
||||
*/
|
||||
public class SysUserMessageQuery {
|
||||
|
||||
private Long userId;
|
||||
private String isRead;
|
||||
private String keyword;
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getIsRead() {
|
||||
return isRead;
|
||||
}
|
||||
|
||||
public void setIsRead(String isRead) {
|
||||
this.isRead = isRead;
|
||||
}
|
||||
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
public void setKeyword(String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
}
|
||||
+28
-3
@@ -2,16 +2,24 @@ package cn.novalon.manage.notify.handler;
|
||||
|
||||
import cn.novalon.manage.notify.core.domain.SysNotice;
|
||||
import cn.novalon.manage.notify.core.service.ISysNoticeService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class SysNoticeHandler {
|
||||
|
||||
private final ISysNoticeService noticeService;
|
||||
private static final List<String> VALID_NOTICE_TYPES = Arrays.asList("1", "2");
|
||||
private static final List<String> VALID_STATUSES = Arrays.asList("0", "1");
|
||||
|
||||
public SysNoticeHandler(ISysNoticeService noticeService) {
|
||||
this.noticeService = noticeService;
|
||||
@@ -37,8 +45,23 @@ public class SysNoticeHandler {
|
||||
|
||||
public Mono<ServerResponse> createNotice(ServerRequest request) {
|
||||
return request.bodyToMono(SysNotice.class)
|
||||
.filter(notice -> notice.getNoticeTitle() != null && !notice.getNoticeTitle().trim().isEmpty())
|
||||
.switchIfEmpty(Mono.error(new IllegalArgumentException("公告标题不能为空")))
|
||||
.filter(notice -> VALID_NOTICE_TYPES.contains(notice.getNoticeType()))
|
||||
.switchIfEmpty(Mono.error(new IllegalArgumentException("公告类型必须是1(通知)或2(公告)")))
|
||||
.filter(notice -> notice.getNoticeContent() != null && !notice.getNoticeContent().trim().isEmpty())
|
||||
.switchIfEmpty(Mono.error(new IllegalArgumentException("公告内容不能为空")))
|
||||
.filter(notice -> notice.getStatus() == null || VALID_STATUSES.contains(notice.getStatus()))
|
||||
.switchIfEmpty(Mono.error(new IllegalArgumentException("状态必须是0(正常)或1(关闭)")))
|
||||
.flatMap(noticeService::createNotice)
|
||||
.flatMap(notice -> ServerResponse.ok().bodyValue(notice));
|
||||
.flatMap(notice -> ServerResponse.created(request.uriBuilder().path("/{id}").build(notice.getId())).bodyValue(notice))
|
||||
.onErrorResume(IllegalArgumentException.class, ex -> {
|
||||
return ServerResponse.badRequest().bodyValue(Map.of(
|
||||
"code", HttpStatus.BAD_REQUEST.value(),
|
||||
"message", ex.getMessage(),
|
||||
"timestamp", LocalDateTime.now()
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
public Mono<ServerResponse> updateNotice(ServerRequest request) {
|
||||
@@ -51,8 +74,10 @@ public class SysNoticeHandler {
|
||||
|
||||
public Mono<ServerResponse> deleteNotice(ServerRequest request) {
|
||||
Long id = Long.parseLong(request.pathVariable("id"));
|
||||
return noticeService.deleteNotice(id)
|
||||
.then(ServerResponse.ok().build())
|
||||
return noticeService.getNoticeById(id)
|
||||
.filter(notice -> notice.getDeletedAt() == null)
|
||||
.flatMap(notice -> noticeService.deleteNotice(id)
|
||||
.then(ServerResponse.noContent().build()))
|
||||
.switchIfEmpty(ServerResponse.notFound().build());
|
||||
}
|
||||
}
|
||||
+12
-11
@@ -19,7 +19,6 @@ import java.time.LocalDateTime;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@@ -132,9 +131,9 @@ class SysNoticeHandlerTest {
|
||||
void testCreateNotice() {
|
||||
SysNotice newNotice = new SysNotice();
|
||||
newNotice.setNoticeTitle("新通知");
|
||||
newNotice.setNoticeType("SYSTEM");
|
||||
newNotice.setNoticeType("1");
|
||||
newNotice.setNoticeContent("测试内容");
|
||||
newNotice.setStatus("DRAFT");
|
||||
newNotice.setStatus("0");
|
||||
|
||||
when(noticeService.createNotice(any(SysNotice.class))).thenReturn(Mono.just(testNotice));
|
||||
|
||||
@@ -144,7 +143,7 @@ class SysNoticeHandlerTest {
|
||||
|
||||
StepVerifier.create(response)
|
||||
.expectNextMatches(serverResponse ->
|
||||
serverResponse.statusCode() == HttpStatus.OK)
|
||||
serverResponse.statusCode() == HttpStatus.CREATED)
|
||||
.verifyComplete();
|
||||
|
||||
verify(noticeService).createNotice(any(SysNotice.class));
|
||||
@@ -154,9 +153,9 @@ class SysNoticeHandlerTest {
|
||||
void testCreateNotice_WithAllFields() {
|
||||
SysNotice newNotice = new SysNotice();
|
||||
newNotice.setNoticeTitle("完整通知");
|
||||
newNotice.setNoticeType("ANNOUNCEMENT");
|
||||
newNotice.setNoticeType("2");
|
||||
newNotice.setNoticeContent("完整内容");
|
||||
newNotice.setStatus("PUBLISHED");
|
||||
newNotice.setStatus("1");
|
||||
newNotice.setCreateBy("admin");
|
||||
|
||||
when(noticeService.createNotice(any(SysNotice.class))).thenReturn(Mono.just(testNotice));
|
||||
@@ -167,7 +166,7 @@ class SysNoticeHandlerTest {
|
||||
|
||||
StepVerifier.create(response)
|
||||
.expectNextMatches(serverResponse ->
|
||||
serverResponse.statusCode() == HttpStatus.OK)
|
||||
serverResponse.statusCode() == HttpStatus.CREATED)
|
||||
.verifyComplete();
|
||||
|
||||
verify(noticeService).createNotice(any(SysNotice.class));
|
||||
@@ -218,6 +217,7 @@ class SysNoticeHandlerTest {
|
||||
|
||||
@Test
|
||||
void testDeleteNotice() {
|
||||
when(noticeService.getNoticeById(1L)).thenReturn(Mono.just(testNotice));
|
||||
when(noticeService.deleteNotice(1L)).thenReturn(Mono.empty());
|
||||
|
||||
ServerRequest request = MockServerRequest.builder()
|
||||
@@ -227,15 +227,16 @@ class SysNoticeHandlerTest {
|
||||
|
||||
StepVerifier.create(response)
|
||||
.expectNextMatches(serverResponse ->
|
||||
serverResponse.statusCode() == HttpStatus.OK)
|
||||
serverResponse.statusCode() == HttpStatus.NO_CONTENT)
|
||||
.verifyComplete();
|
||||
|
||||
verify(noticeService).getNoticeById(1L);
|
||||
verify(noticeService).deleteNotice(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteNotice_NotFound() {
|
||||
when(noticeService.deleteNotice(999L)).thenReturn(Mono.empty());
|
||||
when(noticeService.getNoticeById(999L)).thenReturn(Mono.empty());
|
||||
|
||||
ServerRequest request = MockServerRequest.builder()
|
||||
.pathVariable("id", "999")
|
||||
@@ -244,9 +245,9 @@ class SysNoticeHandlerTest {
|
||||
|
||||
StepVerifier.create(response)
|
||||
.expectNextMatches(serverResponse ->
|
||||
serverResponse.statusCode() == HttpStatus.OK)
|
||||
serverResponse.statusCode() == HttpStatus.NOT_FOUND)
|
||||
.verifyComplete();
|
||||
|
||||
verify(noticeService).deleteNotice(999L);
|
||||
verify(noticeService).getNoticeById(999L);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user