File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="title-box flex justify-between mb40">
<p class="title">단어장</p>
<select v-model="selectedBookId" @change="fetchUnits">
<option v-for="book in books" :key="book.book_id" :value="book.book_id">
{{ book.book_nm }}
</option>
</select>
</div>
<label for="" class="title2">단원</label>
<div class="unit-pagination flex mt10 mb20" style="gap: 10px;">
<button v-for="unit in units" :key="unit.unitId" @click="selectUnit(unit.unitId)" :class="{ 'selected-btn': selectedUnitId === unit.unitId }">
{{ unit.unitName }}
</button>
</div>
<div class="search-wrap flex justify-between mb20 align-center">
<div class="title2 gray flex">{{ titleMessage }}</div>
<div>
<select v-model="searchType" class="mr10 data-wrap">
<option value="text">지문</option>
<option value="word">단어</option>
</select>
<input v-model="searchQuery" type="text" placeholder="검색하세요.">
<button type="button" title="단어장 검색" @click="searchWordBooks">
<img src="../../../resources/img/look_t.png" alt="">
</button>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<td>No.</td>
<td>지문</td>
<td>단어 목록</td>
<td>작성자</td>
</thead>
<tbody>
<tr v-for="(wordBook, index) in dataList" :key="wordBook.wdBookId" @click="goToViewPage('VocaDetail', wordBook.wdBookId)">
<td>{{ createNo(index) }}</td>
<td>{{ wordBook.textTtl }}</td>
<td>{{ wordBook.wordsPreview }}</td>
<td>{{ wordBook.userNm }}</td>
</tr>
</tbody>
</table>
<article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;">
<button @click="goToPage(currentPage - 1)">
<img src="../../../resources/img/btn27_90t_normal.png" alt="">
</button>
<button v-for="page in paginationButtons" :key="page" @click="goToPage(page - 1)" :class="{ 'selected-btn': currentPage === page - 1 }">
{{ page }}
</button>
<button @click="goToPage(currentPage + 1)">
<img src="../../../resources/img/btn28_90t_normal.png" alt="">
</button>
</article>
<div class="flex justify-end ">
<button type="button" title="등록" class="new-btn" @click="goToViewPage('VocaInsert')">
등록
</button>
</div>
</div>
</template>
<script>
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiMagnify } from '@mdi/js';
import axios from "axios";
export default {
data () {
return {
mdiMagnify: mdiMagnify,
books: [],
units: [],
selectedBookId: null, // 선택된 책 ID 저장 변수
selectedUnitId: null, // 선택된 단원 ID 저장 변수
selectedUnitName: '', // 선택된 단원의 이름 저장 변수
titleMessage: '', // 타이틀 메시지 변수
dataList: [],
currentPage: 0,
itemsPerPage: 5,
totalPosts: 0,
searchType: 'text', // 검색 종류를 저장할 변수
searchQuery: '' // 검색어를 저장할 변수
}
},
methods: {
// 모든 책 목록을 가져오는 메서드
fetchBooks() {
axios.post('/book/findAll.json')
.then(response => {
this.books = response.data;
if (this.books.length > 0) {
this.selectedBookId = this.books[1].book_id; // 두 번째 책을 선택하도록 기본 설정
this.fetchUnits(); // 책 선택 후 단원 목록 가져오기
}
})
.catch(error => {
console.error("책 목록 가져오기 실패: ", error);
});
},
// 선택된 책의 단원 목록을 가져오는 메서드
fetchUnits() {
axios.post('/unit/unitList.json', { bookId: this.selectedBookId })
.then(response => {
this.units = response.data;
if (this.units.length > 0) {
this.selectUnit(this.units[4].unitId); // 다섯 번째 단원을 선택하도록 기본 설정
}
})
.catch(error => {
console.error("단원 목록 가져오기 실패: ", error);
});
},
// 단원을 선택했을 때 호출되는 메서드
selectUnit(unitId) {
this.selectedUnitId = unitId;
const selectedUnit = this.units.find(unit => unit.unitId === unitId);
this.selectedUnitName = selectedUnit ? selectedUnit.unitName : '';
this.searchQuery = '';
this.titleMessage = `[${this.selectedUnitName}] 단원 전체 목록`;
this.dataSelectList(); // 단어장 목록 조회
},
// 단어장 목록 조회 메서드
dataSelectList() {
const vm = this;
axios({
url: "/wordbook/findByUnitId.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: {
unitId: vm.selectedUnitId,
page: vm.currentPage + 1,
pageSize: vm.itemsPerPage
},
})
.then(function (response) {
console.log("dataList - response: ", response.data);
const wordBooks = response.data.wordBooks;
vm.totalPosts = response.data.totalWordBooks;
// 지문 제목 및 단어 목록 가져오기
const fetchDataPromises = wordBooks.map(wordBook => {
const textTitlePromise = axios.post("/text/selectOneText.json", {
textId: wordBook.textId
}).then(textResponse => {
wordBook.textTtl = textResponse.data[0].text_ttl;
}).catch(error => {
console.error(`${wordBook.textId}으로 지문 제목 가져오기 실패: `, error);
wordBook.textTtl = '제목값없음'; // 오류 시 기본값 설정
});
const wordsPromise = axios.post("/word/getWordsByBookId.json", {
wdBookId: wordBook.wdBookId
}).then(wordsResponse => {
const words = wordsResponse.data.map(word => word.wdNm);
wordBook.wordsPreview = vm.generateWordsPreview(words);
}).catch(error => {
console.error(`${wordBook.wdBookId}으로 단어 목록 가져오기 실패: `, error);
wordBook.wordsPreview = '단어값없음'; // 오류 시 기본값 설정
});
return Promise.all([textTitlePromise, wordsPromise]);
});
// 모든 데이터 가져오기 작업이 완료되면 dataList에 데이터 설정
Promise.all(fetchDataPromises).then(() => {
vm.dataList = wordBooks;
});
})
.catch(function (error) {
console.log("dataList - error: ", error);
alert("단어장 목록 조회에 오류가 발생했습니다.");
});
},
// 단어 목록 생략 String 생성 메서드
generateWordsPreview(words) {
const maxLength = 20; // 최대 표시 길이 설정
const wordString = words.join(', ');
if (wordString.length > maxLength) {
return wordString.substring(0, maxLength) + '...';
} else {
return wordString;
}
},
// 단어장 NO 생성 메서드
createNo(index) {
return this.totalPosts - (this.currentPage * this.itemsPerPage + index);
},
// 페이지네이션 이동 메서드
goToPage(page) {
if (page < 0 || page >= this.totalPages) {
return;
}
this.currentPage = page;
this.dataSelectList();
},
// 페이지 이동 메서드
goToViewPage(page, wordbookId) {
this.$router.push({
name: page,
query: {
selectedBookId: this.selectedBookId,
selectedUnitId: this.selectedUnitId,
wdBookId: wordbookId
}
});
},
// 검색 메서드 추가
searchWordBooks() {
const vm = this;
let url = '';
let data = {};
if (this.searchType === 'text') {
// 지문으로 검색
url = '/wordbook/findByTextTitle.json';
data = {
unitId: vm.selectedUnitId,
textTitle: vm.searchQuery,
page: vm.currentPage + 1,
pageSize: vm.itemsPerPage
};
this.titleMessage = `[${vm.searchQuery}]의 지문 검색 결과`;
} else if (this.searchType === 'word') {
// 단어로 검색
url = '/wordbook/findByWord.json';
data = {
unitId: vm.selectedUnitId,
word: vm.searchQuery,
page: vm.currentPage + 1,
pageSize: vm.itemsPerPage
};
this.titleMessage = `[${vm.searchQuery}]의 단어 검색 결과`;
}
axios.post(url, data)
.then(function (response) {
console.log("searchWordBooks - response: ", response.data);
const wordBooks = response.data.wordBooks;
vm.totalPosts = response.data.totalWordBooks;
// 지문 제목 및 단어 목록 가져오기
const fetchDataPromises = wordBooks.map(wordBook => {
const textTitlePromise = axios.post("/text/selectOneText.json", {
textId: wordBook.textId
}).then(textResponse => {
wordBook.textTtl = textResponse.data[0].text_ttl;
}).catch(error => {
console.error(`${wordBook.textId}으로 지문 제목 가져오기 실패: `, error);
wordBook.textTtl = '제목값없음'; // 오류 시 기본값 설정
});
const wordsPromise = axios.post("/word/getWordsByBookId.json", {
wdBookId: wordBook.wdBookId
}).then(wordsResponse => {
const words = wordsResponse.data.map(word => word.wdNm);
wordBook.wordsPreview = vm.generateWordsPreview(words);
}).catch(error => {
console.error(`${wordBook.wdBookId}으로 단어 목록 가져오기 실패: `, error);
wordBook.wordsPreview = '단어값없음'; // 오류 시 기본값 설정
});
return Promise.all([textTitlePromise, wordsPromise]);
});
// 모든 데이터 가져오기 작업이 완료되면 dataList에 데이터 설정
Promise.all(fetchDataPromises).then(() => {
vm.dataList = wordBooks;
});
})
.catch(function (error) {
console.log("searchWordBooks - error: ", error);
alert("단어장 검색에 오류가 발생했습니다.");
});
},
},
watch: {
},
computed: {
totalPages() {
return Math.ceil(this.totalPosts / this.itemsPerPage);
},
paginationButtons() {
let start = Math.max(0, this.currentPage - 2);
let end = Math.min(start + 5, this.totalPages);
if (end - start < 5) {
start = Math.max(0, end - 5);
}
return Array.from({ length: end - start }, (_, i) => start + i + 1);
},
startIndex() {
return this.currentPage * this.itemsPerPage;
}
},
components:{
SvgIcon
},
mounted() {
console.log('Voca Book List Component mounted');
this.fetchBooks();
}
}
</script>