288 lines
9.4 KiB
Vue
288 lines
9.4 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"/>
|
|
<!-- ㄱ ㄴ ㄷ ㄹ -->
|
|
<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>
|
|
<!-- 로딩 중일 때 -->
|
|
<LoadingSpinner v-if="loading"/>
|
|
<!-- 에러 메시지 -->
|
|
<div v-if="error" class="error">{{ 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 loading = ref(false);
|
|
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 = () => {
|
|
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;
|
|
loading.value = false;
|
|
})
|
|
.catch(err => {
|
|
console.error('데이터 로드 오류:', err);
|
|
error.value = '데이터를 가져오는 중 문제가 발생했습니다.';
|
|
loading.value = false;
|
|
});
|
|
};
|
|
//정렬 목록
|
|
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 {
|
|
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 {
|
|
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;
|
|
}
|
|
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();
|
|
}
|
|
getwordList();
|
|
getIndex();
|
|
selectedCategory.value = 'all';
|
|
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;
|
|
}
|
|
.error {
|
|
color: red;
|
|
font-weight: bold;
|
|
}
|
|
.sidebar {
|
|
position: sticky;
|
|
top: 5px;
|
|
height: fit-content;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.title {
|
|
margin-bottom: 0.5rem !important;
|
|
}
|
|
}
|
|
</style>
|