From 59f38b33487867f79ed4265a8118d5b0a8ab970c Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Sun, 28 Jun 2026 18:05:43 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B2=8C=EC=8B=9C=ED=8C=90=20=EC=8B=A0?= =?UTF-8?q?=EA=B3=A0=20UI=20=E2=80=94=20=EA=B8=80/=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=8B=A0=EA=B3=A0=20=EB=B2=84=ED=8A=BC=20+=20=EB=B8=94?= =?UTF-8?q?=EB=9D=BC=EC=9D=B8=EB=93=9C=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 작성자·관리자 외 신고 버튼(글 액션·각 댓글) - 신고 누적 블라인드 댓글: 비관리자 가림, 관리자만 본문 + 신고 블라인드 뱃지 - 신고 후 새로고침으로 상태 반영 Co-Authored-By: Claude Opus 4.8 --- src/api/boardApi.js | 7 ++++ src/views/board/BoardDetailView.vue | 59 ++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/api/boardApi.js b/src/api/boardApi.js index 3aba149..8bed804 100644 --- a/src/api/boardApi.js +++ b/src/api/boardApi.js @@ -58,6 +58,13 @@ export const boardApi = { recommenders(id) { return http.get(`/board/posts/${id}/recommenders`) }, + // 신고 (누적 5건 시 블라인드) + reportPost(id) { + return http.post(`/board/posts/${id}/report`) + }, + reportComment(commentId) { + return http.post(`/board/comments/${commentId}/report`) + }, block(id, reason) { return http.post(`/board/posts/${id}/block`, { reason }) }, diff --git a/src/views/board/BoardDetailView.vue b/src/views/board/BoardDetailView.vue index 1550f5f..4606fd0 100644 --- a/src/views/board/BoardDetailView.vue +++ b/src/views/board/BoardDetailView.vue @@ -126,6 +126,28 @@ async function removeComment(c) { } } +// ===== 신고 ===== +async function reportPost() { + if (!(await dialog.confirm('이 게시글을 신고하시겠어요?\n신고가 누적되면 자동으로 블라인드 처리됩니다.', { title: '게시글 신고', danger: true }))) return + try { + await boardApi.reportPost(postId) + await dialog.alert('신고가 접수되었습니다.') + await load() + } catch (e) { + alert(e.response?.data?.message || '신고에 실패했습니다.') + } +} +async function reportComment(c) { + if (!(await dialog.confirm('이 댓글을 신고하시겠어요?\n신고가 누적되면 자동으로 블라인드 처리됩니다.', { title: '댓글 신고', danger: true }))) return + try { + await boardApi.reportComment(c.id) + await dialog.alert('신고가 접수되었습니다.') + await refreshComments() + } catch (e) { + alert(e.response?.data?.message || '신고에 실패했습니다.') + } +} + // 댓글 목록만 새로고침 (다른 사람이 단 댓글·추천 반영) const refreshingComments = ref(false) async function refreshComments() { @@ -278,6 +300,11 @@ onMounted(load)
+ + @@ -305,13 +332,18 @@ onMounted(load) {{ c.authorName }} 작성자 🔥 인기 + 🚩 신고 블라인드 {{ formatRelative(c.createdAt) }}
+ +
+ 🚩 신고 누적으로 블라인드된 댓글입니다. +
-
+
🙈 비추천이 많아 블라인드된 댓글입니다.
@@ -330,6 +362,10 @@ onMounted(load) :title="isMyComment(c) ? '본인 댓글은 비추천할 수 없습니다' : ''" @click="voteComment(c, 'DOWN')" >👎 {{ c.downCount || 0 }} +
@@ -605,6 +641,27 @@ button.notice-btn { font-size: 0.68rem; font-weight: 700; } +.report-badge { + padding: 0.05rem 0.35rem; + border-radius: 3px; + border: 1px solid #c0392b; + color: #c0392b; + font-size: 0.68rem; + font-weight: 700; +} +.report-btn { + padding: 0.45rem 0.9rem; + border-radius: 4px; + color: #c0392b; + font-size: 0.85rem; +} +.creport { + padding: 0.2rem 0.6rem; + font-size: 0.8rem; + border-radius: 999px; + color: #c0392b; + opacity: 0.85; +} .comment-votes { display: flex; gap: 0.4rem;