From 87acf373d9043802d64af0d84340dbca90881b24 Mon Sep 17 00:00:00 2001 From: kimdaae328 Date: Thu, 20 Feb 2025 18:58:53 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/board/BoardComment.vue | 139 ++++++++++++++++++++-- src/components/board/BoardCommentArea.vue | 3 +- src/components/board/BoardCommentList.vue | 1 + src/views/board/BoardView.vue | 136 +++++++++++---------- 4 files changed, 205 insertions(+), 74 deletions(-) diff --git a/src/components/board/BoardComment.vue b/src/components/board/BoardComment.vue index 16916d3..67c7cd5 100644 --- a/src/components/board/BoardComment.vue +++ b/src/components/board/BoardComment.vue @@ -14,21 +14,33 @@ @deleteClick="deleteClick" @submitPassword="submitPassword" @updateReaction="handleUpdateReaction" - @toggleEdit="emit('toggleEdit', comment.commentId, true)" + @toggleEdit="toggleEdit(true)" /> + +
+
+ + +
+ {{ passwordAlert }} +
@@ -89,7 +101,7 @@ const props = defineProps({ }); // emits 정의 -const emit = defineEmits(['submitComment', 'updateReaction', 'toggleEdit', 'editClick']); +const emit = defineEmits(['submitComment', 'updateReaction', 'toggleEdit',]); // 댓글 입력 창 토글 const isComment = ref(false); @@ -97,6 +109,22 @@ const toggleComment = () => { isComment.value = !isComment.value; }; +// 비밀번호 & 수정 모드 관련 상태 +const password = ref(''); +const passwordAlert = ref(''); +const isPassword = ref(false); +const isEditTextarea = ref(false); +const lastClickedButton = ref(""); + +const toggleEdit = (status) => { + if (props.unknown) { + isPassword.value = status; // 익명 사용자면 비밀번호 입력창 표시 + lastClickedButton.value = "edit"; + } else { + isEditTextarea.value = status; // 비밀번호가 필요 없으면 바로 수정 모드 + } +}; + // 부모 컴포넌트에 대댓글 추가 요청 const submitComment = (newComment) => { emit('submitComment', { parentId: props.comment.commentId, ...newComment }); @@ -114,16 +142,103 @@ const handleUpdateReaction = (reactionData) => { }; -// 수정 -const editClick = (data) => { - emit('editClick', data); +// 댓글 수정 버튼 클릭 +const editClick = () => { + if (props.unknown) { + console.log('수정') + togglePassword("edit"); + } }; -// 수정 -const editedContent = ref(props.comment.content); -const submitEdit = () => { - emit('submitComment', { commentId: props.comment.commentId, content: editedContent.value }); - emit('toggleEdit', props.comment.commentId, false); // 수정 모드 종료 +const deleteClick = () => { + if (props.unknown) { + console.log('삭제') + togglePassword("delete"); + } }; +const togglePassword = (button) => { + if (lastClickedButton.value === button) { + isPassword.value = !isPassword.value; + } else { + isPassword.value = true; + } + lastClickedButton.value = button; +}; + +// const deleteComment = async () => { +// if (!confirm("정말 이 댓글을 삭제하시겠습니까?")) return; + +// try { +// console.log("댓글 삭제 요청 시작:"); +// console.log("댓글 ID:", props.comment.commentId); +// console.log("게시글 ID:", props.comment.boardId); +// console.log("비밀번호 포함 여부:", props.unknown ? "예 (익명 사용자)" : "아니오 (로그인 사용자)"); + +// const response = await axios.delete(`board/${props.comment.commentId}`, { +// data: { LOCCMTSEQ: props.comment.commentId } +// }); + +// console.log("📌 서버 응답:", response.data); + +// if (response.data.code === 200) { +// console.log("댓글 삭제 성공!"); +// // emit("commentDeleted", props.comment.commentId); +// } else { +// console.log("❌ 댓글 삭제 실패:", response.data.message); +// // alert("댓글 삭제에 실패했습니다."); +// } +// } catch (error) { +// console.log("🚨 댓글 삭제 중 오류 발생:", error); +// alert("댓글 삭제 중 오류가 발생했습니다."); +// } +// }; + + +// 비밀번호 제출 +const submitPassword = async () => { + if (!password.value) { + passwordAlert.value = "비밀번호를 입력해주세요."; + return; + } + + console.log(props.comment.commentId) + + try { + const response = await axios.post(`board/${props.comment.commentId}/password`, { + LOCCMTPWD: password.value, + LOCCMTSEQ: props.comment.commentId, + }); + + console.log("응답!!!!!!!!", response); // 서버 응답 전체 확인 + console.log("응답 데이터:", response.data); + + // if (response.data.code === 200 && response.data.data === true) { + // console.log('되는거니') + // deleteComment() + // // password.value = ''; + // // isPassword.value = false; + // // isEditTextarea.value = true; + // } else { + // passwordAlert.value = "비밀번호가 일치하지 않습니다."; + // } + } catch (error) { + passwordAlert.value = "비밀번호 검증 중 오류가 발생했습니다."; + } +}; + +const editedContent = ref(props.comment.content); + +// 댓글 수정 취소 +const cancelEdit = () => { + isEditTextarea.value = false; +}; + +// 댓글 수정 내용 저장 +const submitEdit = () => { + emit('submitComment', { commentId: props.comment.commentId, content: editedContent.value }); + isEditTextarea.value = false; // 수정 모드 종료 +}; + + diff --git a/src/components/board/BoardCommentArea.vue b/src/components/board/BoardCommentArea.vue index a51b939..27ada9c 100644 --- a/src/components/board/BoardCommentArea.vue +++ b/src/components/board/BoardCommentArea.vue @@ -43,6 +43,7 @@ class="form-control flex-grow-1" v-model="password" /> + @@ -85,7 +86,7 @@ watch(() => props.unknown, (newVal) => { function handleCommentSubmit() { emit('submitComment', { comment: comment.value, - password: password.value, + password: isCheck.value ? password.value : '', }); comment.value = ''; diff --git a/src/components/board/BoardCommentList.vue b/src/components/board/BoardCommentList.vue index 1ee244a..6d39c2a 100644 --- a/src/components/board/BoardCommentList.vue +++ b/src/components/board/BoardCommentList.vue @@ -14,6 +14,7 @@ @deleteClick="deleteClick" @submitPassword="submitPassword" @submitComment="submitComment" + @commentDeleted="handleCommentDeleted" @updateReaction="(reactionData) => handleUpdateReaction(reactionData, comment.commentId, comment.boardId)" /> diff --git a/src/views/board/BoardView.vue b/src/views/board/BoardView.vue index 2b031b6..5905b9d 100644 --- a/src/views/board/BoardView.vue +++ b/src/views/board/BoardView.vue @@ -98,11 +98,9 @@ currentUserId.value === authorId.value); -const isEditTextarea = ref(false); const password = ref(''); const passwordAlert = ref(""); @@ -265,15 +262,6 @@ const fetchComments = async (page = 1) => { } }); - // 대댓글 - // const replyResponse = await axios.get(`board/${currentBoardId.value}/reply`, { - // params: { - // LOCCMTPNT: 120 - // } - // }); - - // console.log(replyResponse.data) - const commentsList = response.data.data.list.map(comment => ({ commentId: comment.LOCCMTSEQ, // 댓글 ID boardId: comment.LOCBRDSEQ, @@ -290,18 +278,29 @@ const fetchComments = async (page = 1) => { })); for (const comment of commentsList) { - // 대댓글 조회 + if (!comment.commentId) continue; + const replyResponse = await axios.get(`board/${currentBoardId.value}/reply`, { - params: { - LOCCMTPNT: comment.parentId // 부모 댓글의 ID를 사용 - } + params: { LOCCMTPNT: comment.commentId } }); - - console.log(`대댓글:`, replyResponse.data); - - // 대댓글이 있다면 children 배열에 추가할 수 있습니다 + + // console.log(`📌 대댓글 데이터 (${comment.commentId}의 대댓글):`, replyResponse.data); + if (replyResponse.data.data) { - comment.children = replyResponse.data.data; + comment.children = replyResponse.data.data.map(reply => ({ + commentId: reply.LOCCMTSEQ, + boardId: reply.LOCBRDSEQ, + parentId: reply.LOCCMTPNT, // 부모 댓글 ID + content: reply.LOCCMTRPY || "내용 없음", + createdAtRaw: new Date(reply.LOCCMTRDT), + createdAt: formattedDate(reply.LOCCMTRDT), + likeCount: reply.likeCount || 0, + dislikeCount: reply.dislikeCount || 0, + likeClicked: false, + dislikeClicked: false + })); + } else { + comment.children = []; // 대댓글이 없으면 빈 배열로 초기화 } } @@ -324,47 +323,34 @@ const fetchComments = async (page = 1) => { navigateLastPage: response.data.data.navigateLastPage // 페이지네이션에서 마지막 페이지 번호 }; + console.log("📌 댓글 목록:", comments.value); + } catch (error) { console.log('댓글 목록 불러오기 오류:', error); } }; -// 대댓글 목록 조회 -// const fetchReplies = async () => { -// try { -// const response = await axios.get(`board/${currentBoardId.value}/reply`); - -// const replyData = response.data.data || []; - -// return replyData.map(reply => ({ -// commentId: reply.LOCCMTSEQ, // 대댓글 ID -// boardId: reply.LOCBRDSEQ, -// parentId: reply.LOCCMTPNT, // 부모 댓글 ID -// content: reply.LOCCMTRPY, -// createdAtRaw: new Date(reply.LOCCMTRDT), // 정렬용 -// createdAt: formattedDate(reply.LOCCMTRDT), // 표시용 -// likeCount: reply.likeCount || 0, -// dislikeCount: reply.dislikeCount || 0, -// likeClicked: false, -// dislikeClicked: false -// })); -// } catch (error) { -// console.error("대댓글 불러오기 오류:", error); -// return []; -// } -// }; - // 댓글 작성 const handleCommentSubmit = async ({ comment, password }) => { + // if (unknown.value && !password) { + // passwordAlert.value = "익명 사용자는 비밀번호를 입력해야 합니다."; // UI에 메시지 표시 + // return; + // } + // if (!password) { + // passwordAlert.value = "비밀번호를 입력해야 합니다."; // UI에서 경고 표시 + // return; + // } + + try { const response = await axios.post(`board/${currentBoardId.value}/comment`, { LOCBRDSEQ: currentBoardId.value, LOCCMTRPY: comment, - LOCCMTPWD: password || null, + LOCCMTPWD: password, LOCCMTPNT: 1 }); - // console.log('서버 응답 전체:', response.data); + // console.log('서버 응답 전체1212121212:', response.data); if (response.status === 200) { console.log('댓글 작성 성공:', response.data.message); @@ -380,23 +366,47 @@ const handleCommentSubmit = async ({ comment, password }) => { // 대댓글 작성 const handleCommentReply = async (reply) => { - const response = await axios.post(`board/${currentBoardId.value}/comment`, { - LOCBRDSEQ: currentBoardId.value, - LOCCMTRPY: reply.comment, - LOCCMTPWD: reply.password || null, - LOCCMTPNT: reply.parentId - }); + try { + console.log('대댓글 작성 요청 데이터:', { + LOCBRDSEQ: currentBoardId.value, + LOCCMTRPY: reply.comment, + LOCCMTPWD: reply.password || null, + LOCCMTPNT: reply.parentId + }); - if (response.status === 200) { - console.log('대댓글 작성 성공:', response.data.message); - await fetchComments(); - } else { - console.log('대댓글 작성 실패:', response.data.message); + const response = await axios.post(`board/${currentBoardId.value}/comment`, { + LOCBRDSEQ: currentBoardId.value, + LOCCMTRPY: reply.comment, + LOCCMTPWD: reply.password || null, + LOCCMTPNT: reply.parentId + }); + + // 응답 데이터를 자세히 로그로 확인 + console.log('대댓글 작성 응답:', { + status: response.status, + data: response.data, + headers: response.headers + }); + + if (response.status === 200) { + if (response.data.code === 200) { // 서버 응답 코드도 확인 + console.log('대댓글 작성 성공:', response.data); + await fetchComments(); // 댓글 목록 새로고침 + } else { + console.log('대댓글 작성 실패 - 서버 응답:', response.data); + alert('대댓글 작성에 실패했습니다.'); + } + } + } catch (error) { + console.error('대댓글 작성 중 오류 발생:', error); + if (error.response) { + console.error('서버 응답 에러:', error.response.data); + } + alert('대댓글 작성 중 오류가 발생했습니다.'); } } const editClick = (unknown) => { - if (unknown) { togglePassword("edit"); } else { @@ -497,6 +507,10 @@ const handlePageChange = (page) => { } }; +const handleCommentDeleted = (deletedCommentId) => { + comments.value = comments.value.filter(comment => comment.commentId !== deletedCommentId); +}; + // 날짜 const formattedDate = (dateString) => { if (!dateString) return "날짜 없음";