localhost-front/src/components/wordDict/DictCard.vue
2025-02-20 14:19:35 +09:00

218 lines
7.1 KiB
Vue

<template>
<li class="mt-5 card p-5">
<DictWrite
v-if="isWriteVisible"
@close="isWriteVisible = false"
:dataList="cateList"
@addCategory="addCategory"
@addWord="editWord"
:NumValue="item.WRDDICSEQ"
:formValue="item.WRDDICCAT"
:titleValue="item.WRDDICTTL"
:contentValue="item.WRDDICCON"
/>
<div v-else>
<input
v-if="userStore.user.role == 'ROLE_ADMIN'"
type="checkbox"
class="form-check-input admin-chk"
:name="item.WRDDICSEQ"
id=""
@change="toggleCheck($event)"
>
<div class="d-flex align-ite-center">
<div class="w-100 d-flex align-items-center">
<span class="btn btn-primary pe-none">{{ item.category }}</span>
<strong class="mx-2 w-75">{{ item.WRDDICTTL }}</strong>
</div>
</div>
<p class="mt-5" v-html="$common.contentToHtml(item.WRDDICCON)"></p>
<div class="d-flex justify-content-between flex-wrap gap-2 mb-2">
<div class="d-flex flex-wrap align-items-center mb-50">
<div class="avatar avatar-sm me-2">
<img
class="rounded-circle user-avatar"
:src="getProfileImage(item.author.profileImage)"
alt="최초 작성자"
:style="{ borderColor: item.author.color}"/>
</div>
<div>
<p class="mb-0 small fw-medium">{{ formatDate(item.author.createdAt) }}</p>
</div>
</div>
</div>
<div
v-if="item.author.createdAt !== item.lastEditor.updatedAt"
class="d-flex justify-content-between flex-wrap gap-2 mb-2"
>
<div class="d-flex flex-wrap align-items-center mb-50">
<div class="avatar avatar-sm me-2">
<img
class="rounded-circle user-avatar"
:src="getProfileImage(item.lastEditor.profileImage)"
alt="최근 작성자"
:style="{ borderColor: item.lastEditor.color}"/>
</div>
<div>
<p class="mb-0 small fw-medium">{{ formatDate(item.lastEditor.updatedAt) }}</p>
</div>
</div>
</div>
</div>
<div class="edit-btn">
<EditBtn @click="toggleWriteVisible" />
</div>
</li>
</template>
<script setup>
import axios from "@api";
import { useToastStore } from '@s/toastStore';
import { ref, toRefs, getCurrentInstance, } from 'vue';
import EditBtn from '@/components/button/EditBtn.vue';
import $api from '@api';
import DictWrite from './DictWrite.vue';
import { useUserInfoStore } from '@s/useUserInfoStore';
// 유저 구분
const userStore = useUserInfoStore();
const toastStore = useToastStore();
const { appContext } = getCurrentInstance();
const $common = appContext.config.globalProperties.$common;
// Props
const props = defineProps({
item: {
type: Object,
required: true
},
cateList: {
type: Array,
required: false,
}
});
// 카테고리
const localCateList = ref([...props.cateList]);
// 선택 카테고리
const selectedCategory = ref('');
// cateList emit
const emit = defineEmits(['update:cateList','refreshWordList', 'updateChecked']);
// 글 수정 상태
const isWriteVisible = ref(false);
// 글 수정 toggle
const toggleWriteVisible = () => {
isWriteVisible.value = !isWriteVisible.value;
};
//카테고리 등록 수정
const addCategory = (data) => {
try {
const lastCategory = localCateList.value.length > 0
? localCateList.value[localCateList.value.length - 1]
: null;
const newValue = lastCategory ? lastCategory.value + 1 : 600101;
axios.post('worddict/insertCategory', {
CMNCODNAM: data
}).then(res => {
if(res.data.data === 1){
toastStore.onToast('카테고리가 추가 등록 되었습니다.', 's');
const newCategory = { label: data, value: newValue };
localCateList.value = [newCategory, ...localCateList.value];
selectedCategory.value = newCategory.value;
// 부모에게 전달
emit('update:cateList', localCateList.value);
}
}).catch(err => {
console.error('카테고리 추가 중 오류:', err);
});
} catch (err) {
console.error('카테고리 추가 함수 오류:', err);
}
}
// 용어집 수정
const editWord = (data) => {
console.log('📌 수정할 데이터:', data);
console.log('📌 수정할 데이터:', data.id);
console.log('📌 수정할 데이터:', data.category);
console.log('📌 수정할 데이터:', data.title);
console.log('📌 수정할 데이터:', $common.deltaAsJson(data.content));
if (!data.id) {
console.error('❌ 수정할 데이터의 ID가 없습니다.');
toastStore.onToast('수정할 용어의 ID가 필요합니다.', 'e');
return;
}
axios.patch('worddict/updateWord', {
WRDDICSEQ: data.id,
WRDDICCAT: data.category,
WRDDICTTL: data.title,
WRDDICCON: $common.deltaAsJson(data.content),
})
.then((res) => {
if (res.data.data === 1) {
toastStore.onToast('✅ 용어가 수정되었습니다.', 's');
isWriteVisible.value = false;
emit('refreshWordList');
} else {
console.warn('⚠️ 서버 응답이 예상과 다릅니다:', res.data);
toastStore.onToast('용어 수정이 정상적으로 처리되지 않았습니다.', 'e');
}
})
.catch((err) => {
console.error('❌ 용어 수정 중 오류 발생:', err.response?.data || err.message);
toastStore.onToast(`용어 수정 실패: ${err.response?.data?.message || '알 수 없는 오류'}`, 'e');
});
};
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
// 날짜 포맷
const formatDate = (dateString) => new Date(dateString).toLocaleString();
// 프로필 이미지
const getProfileImage = (imagePath) =>
imagePath ? `${baseUrl}upload/img/profile/${imagePath}` : '/img/avatars/default-Profile.jpg';
// 체크 상태 변경 시 부모로 전달
const toggleCheck = (event) => {
emit('updateChecked', event.target.checked, props.item.WRDDICSEQ, event.target.name);
};
</script>
<style scoped>
/* 동그란 테두리 설정 */
.user-avatar {
border: 3px solid; /* 테두리 */
padding: 0.1px; /* 테두리와 이미지 사이의 간격 */
}
.edit-btn {
position: absolute;
right: 0.7rem;
top: 1.2rem;
}
.admin-chk {
position: absolute;
left: -0.5rem;
top: -0.5rem;
--bs-form-check-bg: #fff;
}
</style>