diff --git a/src/main/java/com/sb/web/board/controller/BoardController.java b/src/main/java/com/sb/web/board/controller/BoardController.java index c722bf8..57906d4 100644 --- a/src/main/java/com/sb/web/board/controller/BoardController.java +++ b/src/main/java/com/sb/web/board/controller/BoardController.java @@ -9,6 +9,7 @@ import com.sb.web.board.dto.PostDetail; import com.sb.web.board.dto.PostRequest; import com.sb.web.board.dto.PostSummary; import com.sb.web.board.dto.Recommender; +import com.sb.web.board.dto.ReportedItem; import com.sb.web.board.dto.TagCategoryResponse; import com.sb.web.board.dto.VoteRequest; import com.sb.web.board.dto.VoteResponse; @@ -223,4 +224,20 @@ public class BoardController { boardService.unblockComment(commentId, current); return ResponseEntity.noContent().build(); } + + /** 신고된 글/댓글 목록 (관리자) — 대상별 신고 수 집계 */ + @GetMapping("/reports") + public List reports( + @RequestAttribute(AuthInterceptor.CURRENT_MEMBER) SessionUser current) { + return boardService.listReportedItems(current); + } + + /** 신고 무시 (관리자) — 블라인드 없이 신고 기록만 초기화 */ + @PostMapping("/reports/dismiss") + public ResponseEntity dismissReport( + @RequestBody Map body, + @RequestAttribute(AuthInterceptor.CURRENT_MEMBER) SessionUser current) { + boardService.dismissReports(body.get("targetType"), Long.valueOf(body.get("targetId")), current); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/sb/web/board/dto/ReportedItem.java b/src/main/java/com/sb/web/board/dto/ReportedItem.java new file mode 100644 index 0000000..209be58 --- /dev/null +++ b/src/main/java/com/sb/web/board/dto/ReportedItem.java @@ -0,0 +1,24 @@ +package com.sb.web.board.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 신고 누적 항목 (관리자 신고 관리 화면). 대상별(글/댓글)로 신고 수를 집계. + */ +@Data +public class ReportedItem { + + private String targetType; // POST / COMMENT + private Long targetId; // 대상(글/댓글) id + private Long postId; // 링크용 글 id (POST=자기 자신, COMMENT=상위 글) + private String category; // 상위 글 게시판(community/saving/tips) + private String title; // 글 제목 (댓글이면 상위 글 제목) + private String content; // 본문/댓글 내용 (앞부분 요약) + private Long authorId; // 작성자 id + private String authorName; // 작성자 표시명 + private Boolean blocked; // 이미 블라인드 되었는지 + private Integer reportCount; // 누적 신고 수 + private LocalDateTime lastReportedAt; // 마지막 신고 시각 +} diff --git a/src/main/java/com/sb/web/board/mapper/ReportMapper.java b/src/main/java/com/sb/web/board/mapper/ReportMapper.java index df62698..e01410a 100644 --- a/src/main/java/com/sb/web/board/mapper/ReportMapper.java +++ b/src/main/java/com/sb/web/board/mapper/ReportMapper.java @@ -1,8 +1,11 @@ package com.sb.web.board.mapper; +import com.sb.web.board.dto.ReportedItem; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import java.util.List; + /** * 신고(report) 매퍼 — 글/댓글 신고 누적 집계. */ @@ -15,6 +18,9 @@ public interface ReportMapper { @Param("memberId") Long memberId, @Param("reason") String reason); + /** 신고된 글/댓글 목록 (대상별 집계 — 관리자 화면) */ + List listReported(); + int countByTarget(@Param("targetType") String targetType, @Param("targetId") Long targetId); int deleteByTarget(@Param("targetType") String targetType, @Param("targetId") Long targetId); diff --git a/src/main/java/com/sb/web/board/service/BoardService.java b/src/main/java/com/sb/web/board/service/BoardService.java index c881d0f..a2e184c 100644 --- a/src/main/java/com/sb/web/board/service/BoardService.java +++ b/src/main/java/com/sb/web/board/service/BoardService.java @@ -11,6 +11,7 @@ import com.sb.web.board.dto.PostDetail; import com.sb.web.board.dto.PostRequest; import com.sb.web.board.dto.PostSummary; import com.sb.web.board.dto.Recommender; +import com.sb.web.board.dto.ReportedItem; import com.sb.web.board.dto.VoteResponse; import com.sb.web.board.mapper.CommentMapper; import com.sb.web.board.mapper.PostMapper; @@ -293,6 +294,23 @@ public class BoardService { } } + /** 신고된 글/댓글 목록 (관리자 전용) — 대상별 신고 수 집계 */ + @Transactional(readOnly = true) + public List listReportedItems(SessionUser user) { + assertAdmin(user); + return reportMapper.listReported(); + } + + /** 신고 무시 (관리자 전용) — 블라인드 없이 신고 기록만 초기화 */ + @Transactional + public void dismissReports(String targetType, Long targetId, SessionUser user) { + assertAdmin(user); + if (!T_POST.equals(targetType) && !T_COMMENT.equals(targetType)) { + throw new ApiException(HttpStatus.BAD_REQUEST, "잘못된 신고 대상 유형입니다."); + } + reportMapper.deleteByTarget(targetType, targetId); + } + /* ===================== 추천/비추천 ===================== */ /** 게시글 추천/비추천 토글. 같은 표 재요청 시 취소, 반대면 전환. */ diff --git a/src/main/resources/mapper/ReportMapper.xml b/src/main/resources/mapper/ReportMapper.xml index cbf94b0..ad352aa 100644 --- a/src/main/resources/mapper/ReportMapper.xml +++ b/src/main/resources/mapper/ReportMapper.xml @@ -12,6 +12,29 @@ SELECT COUNT(*) FROM report WHERE target_type = #{targetType} AND target_id = #{targetId} + + + DELETE FROM report WHERE target_type = #{targetType} AND target_id = #{targetId}