

240812 권민수 단어장 등록 후 단어 추가 기능 구현
@e101555503418bdf1ffa834ac03aa4325cabd989
--- client/views/pages/teacher/VocaInsert.vue
+++ client/views/pages/teacher/VocaInsert.vue
... | ... | @@ -26,29 +26,32 @@ |
26 | 26 |
<label for="" class="title2">단어 목록</label> |
27 | 27 |
<div class="flex-column" style="gap: 10px;"> |
28 | 28 |
<div class="flex align-center" style="gap: 10px;"> |
29 |
- <input type="text" class="data-wrap" placeholder="영어"> |
|
30 |
- <input type="text" class="data-wrap" placeholder="한글"> |
|
29 |
+ <input v-model="newWord.eng" type="text" class="data-wrap" placeholder="영어"> |
|
30 |
+ <input v-model="newWord.kor" type="text" class="data-wrap" placeholder="한글"> |
|
31 | 31 |
<button type="button" @click="addWord"> |
32 | 32 |
<img src="../../../resources/img/btn39_120t_normal.png" alt=""> |
33 |
- |
|
34 | 33 |
</button> |
35 | 34 |
</div> |
36 | 35 |
|
37 |
- <!-- 여기에 단어장에 소속될 단어들 태그 형태 리스트 표시할 예정 --> |
|
36 |
+ <!-- 여기에 단어장에 소속될 단어들 태그 형태 리스트 --> |
|
37 |
+ <div v-for="(word, index) in words" :key="index" class="word-item flex align-center" style="gap: 10px;"> |
|
38 |
+ <span>{{ word.eng }} / {{ word.kor }}</span> |
|
39 |
+ <button type="button" @click="removeWord(index)">삭제</button> |
|
40 |
+ </div> |
|
38 | 41 |
|
39 | 42 |
</div> |
40 | 43 |
|
41 | 44 |
</div> |
42 | 45 |
</div> |
43 | 46 |
<div class="flex justify-between mt50"> |
44 |
- <button type="button" title="글쓰기" class="new-btn" @click="goToPage('VocaList')"> |
|
47 |
+ <button type="button" title="목록" class="new-btn" @click="goToPage('VocaList')"> |
|
45 | 48 |
목록 |
46 | 49 |
</button> |
47 | 50 |
<div class="flex"> |
48 |
- <button type="button" title="글쓰기" class="new-btn mr10"> |
|
51 |
+ <button type="button" title="취소" class="new-btn mr10" @click="cancelAction"> |
|
49 | 52 |
취소 |
50 | 53 |
</button> |
51 |
- <button type="button" title="글쓰기" class="new-btn"> |
|
54 |
+ <button type="button" title="등록" class="new-btn" @click="registerWordBook"> |
|
52 | 55 |
등록 |
53 | 56 |
</button> |
54 | 57 |
</div> |
... | ... | @@ -71,7 +74,9 @@ |
71 | 74 |
selectedTextId: null, // 선택된 지문 ID |
72 | 75 |
selectedWdBookTypeId: '1', // 선택된 단어장 타입 ID |
73 | 76 |
newWord: { eng: '', kor: '' }, // 입력된 새 단어 |
74 |
- words: [] // 단어 목록 |
|
77 |
+ words: [], // 단어 목록 |
|
78 |
+ existingWords: [], // 기존 단어 목록 저장 |
|
79 |
+ userId: "2" |
|
75 | 80 |
} |
76 | 81 |
}, |
77 | 82 |
methods: { |
... | ... | @@ -124,9 +129,118 @@ |
124 | 129 |
}); |
125 | 130 |
}, |
126 | 131 |
|
132 |
+ addWord() { // 단어 추가 |
|
133 |
+ if (this.newWord.eng && this.newWord.kor) { |
|
134 |
+ this.words.push({ ...this.newWord }); |
|
135 |
+ this.newWord.eng = ''; |
|
136 |
+ this.newWord.kor = ''; |
|
137 |
+ } else { |
|
138 |
+ console.log("단어 입력이 비어 있음"); |
|
139 |
+ } |
|
140 |
+ }, |
|
141 |
+ |
|
142 |
+ removeWord(index) { // 단어 삭제 |
|
143 |
+ this.words.splice(index, 1); |
|
144 |
+ }, |
|
145 |
+ |
|
127 | 146 |
goToPage(page) { |
128 | 147 |
this.$router.push({ name: page }); |
129 | 148 |
}, |
149 |
+ |
|
150 |
+ cancelAction() { |
|
151 |
+ this.$router.go(-1); |
|
152 |
+ }, |
|
153 |
+ |
|
154 |
+ // 기존 단어 조회 메서드 |
|
155 |
+ fetchExistingWords(wdBookId) { |
|
156 |
+ return axios.post('/word/getWordsByBookId.json', { wdBookId: wdBookId }) |
|
157 |
+ .then(response => { |
|
158 |
+ return response.data.words || []; |
|
159 |
+ }) |
|
160 |
+ .catch(error => { |
|
161 |
+ console.error('기존 단어 목록 가져오기 실패:', error); |
|
162 |
+ return []; |
|
163 |
+ }); |
|
164 |
+ }, |
|
165 |
+ |
|
166 |
+ async registerWordBook() { |
|
167 |
+ const vm = this; |
|
168 |
+ |
|
169 |
+ try { |
|
170 |
+ const response = await axios.post('/wordbook/insert.json', { |
|
171 |
+ wdBookTypeId: vm.selectedWdBookTypeId, |
|
172 |
+ textId: vm.selectedTextId, |
|
173 |
+ userId: vm.userId, |
|
174 |
+ bookId: vm.selectedBookId, |
|
175 |
+ unitId: vm.selectedUnitId |
|
176 |
+ }); |
|
177 |
+ |
|
178 |
+ const wdBookId = response.data.wdBookId; |
|
179 |
+ |
|
180 |
+ // 기존 단어 목록 조회 |
|
181 |
+ const existingWords = await vm.fetchExistingWords(wdBookId); |
|
182 |
+ vm.existingWords = existingWords; |
|
183 |
+ |
|
184 |
+ const existingWordNames = existingWords.map(word => word.wdNm); |
|
185 |
+ const wordsToInsert = []; |
|
186 |
+ const wordsToUpdate = []; |
|
187 |
+ const wordsToDelete = []; |
|
188 |
+ |
|
189 |
+ // 새로 추가된 단어와 기존 단어 비교 |
|
190 |
+ vm.words.forEach(word => { |
|
191 |
+ if (existingWordNames.includes(word.eng)) { |
|
192 |
+ wordsToUpdate.push(word); |
|
193 |
+ } else { |
|
194 |
+ wordsToInsert.push(word); |
|
195 |
+ } |
|
196 |
+ }); |
|
197 |
+ |
|
198 |
+ // 삭제된 단어 목록 찾기 |
|
199 |
+ existingWords.forEach(word => { |
|
200 |
+ if (!vm.words.find(newWord => newWord.eng === word.wdNm)) { |
|
201 |
+ wordsToDelete.push(word); |
|
202 |
+ } |
|
203 |
+ }); |
|
204 |
+ |
|
205 |
+ // 단어 삽입 |
|
206 |
+ for (const word of wordsToInsert) { |
|
207 |
+ await axios.post('/word/insert.json', { |
|
208 |
+ wdBookId: wdBookId, |
|
209 |
+ wdNm: word.eng, |
|
210 |
+ wdMnng: word.kor, |
|
211 |
+ fileMngId: '1' |
|
212 |
+ }); |
|
213 |
+ } |
|
214 |
+ |
|
215 |
+ // 단어 업데이트 |
|
216 |
+ for (const word of wordsToUpdate) { |
|
217 |
+ await axios.post('/word/update.json', { |
|
218 |
+ wdBookId: wdBookId, |
|
219 |
+ wdNm: word.eng, |
|
220 |
+ wdMnng: word.kor, |
|
221 |
+ fileMngId: '1' |
|
222 |
+ }); |
|
223 |
+ } |
|
224 |
+ |
|
225 |
+ // 단어 삭제 |
|
226 |
+ for (const word of wordsToDelete) { |
|
227 |
+ const wordToDelete = existingWords.find(existingWord => existingWord.wdNm === word.wdNm); |
|
228 |
+ if (wordToDelete) { |
|
229 |
+ await axios.post('/word/delete.json', { |
|
230 |
+ wdBookId: wdBookId, |
|
231 |
+ wdId: wordToDelete.wdId |
|
232 |
+ }); |
|
233 |
+ } |
|
234 |
+ } |
|
235 |
+ |
|
236 |
+ alert('단어장이 성공적으로 등록되었습니다.'); |
|
237 |
+ vm.goToPage('VocaList'); |
|
238 |
+ |
|
239 |
+ } catch (error) { |
|
240 |
+ console.error('단어장 등록 중 오류 발생:', error); |
|
241 |
+ alert('단어장 등록에 실패했습니다.'); |
|
242 |
+ } |
|
243 |
+ } |
|
130 | 244 |
|
131 | 245 |
}, |
132 | 246 |
watch: { |
... | ... | @@ -148,10 +262,10 @@ |
148 | 262 |
SvgIcon |
149 | 263 |
}, |
150 | 264 |
mounted() { |
265 |
+ console.log('VocaInsert mounted'); |
|
151 | 266 |
// 쿼리 전달 받기 |
152 | 267 |
this.selectedBookId = this.$route.query.selectedBookId || null; |
153 | 268 |
this.selectedUnitId = this.$route.query.selectedUnitId || null; |
154 |
- console.log('VocaInsert mounted'); |
|
155 | 269 |
this.fetchTexts(); |
156 | 270 |
this.fetchBookAndUnitNames(); |
157 | 271 |
} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?