Merge branch 'main' into mypage
This commit is contained in:
commit
a6c57646d7
@ -12,6 +12,8 @@
|
|||||||
:isLike="!isLike"
|
:isLike="!isLike"
|
||||||
:isCommentPassword="isCommentPassword"
|
:isCommentPassword="isCommentPassword"
|
||||||
:isCommentProfile="true"
|
:isCommentProfile="true"
|
||||||
|
:is-edit-pushed="isEditPushed"
|
||||||
|
:is-delete-pushed="isDeletePushed"
|
||||||
@editClick="handleEditClick"
|
@editClick="handleEditClick"
|
||||||
@deleteClick="$emit('deleteClick', comment)"
|
@deleteClick="$emit('deleteClick', comment)"
|
||||||
@updateReaction="handleUpdateReaction"
|
@updateReaction="handleUpdateReaction"
|
||||||
@ -116,9 +118,20 @@
|
|||||||
password: {
|
password: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
// isEditPushed: {
|
||||||
|
// type: Boolean,
|
||||||
|
// required: false,
|
||||||
|
// },
|
||||||
|
// isDeletePushed: {
|
||||||
|
// type: Boolean,
|
||||||
|
// required: false,
|
||||||
|
// },
|
||||||
editCommentAlert: String,
|
editCommentAlert: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isEditPushed = ref(false);
|
||||||
|
const isDeletePushed = ref(false);
|
||||||
|
|
||||||
const displayName = computed(() => {
|
const displayName = computed(() => {
|
||||||
return props.nickname ? props.nickname : props.comment.author;
|
return props.nickname ? props.nickname : props.comment.author;
|
||||||
});
|
});
|
||||||
@ -171,6 +184,24 @@
|
|||||||
emit('submitPassword', props.comment, props.password);
|
emit('submitPassword', props.comment, props.password);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleInject = inject('isBtnPushed');
|
||||||
|
|
||||||
|
// 수정, 삭제 버튼 활성화 상태값
|
||||||
|
watch(
|
||||||
|
() => handleInject.value,
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
if (newValue.target == props.comment.commentId) {
|
||||||
|
isEditPushed.value = newValue.isEditPushed;
|
||||||
|
isDeletePushed.value = newValue.isDeletePushed;
|
||||||
|
} else {
|
||||||
|
isEditPushed.value = false;
|
||||||
|
isDeletePushed.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.comment.isEditTextarea,
|
() => props.comment.isEditTextarea,
|
||||||
newVal => {
|
newVal => {
|
||||||
|
|||||||
@ -13,6 +13,8 @@
|
|||||||
:currentPasswordCommentId="currentPasswordCommentId"
|
:currentPasswordCommentId="currentPasswordCommentId"
|
||||||
:password="password"
|
:password="password"
|
||||||
:editCommentAlert="editCommentAlert[comment.commentId]"
|
:editCommentAlert="editCommentAlert[comment.commentId]"
|
||||||
|
:is-edit-pushed="comment.isEditPushed"
|
||||||
|
:is-delete-pushed="comment.isDeletePushed"
|
||||||
@editClick="handleEditClick"
|
@editClick="handleEditClick"
|
||||||
@deleteClick="handleDeleteClick"
|
@deleteClick="handleDeleteClick"
|
||||||
@submitPassword="submitPassword"
|
@submitPassword="submitPassword"
|
||||||
@ -40,6 +42,8 @@
|
|||||||
:passwordCommentAlert="passwordCommentAlert"
|
:passwordCommentAlert="passwordCommentAlert"
|
||||||
:password="password"
|
:password="password"
|
||||||
:editCommentAlert="editCommentAlert[child.commentId]"
|
:editCommentAlert="editCommentAlert[child.commentId]"
|
||||||
|
:is-edit-pushed="child.isEditPushed"
|
||||||
|
:is-delete-pushed="child.isDeletePushed"
|
||||||
@editClick="handleReplyEditClick"
|
@editClick="handleReplyEditClick"
|
||||||
@deleteClick="$emit('deleteClick', child)"
|
@deleteClick="$emit('deleteClick', child)"
|
||||||
@submitEdit="(comment, editedContent) => $emit('submitEdit', comment, editedContent, child.commentId)"
|
@submitEdit="(comment, editedContent) => $emit('submitEdit', comment, editedContent, child.commentId)"
|
||||||
@ -59,7 +63,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps, defineEmits } from 'vue';
|
import { defineProps, defineEmits, watch } from 'vue';
|
||||||
import BoardComment from './BoardComment.vue';
|
import BoardComment from './BoardComment.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@ -27,8 +27,8 @@
|
|||||||
<!-- 수정, 삭제 버튼 -->
|
<!-- 수정, 삭제 버튼 -->
|
||||||
<template v-if="!isDeletedComment && (unknown || isCommentAuthor || isAuthor)">
|
<template v-if="!isDeletedComment && (unknown || isCommentAuthor || isAuthor)">
|
||||||
<div class="float-end ms-1">
|
<div class="float-end ms-1">
|
||||||
<EditButton @click.stop="editClick" />
|
<EditButton @click.stop="editClick" :is-pushed="isEditPushed" />
|
||||||
<DeleteButton :class="'ms-1'" @click.stop="deleteClick" />
|
<DeleteButton :class="'ms-1'" @click.stop="deleteClick" :is-pushed="isDeletePushed" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -107,6 +107,14 @@
|
|||||||
type: String,
|
type: String,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
isEditPushed: {
|
||||||
|
type: Boolean,
|
||||||
|
require: false,
|
||||||
|
},
|
||||||
|
isDeletePushed: {
|
||||||
|
type: Boolean,
|
||||||
|
require: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['updateReaction', 'editClick', 'deleteClick']);
|
const emit = defineEmits(['updateReaction', 'editClick', 'deleteClick']);
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<button class="btn btn-label-primary btn-icon">
|
<button class="btn btn-label-primary btn-icon" :class="{ active: props.isPushed }">
|
||||||
<i class='bx bx-trash' ></i>
|
<i class="bx bx-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
const props = defineProps({
|
||||||
name: 'DeleteButton',
|
isPushed: {
|
||||||
methods: {
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<button class="btn btn-label-primary btn-icon" @click="toggleText">
|
<button class="btn btn-label-primary btn-icon" :class="{ active: props.isPushed }" @click="toggleText">
|
||||||
<i :class="buttonClass"></i>
|
<i :class="buttonClass"></i>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch, defineProps, defineEmits, watchEffect } from 'vue';
|
import { ref, watch, defineEmits, watchEffect } from 'vue';
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
isToggleEnabled: {
|
isToggleEnabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -14,18 +14,22 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
isPushed: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const emit = defineEmits(["click"]);
|
const emit = defineEmits(['click']);
|
||||||
const buttonClass = ref('bx bx-edit-alt');
|
const buttonClass = ref('bx bx-edit-alt');
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
buttonClass.value = props.isActive ? 'bx bx-x' : 'bx bx-edit-alt';
|
buttonClass.value = props.isActive ? 'bx bx-x' : 'bx bx-edit-alt';
|
||||||
});
|
});
|
||||||
const toggleText = (event) => {
|
const toggleText = event => {
|
||||||
// 이벤트 객체를 매개변수로 받아옵니다
|
// 이벤트 객체를 매개변수로 받아옵니다
|
||||||
if (props.isToggleEnabled) {
|
if (props.isToggleEnabled) {
|
||||||
buttonClass.value = buttonClass.value === 'bx bx-edit-alt' ? 'bx bx-x' : 'bx bx-edit-alt';
|
buttonClass.value = buttonClass.value === 'bx bx-edit-alt' ? 'bx bx-x' : 'bx bx-edit-alt';
|
||||||
}
|
}
|
||||||
emit("click", event); // 이벤트 객체를 같이 전달
|
emit('click', event); // 이벤트 객체를 같이 전달
|
||||||
};
|
};
|
||||||
const resetButton = () => {
|
const resetButton = () => {
|
||||||
buttonClass.value = 'bx bx-edit-alt';
|
buttonClass.value = 'bx bx-edit-alt';
|
||||||
|
|||||||
@ -6,9 +6,9 @@
|
|||||||
<h5 class="mb-1 me-2">투표진행</h5>
|
<h5 class="mb-1 me-2">투표진행</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body" v-if="voteList.length > 0">
|
<div class="card-body" v-if="voteListData.length > 0">
|
||||||
<ul class="p-0 m-0">
|
<ul class="p-0 m-0">
|
||||||
<li class="d-flex mb-1" v-for="item in voteList" :key="item.LOCVOTSEQ">
|
<li class="d-flex mb-1" v-for="item in voteListData" :key="item.LOCVOTSEQ">
|
||||||
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
<div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<div class="me-2 mb-3">
|
<div class="me-2 mb-3">
|
||||||
<div class="text-muted small">{{ item.localVote.formatted_LOCVOTRDT }}</div>
|
<div class="text-muted small">{{ item.localVote.formatted_LOCVOTRDT }}</div>
|
||||||
@ -23,16 +23,18 @@
|
|||||||
@error="setDefaultImage"
|
@error="setDefaultImage"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="timeline-event ps-1" style="cursor: pointer;" @click="goVoteList()" >
|
<!-- <div class="timeline-event ps-1" style="cursor: pointer;" @click="goVoteList()" > -->
|
||||||
|
<div class="timeline-event ps-1" style="cursor: pointer;" @click.stop="openModal(item.localVote.LOCVOTSEQ)" >
|
||||||
<div class="timeline-header ">
|
<div class="timeline-header ">
|
||||||
<small ><strong>{{ truncateTitle(item.localVote.LOCVOTTTL) }}</strong></small>
|
<small ><strong>{{ truncateTitle(item.localVote.LOCVOTTTL) }}</strong></small>
|
||||||
</div>
|
</div>
|
||||||
<small class="d-flex align-items-center lh-1 me-4 mb-4 mb-sm-0"><span class="badge badge-dot text-bg-warning me-1">
|
<small class="d-flex align-items-center lh-1 me-4 mb-4 mb-sm-0"><span >
|
||||||
</span>{{getDaysAgo(item.localVote.formatted_LOCVOTEDT)}}({{item.localVote.total_voted}}/{{ item.localVote.total_votable }})</small>
|
</span>{{getDaysAgo(item.localVote.formatted_LOCVOTEDT)}}({{item.localVote.total_voted}}/{{ item.localVote.total_votable }})</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -50,13 +52,57 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!--투표 모달 -->
|
||||||
|
<CenterModal :display="isModalOpen" @close="closeModal">
|
||||||
|
<template #title> 투표 하기 </template>
|
||||||
|
<template #body>
|
||||||
|
<div>
|
||||||
|
<vote-list
|
||||||
|
:key="voteListKey"
|
||||||
|
:data="selectVoteDate"
|
||||||
|
@checkedNames="checkedNames"
|
||||||
|
@addContents="addContents"
|
||||||
|
@endVoteId="endVoteId"
|
||||||
|
@voteDelete="voteDelete"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<BackButton @click="closeModal" />
|
||||||
|
</template>
|
||||||
|
</CenterModal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
import $api from '@api';
|
import $api from '@api';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
|
import CenterModal from '@c/modal/CenterModal.vue';
|
||||||
|
import BackButton from '@c/button/BackBtn.vue';
|
||||||
|
import voteList from '@c/voteboard/voteCardList.vue';
|
||||||
|
import { useToastStore } from '@s/toastStore';
|
||||||
|
|
||||||
|
const toastStore = useToastStore();
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const voteset = ref(0);
|
||||||
|
const voteListData= ref([]);
|
||||||
|
const voteListKey = ref(0); //초기화
|
||||||
|
// 로그 모달 상태
|
||||||
|
const isModalOpen = ref(false);
|
||||||
|
const selectVoteDate = ref([]);
|
||||||
|
// 로그 모달 열기
|
||||||
|
const openModal = async (id) => {
|
||||||
|
isModalOpen.value = true;
|
||||||
|
if(id){
|
||||||
|
const selectData = voteListData.value.filter((item) => item.localVote.LOCVOTSEQ === id);
|
||||||
|
selectVoteDate.value = selectData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 로그 모달 닫기
|
||||||
|
const closeModal = () => {
|
||||||
|
isModalOpen.value = false;
|
||||||
|
voteListKey.value++;
|
||||||
|
};
|
||||||
// 프로필 이미지
|
// 프로필 이미지
|
||||||
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
||||||
const defaultProfile = "/img/icons/icon.png";
|
const defaultProfile = "/img/icons/icon.png";
|
||||||
@ -67,9 +113,6 @@ const setDefaultImage = (event) => {
|
|||||||
event.target.src = defaultProfile;
|
event.target.src = defaultProfile;
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentPage = ref(1);
|
|
||||||
const voteset = ref(0);
|
|
||||||
const voteList= ref([]);
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getvoteList();
|
getvoteList();
|
||||||
});
|
});
|
||||||
@ -77,7 +120,6 @@ onMounted(() => {
|
|||||||
//투표목록
|
//투표목록
|
||||||
const getvoteList = () => {
|
const getvoteList = () => {
|
||||||
$api.get('vote/getVoteList',{
|
$api.get('vote/getVoteList',{
|
||||||
//목록조회시 파라미터 전달
|
|
||||||
params:
|
params:
|
||||||
{
|
{
|
||||||
page: 1
|
page: 1
|
||||||
@ -85,11 +127,80 @@ const getvoteList = () => {
|
|||||||
,myVote:'2' //내가 안한 투표
|
,myVote:'2' //내가 안한 투표
|
||||||
}
|
}
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
voteList.value = res.data.data.list;
|
voteListData.value = res.data.data.list;
|
||||||
voteList.value = res.data.data.list.slice(0, 6);
|
voteListData.value = res.data.data.list.slice(0, 6);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//투표하기
|
||||||
|
const checkedNames = (numList) => {
|
||||||
|
$api.post('vote/insertCheckedNums',{
|
||||||
|
checkedList :numList
|
||||||
|
,votenum : numList[0].LOCVOTSEQ
|
||||||
|
}).then((res)=>{
|
||||||
|
if(res.data.status === 'OK'){
|
||||||
|
toastStore.onToast('투표가 완료되었습니다.', 's');
|
||||||
|
isModalOpen.value = false;
|
||||||
|
getvoteList();
|
||||||
|
voteListKey.value++;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//투표항목추가
|
||||||
|
const addContents = (itemList, voteId) => {
|
||||||
|
$api.post('vote/insertWord',{
|
||||||
|
itemList :itemList
|
||||||
|
,voteId :voteId
|
||||||
|
}).then((res)=>{
|
||||||
|
if(res.data.status === 'OK'){
|
||||||
|
toastStore.onToast('항목이 등록되었습니다.', 's');
|
||||||
|
getvoteList();
|
||||||
|
const updatedVote = selectVoteDate.value.find(vote => vote.localVote.LOCVOTSEQ === voteId);
|
||||||
|
if (updatedVote) {
|
||||||
|
if (!updatedVote.voteDetails) {
|
||||||
|
updatedVote.voteDetails = [];
|
||||||
|
}
|
||||||
|
const maxSeq = updatedVote.voteDetails.reduce((max, item) => {
|
||||||
|
return item.VOTDETSEQ > max ? item.VOTDETSEQ : max;
|
||||||
|
}, 0);
|
||||||
|
// 새 항목을 voteDetails에 추가
|
||||||
|
itemList.forEach(item => {
|
||||||
|
updatedVote.voteDetails.push({
|
||||||
|
VOTDETSEQ: maxSeq + 1,
|
||||||
|
LOCVOTSEQ: voteId,
|
||||||
|
LOCVOTCON: item.content,
|
||||||
|
LOCVOTLIK: item.url,
|
||||||
|
VOTE_COUNT: 0,
|
||||||
|
yesvote: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//투표종료
|
||||||
|
const endVoteId = (endVoteId) => {
|
||||||
|
$api.patch('vote/updateEndData',{
|
||||||
|
endVoteId :endVoteId
|
||||||
|
}).then((res)=>{
|
||||||
|
if(res.data.status === 'OK'){
|
||||||
|
getvoteList();
|
||||||
|
isModalOpen.value = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//투표 삭제
|
||||||
|
const voteDelete =(id) =>{
|
||||||
|
$api.patch('vote/updateDeleteData',{
|
||||||
|
deleteVoteId :id
|
||||||
|
}).then((res)=>{
|
||||||
|
if(res.data.status === 'OK'){
|
||||||
|
toastStore.onToast('투표가 삭제되었습니다.', 's');
|
||||||
|
getvoteList();
|
||||||
|
isModalOpen.value = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
// 제목이 14글자 넘어가면 ... 처리하는 함수
|
// 제목이 14글자 넘어가면 ... 처리하는 함수
|
||||||
const truncateTitle = title => {
|
const truncateTitle = title => {
|
||||||
return title.length > 10 ? title.slice(0, 10) + '...' : title;
|
return title.length > 10 ? title.slice(0, 10) + '...' : title;
|
||||||
@ -102,6 +213,7 @@ const goVoteList = () =>{
|
|||||||
query: {
|
query: {
|
||||||
voteset: '2' //투표중
|
voteset: '2' //투표중
|
||||||
,myVote:'2' //내가 안한 투표
|
,myVote:'2' //내가 안한 투표
|
||||||
|
,id:id
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -115,9 +227,9 @@ const getDaysAgo = (dateString) => {
|
|||||||
const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24))+1; // 일 단위 변환
|
const dayDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24))+1; // 일 단위 변환
|
||||||
|
|
||||||
// 오늘 날짜인 경우 "오늘" 반환
|
// 오늘 날짜인 경우 "오늘" 반환
|
||||||
if (dayDiff === 0) return "금일 종료";
|
if (dayDiff === 0) return "⏰금일 종료";
|
||||||
|
|
||||||
return `종료 ${Math.abs(dayDiff)}일 전`;
|
return `⏰종료 ${Math.abs(dayDiff)}일 전`;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap border-top-0 p-0">
|
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap border-top-0 p-0">
|
||||||
<div class="d-flex flex-wrap align-items-center">
|
<div class="d-flex flex-wrap align-items-center">
|
||||||
<ul class="list-unstyled users-list d-flex align-items-center avatar-group m-0 me-2">
|
<ul class="list-unstyled users-list d-flex align-items-center avatar-group">
|
||||||
<vote-complete-user-list-card :data="data"/>
|
<vote-complete-user-list-card :data="data"/>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<img
|
<img
|
||||||
class="rounded-circle user-avatar border border-3"
|
class="rounded-circle user-avatar border border-3"
|
||||||
:src="`${baseUrl}upload/img/profile/${data.MEMBERPRF}`"
|
:src="`${baseUrl}upload/img/profile/${data.MEMBERPRF}`"
|
||||||
:style="`border-color: ${data.usercolor} !important;`"
|
:style="`border-color: ${data.usercolor} !important; width: 90%; height: auto;`"
|
||||||
@error="$event.target.src = '/img/icons/icon.png'"
|
@error="$event.target.src = '/img/icons/icon.png'"
|
||||||
alt="user"
|
alt="user"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap border-top-0 p-0">
|
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap border-top-0 p-0">
|
||||||
<div class="d-flex flex-wrap align-items-center">
|
<div class="d-flex flex-wrap align-items-center">
|
||||||
<ul class="list-unstyled users-list d-flex align-items-center avatar-group m-0 me-2">
|
<ul class="list-unstyled users-list d-flex align-items-center avatar-group ">
|
||||||
<vote-in-complete-user-list-card :data="data" />
|
<vote-in-complete-user-list-card :data="data" />
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<img
|
<img
|
||||||
class="rounded-circle user-avatar border border-3"
|
class="rounded-circle user-avatar border border-3"
|
||||||
:src="`${baseUrl}upload/img/profile/${data.MEMBERPRF}`"
|
:src="`${baseUrl}upload/img/profile/${data.MEMBERPRF}`"
|
||||||
:style="`border-color: ${data.usercolor} !important;`"
|
:style="`border-color: ${data.usercolor} !important; width: 90%; height: auto;`"
|
||||||
@error="$event.target.src = '/img/icons/icon.png'"
|
@error="$event.target.src = '/img/icons/icon.png'"
|
||||||
alt="user"
|
alt="user"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<div class="d-flex align-items-start mt-3">
|
<div class="d-flex align-items-start mt-3">
|
||||||
<!--투표한 사람 목록 -->
|
<!--투표한 사람 목록 -->
|
||||||
<div class="d-flex align-items-center gap-2 flex-wrap">
|
<div class="d-flex align-items-center gap-2 flex-wrap">
|
||||||
<i class='bx bxs-user-check link-info fa-3x'></i>
|
<i class='bx bxs-user-check link-info fa-2x'></i>
|
||||||
<vote-complete-user-list
|
<vote-complete-user-list
|
||||||
v-for="(item, index) in voetedUsers"
|
v-for="(item, index) in voetedUsers"
|
||||||
:key="index"
|
:key="index"
|
||||||
@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 투표안한 사람 목록 -->
|
<!-- 투표안한 사람 목록 -->
|
||||||
<div class="d-flex align-items-center gap-2 ms-auto flex-wrap">
|
<div class="d-flex align-items-center gap-2 ms-auto flex-wrap">
|
||||||
<i class='bx bxs-user-x link-danger fa-3x'></i>
|
<i class='bx bxs-user-x link-danger fa-2x'></i>
|
||||||
<vote-in-complete-user-list
|
<vote-in-complete-user-list
|
||||||
v-for="(item, index) in noVoetedUsers"
|
v-for="(item, index) in noVoetedUsers"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|||||||
@ -17,6 +17,8 @@
|
|||||||
:date="formattedBoardDate"
|
:date="formattedBoardDate"
|
||||||
:isLike="false"
|
:isLike="false"
|
||||||
:isAuthor="isAuthor"
|
:isAuthor="isAuthor"
|
||||||
|
:is-edit-pushed="isEditPushed"
|
||||||
|
:is-delete-pushed="isDeletePushed"
|
||||||
@editClick="editClick"
|
@editClick="editClick"
|
||||||
@deleteClick="deleteClick"
|
@deleteClick="deleteClick"
|
||||||
/>
|
/>
|
||||||
@ -142,7 +144,7 @@
|
|||||||
import BoardCommentList from '@c/board/BoardCommentList.vue';
|
import BoardCommentList from '@c/board/BoardCommentList.vue';
|
||||||
import BoardRecommendBtn from '@c/button/BoardRecommendBtn.vue';
|
import BoardRecommendBtn from '@c/button/BoardRecommendBtn.vue';
|
||||||
import Pagination from '@c/pagination/Pagination.vue';
|
import Pagination from '@c/pagination/Pagination.vue';
|
||||||
import { ref, onMounted, computed, inject } from 'vue';
|
import { ref, onMounted, computed, inject, provide } 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 { useToastStore } from '@s/toastStore';
|
import { useToastStore } from '@s/toastStore';
|
||||||
@ -165,6 +167,8 @@
|
|||||||
const attachment = ref(false);
|
const attachment = ref(false);
|
||||||
const comments = ref([]);
|
const comments = ref([]);
|
||||||
const profileImg = ref('');
|
const profileImg = ref('');
|
||||||
|
const isEditPushed = ref(false);
|
||||||
|
const isDeletePushed = ref(false);
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -319,6 +323,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
fetchComments(pagination.value.currentPage);
|
fetchComments(pagination.value.currentPage);
|
||||||
|
closeAllEditTextareas();
|
||||||
|
closeAllPasswordAreas();
|
||||||
|
activeCommentBtnClass();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 댓글 목록 조회
|
// 댓글 목록 조회
|
||||||
@ -476,6 +483,9 @@
|
|||||||
|
|
||||||
if (isUnknown) {
|
if (isUnknown) {
|
||||||
togglePassword('edit');
|
togglePassword('edit');
|
||||||
|
closeAllEditTextareas();
|
||||||
|
closeAllPasswordAreas();
|
||||||
|
activeCommentBtnClass();
|
||||||
} else {
|
} else {
|
||||||
router.push({ name: 'BoardEdit', params: { id: currentBoardId.value } });
|
router.push({ name: 'BoardEdit', params: { id: currentBoardId.value } });
|
||||||
}
|
}
|
||||||
@ -505,11 +515,36 @@
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const btnState = ref({});
|
||||||
|
provide('isBtnPushed', btnState);
|
||||||
|
|
||||||
|
const activeCommentBtnClass = (targetComment = null, type = 3) => {
|
||||||
|
const target = targetComment?.commentId;
|
||||||
|
let editPush = false;
|
||||||
|
let deletePush = false;
|
||||||
|
|
||||||
|
if (targetComment) {
|
||||||
|
if (type == 1) {
|
||||||
|
editPush = true;
|
||||||
|
deletePush = false;
|
||||||
|
} else if (type == 2) {
|
||||||
|
editPush = false;
|
||||||
|
deletePush = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btnState.value = {
|
||||||
|
target: target,
|
||||||
|
isEditPushed: editPush,
|
||||||
|
isDeletePushed: deletePush,
|
||||||
|
};
|
||||||
|
};
|
||||||
// 댓글 수정 클릭 시 이벤트(대댓글 포함)
|
// 댓글 수정 클릭 시 이벤트(대댓글 포함)
|
||||||
const editComment = comment => {
|
const editComment = comment => {
|
||||||
|
acitveButtonType(); //게시글 버튼 클릭 클래스 제거
|
||||||
|
|
||||||
password.value = '';
|
password.value = '';
|
||||||
passwordCommentAlert.value = '';
|
passwordCommentAlert.value = '';
|
||||||
//currentPasswordCommentId.value = null;
|
|
||||||
isPassword.value = false; // 상단 프로필 비밀번호
|
isPassword.value = false; // 상단 프로필 비밀번호
|
||||||
|
|
||||||
const targetComment = findCommentById(comment.commentId, comments.value);
|
const targetComment = findCommentById(comment.commentId, comments.value);
|
||||||
@ -522,27 +557,20 @@
|
|||||||
if (isMyComment) {
|
if (isMyComment) {
|
||||||
if (targetComment.isEditTextarea) {
|
if (targetComment.isEditTextarea) {
|
||||||
// 수정창이 열려 있는 상태에서 다시 수정 버튼을 누르면 초기화
|
// 수정창이 열려 있는 상태에서 다시 수정 버튼을 누르면 초기화
|
||||||
|
|
||||||
targetComment.isEditTextarea = false;
|
targetComment.isEditTextarea = false;
|
||||||
|
|
||||||
currentPasswordCommentId.value = comment.commentId;
|
currentPasswordCommentId.value = comment.commentId;
|
||||||
|
activeCommentBtnClass(targetComment, 3);
|
||||||
} else {
|
} else {
|
||||||
// 다른 모든 댓글의 수정창 닫기
|
closeAllEditTextareas(); // 다른 모든 댓글의 수정창 닫기
|
||||||
closeAllEditTextareas();
|
currentPasswordCommentId.value = null; // 현재 댓글만 수정 모드 활성화
|
||||||
currentPasswordCommentId.value = null;
|
targetComment.isEditTextarea = true; // 선택 버튼 활성화 상태 제어
|
||||||
// 현재 댓글만 수정 모드 활성화
|
activeCommentBtnClass(targetComment, 1);
|
||||||
targetComment.isEditTextarea = true;
|
|
||||||
}
|
}
|
||||||
} else if (isAnonymous) {
|
} else if (isAnonymous) {
|
||||||
if (currentPasswordCommentId.value === comment.commentId) {
|
if (currentPasswordCommentId.value === comment.commentId) {
|
||||||
// 이미 비밀번호 입력 중이면 유지
|
toggleCommentPassword(comment, 'edit'); // 이미 비밀번호 입력 중이면 유지
|
||||||
toggleCommentPassword(comment, 'edit');
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
// 다른 모든 댓글의 수정창 닫기
|
closeAllEditTextareas(); // 다른 모든 댓글의 수정창 닫기
|
||||||
closeAllEditTextareas();
|
|
||||||
|
|
||||||
// 비밀번호 입력
|
|
||||||
targetComment.isEditTextarea = false;
|
targetComment.isEditTextarea = false;
|
||||||
toggleCommentPassword(comment, 'edit');
|
toggleCommentPassword(comment, 'edit');
|
||||||
}
|
}
|
||||||
@ -551,6 +579,26 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 댓글 삭제 버튼 클릭
|
||||||
|
const deleteComment = async comment => {
|
||||||
|
const isMyComment = comment.authorId === currentUserId.value;
|
||||||
|
|
||||||
|
// 익명인 경우
|
||||||
|
if (unknown.value && !isMyComment) {
|
||||||
|
// 수정 에디터 열려있을때
|
||||||
|
if (comment.isEditTextarea) {
|
||||||
|
comment.isEditTextarea = false;
|
||||||
|
comment.isCommentPassword = true;
|
||||||
|
toggleCommentPassword(comment, 'delete');
|
||||||
|
} else {
|
||||||
|
activeCommentBtnClass(comment, 3);
|
||||||
|
toggleCommentPassword(comment, 'delete');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deleteReplyComment(comment);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 모든 댓글의 수정 창 닫기
|
// 모든 댓글의 수정 창 닫기
|
||||||
const closeAllEditTextareas = () => {
|
const closeAllEditTextareas = () => {
|
||||||
comments.value.forEach(comment => {
|
comments.value.forEach(comment => {
|
||||||
@ -568,30 +616,20 @@
|
|||||||
passwordCommentAlert.value = '';
|
passwordCommentAlert.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 댓글 삭제 버튼 클릭
|
|
||||||
const deleteComment = async comment => {
|
|
||||||
const isMyComment = comment.authorId === currentUserId.value;
|
|
||||||
|
|
||||||
if (unknown.value && !isMyComment) {
|
|
||||||
if (comment.isEditTextarea) {
|
|
||||||
comment.isEditTextarea = false;
|
|
||||||
comment.isCommentPassword = true;
|
|
||||||
toggleCommentPassword(comment, 'delete');
|
|
||||||
} else {
|
|
||||||
toggleCommentPassword(comment, 'delete');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deleteReplyComment(comment);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 익명 댓글 비밀번호 창 토글
|
// 익명 댓글 비밀번호 창 토글
|
||||||
const toggleCommentPassword = (comment, button) => {
|
const toggleCommentPassword = (comment, button) => {
|
||||||
if (lastCommentClickedButton.value === button && currentPasswordCommentId.value === comment.commentId) {
|
if (lastCommentClickedButton.value === button && currentPasswordCommentId.value === comment.commentId) {
|
||||||
currentPasswordCommentId.value = null; // 비밀번호 창 닫기
|
currentPasswordCommentId.value = null; // 비밀번호 창 닫기
|
||||||
password.value = '';
|
password.value = '';
|
||||||
passwordCommentAlert.value = '';
|
passwordCommentAlert.value = '';
|
||||||
|
activeCommentBtnClass(comment, 3);
|
||||||
} else {
|
} else {
|
||||||
|
if (button == 'edit') {
|
||||||
|
activeCommentBtnClass(comment, 1);
|
||||||
|
} else if (button == 'delete') {
|
||||||
|
activeCommentBtnClass(comment, 2);
|
||||||
|
}
|
||||||
|
|
||||||
currentPasswordCommentId.value = comment.commentId; // 비밀번호 창 열기
|
currentPasswordCommentId.value = comment.commentId; // 비밀번호 창 열기
|
||||||
password.value = '';
|
password.value = '';
|
||||||
passwordCommentAlert.value = '';
|
passwordCommentAlert.value = '';
|
||||||
@ -608,17 +646,49 @@
|
|||||||
isPassword.value = false;
|
isPassword.value = false;
|
||||||
boardPasswordAlert.value = '';
|
boardPasswordAlert.value = '';
|
||||||
password.value = '';
|
password.value = '';
|
||||||
|
acitveButtonType();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
closeAllPasswordAreas();
|
closeAllPasswordAreas();
|
||||||
if (lastClickedButton.value === button) {
|
if (lastClickedButton.value === button) {
|
||||||
isPassword.value = !isPassword.value;
|
isPassword.value = !isPassword.value;
|
||||||
boardPasswordAlert.value = '';
|
boardPasswordAlert.value = '';
|
||||||
|
lastClickedButton.value = '';
|
||||||
|
acitveButtonType();
|
||||||
} else {
|
} else {
|
||||||
isPassword.value = true;
|
isPassword.value = true;
|
||||||
}
|
|
||||||
|
|
||||||
lastClickedButton.value = button;
|
lastClickedButton.value = button;
|
||||||
|
|
||||||
|
if (button == 'edit') {
|
||||||
|
acitveButtonType(1);
|
||||||
|
} else if (button == 'delete') {
|
||||||
|
acitveButtonType(2);
|
||||||
|
} else {
|
||||||
|
acitveButtonType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 선택한 게시글 버튼 핸들링(수정, 삭제 버튼)
|
||||||
|
const acitveButtonType = type => {
|
||||||
|
//closeAllEditTextareas(); //다른 모든 텍스트 에디터 비활성화
|
||||||
|
//inActiveCommentButtonClass(); // 댓글 버튼 비활성화
|
||||||
|
|
||||||
|
// 수정
|
||||||
|
if (type == 1) {
|
||||||
|
isEditPushed.value = true;
|
||||||
|
isDeletePushed.value = false;
|
||||||
|
|
||||||
|
// 삭제
|
||||||
|
} else if (type == 2) {
|
||||||
|
isEditPushed.value = false;
|
||||||
|
isDeletePushed.value = true;
|
||||||
|
|
||||||
|
// 비활성화
|
||||||
|
} else {
|
||||||
|
isEditPushed.value = false;
|
||||||
|
isDeletePushed.value = false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 게시글 비밀번호 제출
|
// 게시글 비밀번호 제출
|
||||||
@ -738,6 +808,7 @@
|
|||||||
if (response.data.code === 200) {
|
if (response.data.code === 200) {
|
||||||
await fetchComments(pagination.value.currentPage);
|
await fetchComments(pagination.value.currentPage);
|
||||||
closeAllPasswordAreas();
|
closeAllPasswordAreas();
|
||||||
|
activeCommentBtnClass();
|
||||||
|
|
||||||
if (targetComment) {
|
if (targetComment) {
|
||||||
// 댓글 내용만 "삭제된 댓글입니다."로 변경하고, 구조는 유지
|
// 댓글 내용만 "삭제된 댓글입니다."로 변경하고, 구조는 유지
|
||||||
@ -766,6 +837,7 @@
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
togglePassword('close');
|
togglePassword('close');
|
||||||
fetchComments(pagination.value.currentPage);
|
fetchComments(pagination.value.currentPage);
|
||||||
|
activeCommentBtnClass();
|
||||||
return;
|
return;
|
||||||
// const targetComment = findCommentById(comment.commentId, comments.value);
|
// const targetComment = findCommentById(comment.commentId, comments.value);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user