This commit is contained in:
khj0414 2025-02-25 15:26:30 +09:00
commit 56757155ee
6 changed files with 146 additions and 172 deletions

View File

@ -37,14 +37,11 @@ $api.interceptors.response.use(
}, },
function (error) { function (error) {
const toastStore = useToastStore(); const toastStore = useToastStore();
const currentPage = error.config.headers['X-Page-Route'];
// 오류 응답 처리 // 오류 응답 처리
if (error.response) { if (error.response) {
switch (error.response.status) { switch (error.response.status) {
case 401: case 401:
if (currentPage === '/login') { if (!error.config.headers.isLogin) {
toastStore.onToast('아이디 혹은 비밀번호가 틀렸습니다.', 'e');
} else {
toastStore.onToast('인증이 필요합니다.', 'e'); toastStore.onToast('인증이 필요합니다.', 'e');
} }
break; break;

View File

@ -40,39 +40,39 @@ const common = {
return null; // Delta 객체가 아니거나 ops가 없을 경우 null 반환 return null; // Delta 객체가 아니거나 ops가 없을 경우 null 반환
}, },
/** // /**
* Date 타입 문자열 포멧팅 // * Date 타입 문자열 포멧팅
* // *
* @param {string} dateStr // * @param {string} dateStr
* @return // * @return
* 1. Date type 경우 예시 '25-02-24 12:02' // * 1. Date type 인 경우 예시 '25-02-24 12:02'
* 2. Date type 아닌 경우 입력값 리턴 // * 2. Date type 이 아닌 경우 입력값 리턴
* // *
*/ // */
dateFormatter(dateStr) { // dateFormatter(dateStr) {
const date = new Date(dateStr); // const date = new Date(dateStr);
const dateCheck = date.getTime(); // const dateCheck = date.getTime();
if (isNaN(dateCheck)) { // if (isNaN(dateCheck)) {
return dateStr; // return dateStr;
} else { // } else {
const { year, month, day, hours, minutes } = this.formatDateTime(date); // const { year, month, day, hours, minutes } = this.formatDateTime(date);
return `${year}-${month}-${day} ${hours}:${minutes}`; // return `${year}-${month}-${day} ${hours}:${minutes}`;
} // }
}, // },
formatDateTime(date) { // formatDateTime(date) {
const zeroFormat = num => (num < 10 ? `0${num}` : num); // const zeroFormat = num => (num < 10 ? `0${num}` : num);
return { // return {
year: date.getFullYear(), // year: date.getFullYear(),
month: zeroFormat(date.getMonth() + 1), // month: zeroFormat(date.getMonth() + 1),
day: zeroFormat(date.getDate()), // day: zeroFormat(date.getDate()),
hours: zeroFormat(date.getHours()), // hours: zeroFormat(date.getHours()),
minutes: zeroFormat(date.getMinutes()), // minutes: zeroFormat(date.getMinutes()),
seconds: zeroFormat(date.getSeconds()), // seconds: zeroFormat(date.getSeconds()),
}; // };
}, // },
}; };
export default { export default {

View File

@ -124,7 +124,7 @@ const toggleComment = () => {
// //
const submitComment = (newComment) => { const submitComment = (newComment) => {
emit('submitComment', { parentId: props.comment.commentId, ...newComment }); emit('submitComment', { parentId: props.comment.commentId, ...newComment, LOCBRDTYP: newComment.LOCBRDTYP });
isComment.value = false; isComment.value = false;
}; };

View File

@ -76,26 +76,26 @@ const props = defineProps({
default: false default: false
} }
}); });
const comment = ref(''); const comment = ref('');
const password = ref(''); const password = ref('');
const isCheck = ref(props.unknown); const isCheck = ref(false);
const emit = defineEmits(['submitComment']); const emit = defineEmits(['submitComment']);
watch(() => props.unknown, (newVal) => {
isCheck.value = newVal;
});
function handleCommentSubmit() { function handleCommentSubmit() {
if (props.unknown && isCheck.value && !password.value) {
alert('익명 댓글을 작성하려면 비밀번호를 입력해야 합니다.');
return;
}
const LOCBRDTYP = isCheck.value ? '300102' : null;
emit('submitComment', { emit('submitComment', {
comment: comment.value, comment: comment.value,
password: isCheck.value ? password.value : '', password: isCheck.value ? password.value : '',
LOCBRDTYP,
isCheck: isCheck.value
}); });
comment.value = ''; comment.value = '';
password.value = ''; password.value = '';
isCheck.value = false; //
} }
</script> </script>

View File

@ -62,11 +62,8 @@ const props = defineProps({
}, },
profileName: { profileName: {
type: String, type: String,
<<<<<<< HEAD
default: '익명', default: '익명',
=======
default: '', default: '',
>>>>>>> board-comment
}, },
unknown: { unknown: {
type: Boolean, type: Boolean,

View File

@ -76,9 +76,9 @@
@updateReaction="handleUpdateReaction" @updateReaction="handleUpdateReaction"
/> />
</div> </div>
<p>현재 로그인한 사용자 ID: {{ currentUserId }}</p> <!-- <p>현재 로그인한 사용자 ID: {{ currentUserId }}</p>
<p>게시글 작성자: {{ authorId }}</p> <p>게시글 작성자: {{ authorId }}</p>
<p>isAuthor : {{ isAuthor }}</p> <p>isAuthor : {{ isAuthor }}</p> -->
<!-- <p>use이미지:{{userStore.user.img}}</p> --> <!-- <p>use이미지:{{userStore.user.img}}</p> -->
<!-- <img :src="`http://localhost:10325/upload/img/profile/${userStore.user.profile}`" alt="Profile Image" class="w-px-40 h-auto rounded-circle"/> --> <!-- <img :src="`http://localhost:10325/upload/img/profile/${userStore.user.profile}`" alt="Profile Image" class="w-px-40 h-auto rounded-circle"/> -->
@ -94,6 +94,7 @@
<BoardCommentArea <BoardCommentArea
:profileName="profileName" :profileName="profileName"
:unknown="unknown" :unknown="unknown"
:commentAlert="commentAlert"
:passwordAlert="passwordAlert" :passwordAlert="passwordAlert"
@submitComment="handleCommentSubmit" @submitComment="handleCommentSubmit"
/> />
@ -139,6 +140,7 @@ import { ref, onMounted, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useUserInfoStore } from '@/stores/useUserInfoStore'; import { useUserInfoStore } from '@/stores/useUserInfoStore';
import axios from '@api'; import axios from '@api';
import { formattedDate } from '@/common/formattedDate.js';
// //
const profileName = ref(''); const profileName = ref('');
@ -158,22 +160,19 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
const userStore = useUserInfoStore(); const userStore = useUserInfoStore();
const currentBoardId = ref(Number(route.params.id)); const currentBoardId = ref(Number(route.params.id));
<<<<<<< HEAD
const unknown = computed(() => profileName.value === '익명'); const unknown = computed(() => profileName.value === '익명');
const currentUserId = ref('김자바'); // id
const authorId = ref(null); // id
=======
// const unknown = computed(() => profileName.value === '');
const currentUserId = computed(() => userStore.user.id); // id const currentUserId = computed(() => userStore.user.id); // id
const authorId = ref(''); // id const authorId = ref(''); // id
>>>>>>> board-comment
const isAuthor = computed(() => currentUserId.value === authorId.value); const isAuthor = computed(() => currentUserId.value === authorId.value);
// const isCommentAuthor =
const commentsWithAuthStatus = computed(() => { const commentsWithAuthStatus = computed(() => {
const updatedComments = comments.value.map(comment => ({ const updatedComments = comments.value.map(comment => ({
...comment, ...comment,
isCommentAuthor: comment.authorId === currentUserId.value isCommentAuthor: comment.authorId === currentUserId.value,
children: comment.children.map(reply => ({
...reply,
isCommentAuthor: reply.authorId === currentUserId.value
}))
})); }));
// console.log(" commentsWithAuthStatus :", updatedComments); // console.log(" commentsWithAuthStatus :", updatedComments);
return updatedComments; return updatedComments;
@ -188,6 +187,7 @@ const isCommentPassword = ref(false);
const lastClickedButton = ref(""); const lastClickedButton = ref("");
const lastCommentClickedButton = ref(""); const lastCommentClickedButton = ref("");
const isEditTextarea = ref(false); const isEditTextarea = ref(false);
const commentAlert = ref('')
const pagination = ref({ const pagination = ref({
currentPage: 1, currentPage: 1,
@ -211,29 +211,21 @@ const fetchBoardDetails = async () => {
const response = await axios.get(`board/${currentBoardId.value}`); const response = await axios.get(`board/${currentBoardId.value}`);
const data = response.data.data; const data = response.data.data;
console.log(data) // console.log(data)
// API // API
// const boardDetail = data.boardDetail || {}; // const boardDetail = data.boardDetail || {};
<<<<<<< HEAD
profileName.value = data.author || '익명'; profileName.value = data.author || '익명';
//
// profileName.value = 'null;
// :
authorId.value = data.author;
=======
profileName.value = data.author;
// //
// profileName.value = ''; // profileName.value = '';
console.log("📌 게시글 작성자:", profileName.value); //
console.log("🔍 익명 여부 (unknown.value):", unknown.value); //
authorId.value = data.authorId; // id authorId.value = data.authorId; // id
>>>>>>> board-comment
boardTitle.value = data.title || '제목 없음'; boardTitle.value = data.title || '제목 없음';
boardContent.value = data.content || ''; boardContent.value = data.content || '';
date.value = data.date || ''; date.value = data.date || '';
@ -309,20 +301,14 @@ const fetchComments = async (page = 1) => {
} }
}); });
<<<<<<< HEAD // console.log(response.data.data)
=======
console.log(response.data.data)
>>>>>>> board-comment
const commentsList = response.data.data.list.map(comment => ({ const commentsList = response.data.data.list.map(comment => ({
commentId: comment.LOCCMTSEQ, // ID commentId: comment.LOCCMTSEQ, // ID
boardId: comment.LOCBRDSEQ, boardId: comment.LOCBRDSEQ,
parentId: comment.LOCCMTPNT, // ID parentId: comment.LOCCMTPNT, // ID
author: comment.author || '익명', author: comment.author || '익명',
<<<<<<< HEAD
=======
authorId: comment.authorId, authorId: comment.authorId,
>>>>>>> board-comment
content: comment.LOCCMTRPY, content: comment.LOCCMTRPY,
likeCount: comment.likeCount || 0, likeCount: comment.likeCount || 0,
dislikeCount: comment.dislikeCount || 0, dislikeCount: comment.dislikeCount || 0,
@ -340,10 +326,12 @@ const fetchComments = async (page = 1) => {
params: { LOCCMTPNT: comment.commentId } params: { LOCCMTPNT: comment.commentId }
}); });
console.log(`대댓글 데이터 (${comment.commentId}의 대댓글):`, replyResponse.data); // console.log(` (${comment.commentId} ):`, replyResponse.data);
if (replyResponse.data.data) { if (replyResponse.data.data) {
comment.children = replyResponse.data.data.map(reply => ({ comment.children = replyResponse.data.data.map(reply => ({
author: reply.author || '익명',
authorId: reply.authorId,
commentId: reply.LOCCMTSEQ, commentId: reply.LOCCMTSEQ,
boardId: reply.LOCBRDSEQ, boardId: reply.LOCBRDSEQ,
parentId: reply.LOCCMTPNT, // ID parentId: reply.LOCCMTPNT, // ID
@ -386,29 +374,19 @@ const fetchComments = async (page = 1) => {
console.log('댓글 목록 불러오기 오류:', error); console.log('댓글 목록 불러오기 오류:', error);
} }
}; };
// const isSubmitting = ref(false);
// //
const handleCommentSubmit = async ({ comment, password }) => { const handleCommentSubmit = async (data) => {
console.log('댓글') const { comment, password } = data;
// const LOCBRDTYP = data.LOCBRDTYP || null; // undefined
// if (!password) {
// passwordAlert.value = " .";
// return;
// }
// console.log(' ')
//
// if (isSubmitting.value) return;
// isSubmitting.value = true;
try { try {
const response = await axios.post(`board/${currentBoardId.value}/comment`, { const response = await axios.post(`board/${currentBoardId.value}/comment`, {
LOCBRDSEQ: currentBoardId.value, LOCBRDSEQ: currentBoardId.value,
LOCCMTRPY: comment, LOCCMTRPY: comment,
LOCCMTPWD: password, LOCCMTPWD: password,
LOCCMTPNT: 1 LOCCMTPNT: 1,
LOCBRDTYP //
}); });
if (response.status === 200) { if (response.status === 200) {
@ -426,48 +404,41 @@ const handleCommentSubmit = async ({ comment, password }) => {
// ( `BoardCommentList` ) // ( `BoardCommentList` )
const handleCommentReply = async (reply) => { const handleCommentReply = async (reply) => {
try { try {
// console.log(' :', { // ( LOCBRDTYP 300102 )
// LOCBRDSEQ: currentBoardId.value,
// LOCCMTRPY: reply.comment,
// LOCCMTPWD: reply.password || null,
// LOCCMTPNT: reply.parentId
// });
const response = await axios.post(`board/${currentBoardId.value}/comment`, { const requestBody = {
LOCBRDSEQ: currentBoardId.value, LOCBRDSEQ: currentBoardId.value,
LOCCMTRPY: reply.comment, LOCCMTRPY: reply.comment,
LOCCMTPWD: reply.password || null, LOCCMTPWD: reply.password || null,
LOCCMTPNT: reply.parentId LOCCMTPNT: reply.parentId,
}); LOCBRDTYP: reply.isCheck ? "300102" : null
};
// console.log(requestBody)
// console.log(' :', { const response = await axios.post(`board/${currentBoardId.value}/comment`, requestBody);
// status: response.status,
// data: response.data,
// headers: response.headers
// });
if (response.status === 200) { if (response.status === 200) {
if (response.data.code === 200) { // if (response.data.code === 200) {
console.log('대댓글 작성 성공:', response.data); console.log('✅ 대댓글 작성 성공:', response.data);
await fetchComments(); // await fetchComments();
} else { } else {
console.log('대댓글 작성 실패 - 서버 응답:', response.data); console.log('대댓글 작성 실패 - 서버 응답:', response.data);
alert('대댓글 작성에 실패했습니다.'); alert('대댓글 작성에 실패했습니다.');
} }
} }
} catch (error) { } catch (error) {
console.error('대댓글 작성 중 오류 발생:', error); console.error('🚨 대댓글 작성 중 오류 발생:', error);
if (error.response) { if (error.response) {
console.error('서버 응답 에러:', error.response.data); console.error('📌 서버 응답 에러:', error.response.data);
}
alert('대댓글 작성 중 오류가 발생했습니다.');
} }
alert('❌ 대댓글 작성 중 오류가 발생했습니다.');
} }
};
// //
const editClick = (unknown) => { const editClick = (unknown) => {
if (unknown) { const isUnknown = unknown?.unknown ?? false;
if (isUnknown) {
togglePassword("edit"); togglePassword("edit");
} else { } else {
router.push({ name: "BoardEdit", params: { id: currentBoardId.value } }); router.push({ name: "BoardEdit", params: { id: currentBoardId.value } });
@ -483,47 +454,50 @@ const deleteClick = (unknown) => {
} }
}; };
const findCommentById = (commentId, commentsList) => {
for (const comment of commentsList) {
if (comment.commentId === commentId) {
return comment; //
}
if (comment.children && comment.children.length) {
const found = findCommentById(commentId, comment.children);
if (found) return found; //
}
}
return null;
};
// //
const editComment = (comment) => { const editComment = (comment) => {
const targetComment = comments.value.find(c => c.commentId === comment.commentId); console.log('대댓글 수정 버튼 클릭')
//
const targetComment = findCommentById(comment.commentId, comments.value);
if (!targetComment) { if (!targetComment) {
console.log("대댓글을 찾을 수 없음:", comment.commentId);
return; return;
} }
// text , // text ,
if (targetComment.isEditTextarea) { targetComment.isEditTextarea = !targetComment.isEditTextarea;
targetComment.isEditTextarea = false;
} else {
targetComment.isEditTextarea = true;
}
// //
if (unknown.value) { if (unknown.value) {
toggleCommentPassword(comment, "edit"); toggleCommentPassword(comment, "edit");
} else {
comment.isEditTextarea = true;
} }
<<<<<<< HEAD
// comments.value.forEach(c => {
// c.isEditTextarea = false;
// c.isCommentPassword = false;
// });
// if (comment.unknown) {
// comment.isCommentPassword = true;
// } else {
// comment.isEditTextarea = true;
// }
=======
>>>>>>> board-comment
} }
// //
const deleteComment = async (comment) => { const deleteComment = async (comment) => {
console.log('🗑 댓글 삭제 시도:', comment);
// //
if (unknown.value) { const isMyComment = comment.authorId === currentUserId.value;
if (unknown.value && !isMyComment) {
console.log('🛑 익명 사용자의 댓글 삭제 시도 (비밀번호 필요)');
if (comment.isEditTextarea) { if (comment.isEditTextarea) {
// , // ,
comment.isEditTextarea = false; comment.isEditTextarea = false;
@ -533,8 +507,8 @@ const deleteComment = async (comment) => {
toggleCommentPassword(comment, "delete"); toggleCommentPassword(comment, "delete");
} }
} else { } else {
// ( ) console.log('✅ 로그인 사용자 댓글 삭제 진행');
deleteReplyComment(comment) deleteReplyComment(comment);
} }
}; };
@ -626,11 +600,8 @@ const submitCommentPassword = async (comment, password) => {
if (lastCommentClickedButton.value === "edit") { if (lastCommentClickedButton.value === "edit") {
comment.isEditTextarea = true; comment.isEditTextarea = true;
<<<<<<< HEAD
=======
passwordCommentAlert.value = ""; passwordCommentAlert.value = "";
>>>>>>> board-comment
// handleSubmitEdit(comment, comment.content); // handleSubmitEdit(comment, comment.content);
} else if (lastCommentClickedButton.value === "delete") { } else if (lastCommentClickedButton.value === "delete") {
passwordCommentAlert.value = ""; passwordCommentAlert.value = "";
@ -704,19 +675,20 @@ const handleSubmitEdit = async (comment, editedContent) => {
}); });
// //
<<<<<<< HEAD
comment.content = editedContent;
comment.isEditTextarea = false;
=======
// comment.content = editedContent; // comment.content = editedContent;
// comment.isEditTextarea = false; // comment.isEditTextarea = false; f
if (response.status === 200) { if (response.status === 200) {
//
await fetchComments(); const targetComment = findCommentById(comment.commentId, comments.value);
if (targetComment) {
targetComment.content = editedContent; //
targetComment.isEditTextarea = false; //
} else {
console.warn("❌ 수정할 댓글을 찾을 수 없음");
}
} else { } else {
console.log("❌ 댓글 수정 실패:", response.data); console.log("❌ 댓글 수정 실패:", response.data);
} }
>>>>>>> board-comment
} catch (error) { } catch (error) {
console.error("댓글 수정 중 오류 발생:", error); console.error("댓글 수정 중 오류 발생:", error);
} }
@ -724,13 +696,10 @@ const handleSubmitEdit = async (comment, editedContent) => {
// ( ) // ( )
const handleCancelEdit = (comment) => { const handleCancelEdit = (comment) => {
console.log("BoardView.vue - 댓글 수정 취소:", comment); const targetComment = findCommentById(comment.commentId, comments.value);
// comments comment
const targetComment = comments.value.find(c => c.commentId === comment.commentId);
if (targetComment) { if (targetComment) {
console.log("✅ 원본 데이터 찾음, 수정 취소 처리 가능"); console.log("✅ 원본 데이터 찾음, 수정 취소 처리 가능:", targetComment);
targetComment.isEditTextarea = false; targetComment.isEditTextarea = false;
} else { } else {
console.error("❌ 원본 데이터 찾을 수 없음, 수정 취소 실패"); console.error("❌ 원본 데이터 찾을 수 없음, 수정 취소 실패");
@ -745,15 +714,26 @@ const handlePageChange = (page) => {
} }
}; };
// ( )
const handleCommentDeleted = (deletedCommentId) => { const handleCommentDeleted = (deletedCommentId) => {
comments.value = comments.value.filter(comment => comment.commentId !== deletedCommentId); //
}; const parentIndex = comments.value.findIndex(comment => comment.commentId === deletedCommentId);
// if (parentIndex !== -1) {
const formattedDate = (dateString) => { comments.value.splice(parentIndex, 1);
if (!dateString) return "날짜 없음"; return;
const dateObj = new Date(dateString); }
return `${dateObj.getFullYear()}-${String(dateObj.getMonth() + 1).padStart(2, '0')}-${String(dateObj.getDate()).padStart(2, '0')} ${String(dateObj.getHours()).padStart(2, '0')}:${String(dateObj.getMinutes()).padStart(2, '0')}`;
// 2
for (let parent of comments.value) {
const childIndex = parent.children.findIndex(child => child.commentId === deletedCommentId);
if (childIndex !== -1) {
parent.children.splice(childIndex, 1);
return;
}
}
console.error("❌ 삭제할 댓글을 찾을 수 없음:", deletedCommentId);
}; };
const formattedBoardDate = computed(() => formattedDate(date.value)); const formattedBoardDate = computed(() => formattedDate(date.value));