하... mysql 로 구현하려고 오늘까지 5일 동안 고민했는데 실패했다.
자바단에서 첫대댓이나 첫대댓의 첫대댓을 어케 잘 해서 잘 넣어주고 싶었는데
코드가 너무 복잡해지고 효율이 떨어지는 것 같아서 포기했다.
진짜진짜진짜 해결하고 싶었는데 못 한 게 아쉽다.. 꿈에서 해결한 적도 있음(ㅋㅋ)
<div
v-for="list in lists"
:key="list.cno"
class="comment-item"
:style="{ paddingLeft: getPadding(list.depth) }"
>
getPadding(depth) {
const Padding = 20;
return `${depth * Padding}px`; // depth 1 일 때 20 만큼 들여쓰기
},
depth로 구분할 수 있게 depth 에 따라서 padding이 달라지도록 했다
이런 느낌.. 화살표도 넣으면 좋겠지만 귀찮다.
Form 이랑 List 컴포넌트를 나눠서 구현했는데 굳이..인 느낌도 들고 했는데 보기엔 편하다.
지금까지 한 거랑 다를 게 없고 수정 input 을 새로 보여주는 게 좀 귀찮은 일인듯...
<template>
<div class="comment-form">
<form>
<input
v-model="content"
placeholder="댓글을 입력하세요."
rows="4"
class="comment-input"
/>
</form>
<button class="comment-submit" @click="handleForm">등록</button>
</div>
</template>
<script>
export default {
data() {
return {
content: "",
};
},
methods: {
async handleForm() {
try {
const commentData = {
content: this.content,
bno: this.$store.state.board.details.bno,
id: this.$store.state.user.login.loginId,
};
const res = await this.$store.dispatch("writeComment", commentData);
if (res.data == 1) {
alert("댓글이 등록되었습니다.");
const bno = this.$route.params.bno;
await this.$store.dispatch("getCommentList", bno);
this.content = "";
return;
}
alert("작성에 실패하였습니다.");
} catch (e) {
console.error("오류", e);
alert("작성 중 오류가 발생했습니다.");
}
},
},
};
</script>
<style scoped>
.comment-form {
margin-top: 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.comment-input {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
resize: vertical;
}
.comment-submit {
align-self: flex-end;
padding: 8px 16px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.comment-submit:hover {
background-color: #0056b3;
}
</style>
<template>
<div class="comment-wrapper">
<div class="comment-list">
<div
v-for="list in lists"
:key="list.cno"
class="comment-item"
:style="{ paddingLeft: getPadding(list.depth) }"
>
<div class="comment-content">{{ list.content }}</div>
<div class="comment-actions">
<button class="btn-reply" @click="handleReply(list)">댓글</button>
<button class="btn-edit" @click="handleUpdate(list)">수정</button>
<button class="btn-delete" @click="handleDelete(list.cno)">
삭제
</button>
</div>
<div v-if="showReplyInput === list.cno" class="reply-input">
<input
class="comment-input"
v-model="replyContent"
placeholder="댓글을 입력하세요."
/>
<button class="btn-submitReply" @click="submitReply(list)">
등록
</button>
</div>
<div v-if="showUpInput === list.cno" class="reply-input">
<input
class="comment-input"
v-model="upContent"
placeholder="댓글을 입력하세요."
/>
<button class="btn-submitReply" @click="submitReply(list)">
등록
</button>
</div>
</div>
</div>
<CommentForm />
</div>
</template>
<script>
import { mapState } from "vuex";
import CommentForm from "./CommentForm.vue";
export default {
components: {
CommentForm,
},
data() {
return {
showReplyInput: null,
replyContent: "",
showUpInput: null,
upContent: "",
};
},
computed: {
...mapState({
lists: (state) => state.comment.lists,
}),
},
created() {
const bno = this.$route.params.bno;
if (bno) {
this.$store.dispatch("getCommentList", bno);
}
},
methods: {
handleReply(lists) {
this.showReplyInput =
this.showReplyInput === lists.cno ? null : lists.cno;
},
handleUpdate(lists) {
this.showUpInput = this.showUpInput === lists.cno ? null : lists.cno;
},
async submitReply(parent) {
try {
const replyData = {
content: this.replyContent,
bno: this.$store.state.board.details.bno,
id: this.$store.state.user.login.loginId,
cno: parent.cno, // 부모 댓글의 cno (선택한 댓글의 cno)
depth: parent.depth,
group_cno: parent.group_cno,
order_cno: parent.order_cno,
};
const res = await this.$store.dispatch("writeComment", replyData);
if (res.data == 1) {
alert("댓글이 등록되었습니다.");
const bno = this.$route.params.bno;
await this.$store.dispatch("getCommentList", bno);
this.showReplyInput = null; // 대댓글 입력 창 숨기기
this.replyContent = "";
}
} catch (e) {
console.error("댓글 작성 중 오류", e);
}
},
getPadding(depth) {
const padding = 20;
return `${depth * padding}px`; // depth 1 일 때 20 만큼 들여쓰기
},
},
};
</script>
<style scoped>
.comment-wrapper {
margin: 0 auto;
margin-top: 30px;
}
.comment-list {
border: 1px solid #ddd;
padding: 15px;
border-radius: 5px;
height: 200px;
overflow-y: auto;
}
.comment-item {
border-bottom: 1px dashed #ddd;
padding: 8px 0;
position: relative;
text-align: left;
}
.comment-content {
padding-right: 90px;
}
.comment-actions {
position: absolute;
right: -5px;
top: 50%;
transform: translateY(-50%);
}
.comment-input {
border: 1px solid #ccc;
border-radius: 5px;
}
button.btn-edit {
background-color: #aaa8a8;
border: none;
border-radius: 3px;
cursor: pointer;
padding: 5px 10px;
margin-left: 5px;
}
button.btn-delete {
background-color: #f44336;
color: #fdfdfd;
border: none;
border-radius: 3px;
cursor: pointer;
padding: 5px 10px;
margin-left: 5px;
}
button.btn-reply {
background-color: #2196f3;
color: #fdfdfd;
border: none;
border-radius: 3px;
cursor: pointer;
padding: 5px 10px;
margin-left: 10px;
}
button.btn-submitReply {
background-color: #2196f3;
color: #fdfdfd;
border: none;
border-radius: 3px;
cursor: pointer;
margin-left: 5px;
}
button.btn-edit:hover,
button.btn-delete:hover {
background-color: #7e7e7e;
}
</style>
import axios from "axios";
const state = {
lists: [],
replyData: {
bno: "",
content: "",
id: "",
cno: "",
depth: "",
group_cno: "",
},
};
const getters = {};
const mutations = {
setLists(state, data) {
state.lists = data;
},
setReply(state, data) {
state.replyData = data;
},
};
const actions = {
async writeComment(context, commentData) {
// 댓글 작성
try {
const res = await axios.post("/api/comment/write", commentData);
context.commit("setComments", res.data);
return res;
} catch (e) {
console.error("API 호출 실패", e);
throw e;
}
},
getCommentList(context, bno) {
// 댓글 조회
axios
.get("/api/comment/" + bno)
.then((res) => {
console.log("API 호출 성공", res.data);
context.commit("setLists", res.data);
})
.catch((e) => {
console.error("API 호출 실패", e);
});
},
};
export default {
state,
getters,
mutations,
actions,
};
commentData, replyData 이런 식으로 다 로컬에서 때려박아서 store 로 넣어줬는데
bno 같이 다른 store에 저장된 state 를 불러와서 넣는게 번거롭지만 않았어도 store에서 했을텐데...저 부분이 아쉽다,, 나중에 정리 해야지...