feat: 게시판 신고 UI — 글/댓글 신고 버튼 + 블라인드 표시
CI / build (push) Failing after 12m42s

- 작성자·관리자 외 신고 버튼(글 액션·각 댓글)
- 신고 누적 블라인드 댓글: 비관리자 가림, 관리자만 본문 + 신고 블라인드 뱃지
- 신고 후 새로고침으로 상태 반영

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ByungCheol
2026-06-28 18:05:43 +09:00
parent 0fa8c95139
commit 59f38b3348
2 changed files with 65 additions and 1 deletions
+58 -1
View File
@@ -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)
<div class="actions">
<IconBtn icon="list" title="목록" @click="router.push({ path: `/board/${category}`, query: route.query })" />
<div class="right-actions">
<!-- 신고 (작성자·관리자 ) -->
<button
v-if="!isAdmin && !restricted && auth.user && post.authorId !== auth.user.id"
type="button" class="report-btn" @click="reportPost"
>🚩 신고</button>
<!-- 관리자 제한/해제 -->
<button v-if="isAdmin && !post.blocked" type="button" class="warn" @click="blockPost">열람 제한</button>
<button v-if="isAdmin && post.blocked" type="button" class="warn" @click="unblockPost">제한 해제</button>
@@ -305,13 +332,18 @@ onMounted(load)
<strong>{{ c.authorName }}</strong>
<span v-if="isAuthorComment(c)" class="author-badge">작성자</span>
<span v-if="c.hot" class="hot-badge">🔥 인기</span>
<span v-if="c.blocked && isAdmin" class="report-badge">🚩 신고 블라인드</span>
<span class="comment-date">{{ formatRelative(c.createdAt) }}</span>
<span v-if="canModifyComment(c)" class="comment-del">
<IconBtn icon="trash" title="댓글 삭제" variant="danger" size="sm" @click="removeComment(c)" />
</span>
</div>
<!-- 신고 누적 블라인드 (관리자만 본문 열람, 외엔 가림) -->
<div v-if="c.blocked && !isAdmin" class="blinded comment-blinded">
🚩 신고 누적으로 블라인드된 댓글입니다.
</div>
<!-- 비추천 많은 댓글 블라인드 (작성자·관리자는 정상) -->
<div v-if="isBlinded(c) && !isMyComment(c) && !isAdmin && !revealedComments[c.id]" class="blinded comment-blinded">
<div v-else-if="isBlinded(c) && !isMyComment(c) && !isAdmin && !revealedComments[c.id]" class="blinded comment-blinded">
🙈 비추천이 많아 블라인드된 댓글입니다.
<button type="button" class="reveal-btn" @click="toggleReveal(c)">그래도 보기</button>
</div>
@@ -330,6 +362,10 @@ onMounted(load)
:title="isMyComment(c) ? '본인 댓글은 비추천할 수 없습니다' : ''"
@click="voteComment(c, 'DOWN')"
>👎 {{ c.downCount || 0 }}</button>
<button
v-if="!isAdmin && auth.user && c.authorId !== auth.user.id"
type="button" class="creport" @click="reportComment(c)"
>🚩 신고</button>
</div>
</template>
</li>
@@ -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;