localhost-front/src/views/wordDict/wordDict.vue
2025-03-25 11:04:08 +09:00

288 lines
9.8 KiB
Vue

<template>
<div class="container-xxl flex-grow-1 container-p-y d-flex">
<!-- 메인 컨텐츠 -->
<div class="flex-grow-1">
<!-- 타이틀, 검색 -->
<SearchBar @update:data="search"/>
<div class="d-flex">
<!-- 단어 갯수, 작성하기 -->
<!-- 왼쪽 사이드바 -->
<div class="sidebar position-sticky" style="top: 100px; max-width: 250px; min-width: 250px;">
<WriteButton ref="writeButton" @click="writeStore.toggleItem(999999)" :isToggleEnabled="true"
:isActive="writeStore.activeItemId === 999999"/>
<!-- -->
<DictAlphabetFilter @update:data="handleSelectedAlphabetChange" :indexCategory="indexCategory" :selectedAl="selectedAlphabet" />
<!-- 카테고리 -->
<div v-if="cateList.length" class="mt-3">
<CategoryBtn :lists="cateList" @update:data="handleSelectedCategoryChange" :showAll="true" :selectedCategory="selectedCategory" />
</div>
</div>
<!-- 용어 리스트 컨텐츠 -->
<div class="flex-grow-1">
<!-- 작성 -->
<div v-if="writeStore.isItemActive(999999)" class="ms-3 card p-5 mb-2">
<DictWrite @close="writeStore.closeAll()" :dataList="cateList" @addWord="addWord"/>
</div>
<!-- 용어 리스트 -->
<div>
<!-- 에러 메시지 -->
<div v-if="error" class="fw-bold text-danger">{{ error }}</div>
<!-- 단어 목록 -->
<ul v-if="total > 0" class="ms-3 list-unstyled">
<DictCard
v-for="item in wordList"
:key="item.WRDDICSEQ"
:item="item"
v-model:cateList="cateList"
@refreshWordList="refreshWordList"
@updateChecked="updateCheckedItems"
/>
</ul>
<!-- 데이터가 없을 때 -->
<div v-if="total == 0" class="text-center mt-5">용어를 선택 / 작성해 주세요</div>
</div>
</div>
</div>
</div>
</div>
<button v-if="isAnyChecked" class="btn btn-danger admin-del-btn" @click="deleteCheckedItems">
<i class="bx bx-trash"></i>
</button>
</template>
<script setup>
import { ref, computed, onMounted, getCurrentInstance, toRaw } from 'vue';
import axios from '@api';
import SearchBar from '@c/search/SearchBar.vue';
import WriteButton from '@c/button/WriteBtn.vue';
import CategoryBtn from '@/components/category/CategoryBtn.vue';
import DictCard from '@/components/wordDict/DictCard.vue';
import DictWrite from '@/components/wordDict/DictWrite.vue';
import DictAlphabetFilter from '@/components/wordDict/DictAlphabetFilter.vue';
import commonApi from '@/common/commonApi';
import { useToastStore } from '@s/toastStore';
import { useWriteVisibleStore } from '@s/writeVisible';
import LoadingSpinner from "@v/LoadingPage.vue";
// 작성창 구분
const writeStore = useWriteVisibleStore();
const writeButton = ref(null);
const { appContext } = getCurrentInstance();
const $common = appContext.config.globalProperties.$common;
const toastStore = useToastStore();
// 공통
const error = ref('');
// 용어집
const wordList = ref([]);
//용어집 총개수
const total = ref(0);
// 카테고리
const { cateList } = commonApi({
loadCateList: true
});
const selectedCategory = ref('');
// 체크박스 체크된 갯수
const checkedItems = ref([]);
// 체크박스의 name
const checkedNames = ref([]);
//선택된 알파벳
const selectedAlphabet = ref('');
// 검색
const searchText = ref('');
//검색 정렬
const indexCategory = ref([]);
// 데이터 로드
onMounted(() => {
getIndex();
writeStore.closeAll();
});
const refreshWordList = (category) => {
selectedCategory.value = category;
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
};
//용어 목록
const getwordList = (searchKeyword='', indexKeyword='', category='') => {
axios.get('worddict/getWordList',{
//목록조회시 파라미터 전달
params: {
searchKeyword : searchKeyword,
indexKeyword :indexKeyword,
category : category
}
})
.then(res => {
// 용어 목록 저장
wordList.value = res.data.data.data;
// 총 개수 저장
total.value = res.data.data.total;
})
.catch(err => {
console.error('데이터 로드 오류:', err);
error.value = '데이터를 가져오는 중 문제가 발생했습니다.';
});
};
//정렬 목록
const getIndex = () => {
axios.get('worddict/getIndexCategory').then(res=>{
if(res.data.status ="OK"){
indexCategory.value = res.data.data;
}
})
}
// 검색
const search = (e) => {
searchText.value = e.trim();
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
};
// 알파벳 선택
const handleSelectedAlphabetChange = (newAlphabet) => {
selectedAlphabet.value = newAlphabet;
if (newAlphabet !== null) {
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
} else {
if( selectedCategory.value !== '' && selectedCategory.value !== null){
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
}
wordList.value = [];
total.value = 0;
}
};
// 카테고리 선택
const handleSelectedCategoryChange = (category) => {
selectedCategory.value = category;
if (category !== null ) {
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
if(category == 'all'){
getwordList(searchText.value, selectedAlphabet.value, '');
}
} else {
if( selectedAlphabet.value !== '' && selectedAlphabet.value !== null){
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
}
wordList.value = [];
total.value = 0;
}
}
// 용어집 등록
const addWord = (wordData, data) => {
let category = null;
let newCodName = '';
// 카테고리 체크
if(typeof(data) == 'number'){
category = data;
newCodName = '';
}else{
const lastCategory = cateList.value[cateList.value.length - 1];
category = lastCategory ? lastCategory.value + 1 : 600101;
newCodName = data.trim();
}
sendWordRequest(category, wordData, newCodName);
};
const sendWordRequest = (category, wordData, data) => {
const payload = {
WRDDICCAT: category,
WRDDICTTL: wordData.title,
WRDDICCON: $common.deltaAsJson(wordData.content),
};
payload.CMNCODNAM = data;
axios.post('worddict/insertWord', payload).then(res => {
if (res.data.status === 'OK') {
toastStore.onToast('용어가 등록 되었습니다.', 's');
writeStore.closeAll();
if (writeButton.value) {
writeButton.value.resetButton();
}
selectedCategory.value = category;
getwordList(searchText.value, selectedAlphabet.value, selectedCategory.value);
getIndex();
if(res.data.data == '2'){
const newCategory = { label: data, value: category };
cateList.value = [...cateList.value,newCategory];
}
selectedAlphabet.value = '';
}
});
};
// 체크 상태 업데이트
const updateCheckedItems = (checked, id, name) => {
if (checked) {
checkedItems.value.push(id);
checkedNames.value.push(Number(name));
} else {
checkedItems.value = checkedItems.value.filter(item => item !== id);
checkedNames.value = checkedNames.value.filter(item => item !== name);
}
};
const isAnyChecked = computed(() => checkedItems.value.length > 0);
// 용어집 삭제
const deleteCheckedItems = () => {
axios.patch('worddict/deleteword', {
idList: Object.values(checkedNames.value)
})
.then(res => {
if (res.data.status == 'OK') {
toastStore.onToast('용어 삭제가 완료되었습니다.', 's');
writeStore.closeAll();
getwordList();
// 삭제 후 초기화
checkedItems.value = [];
checkedNames.value = [];
}
})
.catch(error => {
toastStore.onToast('오류가 발생했습니다. 다시 시도해주세요.', 'e');
});
};
</script>
<style scoped>
.admin-del-btn {
position: fixed;
right: 1.5rem;
bottom: 1.5rem;
width: 3rem;
height: 3rem;
}
.sidebar {
position: sticky;
top: 5px;
height: fit-content;
}
.DictCard {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1rem;
}
</style>