
--- client/views/pages/main/Chapter/Chapter2.vue
+++ client/views/pages/main/Chapter/Chapter2.vue
... | ... | @@ -1,6 +1,6 @@ |
1 | 1 |
<template> |
2 | 2 |
<div id="Chapter1_1" class="content-wrap"> |
3 |
- <div style="margin: 30px 0px 50px"> |
|
3 |
+ <div style="margin: 30px 0px 50px; width: 20%"> |
|
4 | 4 |
<router-link to="/MyPlan.page"> |
5 | 5 |
<div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
6 | 6 |
</router-link> |
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 |
<div class="flex justify-between align-center"> |
13 | 13 |
<div class="pre-btn" @click="goToPage('Chapter1_3')"><img src="../../../../resources/img/left.png" alt=""></div> |
14 | 14 |
<div class="content title-box"> |
15 |
- <p class="title mt25 title-bg">단어로 공부하는 영어</p> |
|
15 |
+ <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p> |
|
16 | 16 |
<div class="flex align-center mb30"> |
17 | 17 |
<p class="subtitle2 mr20"></p> |
18 | 18 |
<!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
--- client/views/pages/main/Chapter/Chapter2_2.vue
+++ client/views/pages/main/Chapter/Chapter2_2.vue
... | ... | @@ -1,10 +1,10 @@ |
1 | 1 |
<template> |
2 | 2 |
<div id="Chapter2_2" class="content-wrap"> |
3 |
- <div style="margin: 30px 0px 50px"> |
|
4 |
- <router-link to="/MyPlan.page"> |
|
5 |
- <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
- </router-link> |
|
7 |
- </div> |
|
3 |
+ <div style="margin: 30px 0px 50px; width: 20%"> |
|
4 |
+ <router-link to="/MyPlan.page"> |
|
5 |
+ <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
+ </router-link> |
|
7 |
+ </div> |
|
8 | 8 |
<div class="title-box mb25 flex align-center mt40"> |
9 | 9 |
<span class="title mr40">1. Hello WORLD</span> |
10 | 10 |
<span class="subtitle">my name is dd</span> |
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 |
<div class="pre-btn" @click="goToPage('Chapter2_3')"><img src="../../../../resources/img/left.png" alt=""> |
14 | 14 |
</div> |
15 | 15 |
<div class="content title-box"> |
16 |
- <p class="title mt25 title-bg">단어로 공부하는 영어</p> |
|
16 |
+ <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p> |
|
17 | 17 |
<div class="flex align-center mb30"> |
18 | 18 |
<p class="subtitle2 mr20">카드를 뒤집어 보세요.</p> |
19 | 19 |
<!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
--- client/views/pages/main/Chapter/Chapter2_3.vue
+++ client/views/pages/main/Chapter/Chapter2_3.vue
... | ... | @@ -1,6 +1,6 @@ |
1 | 1 |
<template> |
2 | 2 |
<div id="Chapter2_2" class="content-wrap"> |
3 |
- <div style="margin: 30px 0px 50px"> |
|
3 |
+ <div style="margin: 30px 0px 50px; width: 20%"> |
|
4 | 4 |
<router-link to="/MyPlan.page"> |
5 | 5 |
<div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
6 | 6 |
</router-link> |
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 |
<div class="pre-btn" @click="goToPage('Chapter2')"><img src="../../../../resources/img/left.png" alt=""></div> |
14 | 14 |
<div class="content title-box"> |
15 | 15 |
<p class="subtitle2 "></p> |
16 |
- <p class="title mt25 title-bg">단어로 공부하는 영어</p> |
|
16 |
+ <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p> |
|
17 | 17 |
<div class="flex align-center mb30"> |
18 | 18 |
<p class="subtitle2 mr20">다음을 듣고 따라 말하세요.</p> |
19 | 19 |
<!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
... | ... | @@ -33,30 +33,23 @@ |
33 | 33 |
|
34 | 34 |
<div class="flex justify-center"> |
35 | 35 |
<div class="readGroup"> |
36 |
- <section> |
|
37 |
- <div class="imgGroup flex justify-center"> |
|
38 |
- <!-- 녹음 버튼 --> |
|
39 |
- <div :class="['mic-btn', { notRecording: !isRecording }]" @click="toggleRecording"> |
|
40 |
- <img src="../../../../resources/img/btn11_s.png" alt="" /> |
|
41 |
- </div> |
|
42 |
- </div> |
|
43 |
- <article> |
|
44 |
- <p class="speakText mb25"> |
|
45 |
- <span v-if="transcription === null" |
|
46 |
- >위의 버튼을 누른 후 오늘 배운 단어를 말해보세요!</span |
|
47 |
- > |
|
48 |
- <span v-else-if="!transcription || transcription.trim() === ''" |
|
49 |
- >다시 말해보세요!</span |
|
50 |
- > |
|
51 |
- <span v-else>{{ transcription }}</span> |
|
52 |
- </p> |
|
53 |
- <p class="read-ai"> |
|
54 |
- <img style="margin-top: -5px" src="../../../../resources/img/img43_s.png" alt="" /> |
|
55 |
- </p> |
|
56 |
- </article> |
|
57 |
- </section> |
|
36 |
+ <section> |
|
37 |
+ <div class="imgGroup flex justify-center"> |
|
38 |
+ <!-- 녹음 버튼 --> |
|
39 |
+ <div :class="['mic-btn', { notRecording: !isRecording }]" @click="toggleRecording"> |
|
40 |
+ <img src="../../../../resources/img/btn11_s.png" alt="" /> |
|
41 |
+ </div> |
|
42 |
+ </div> |
|
43 |
+ <article> |
|
44 |
+ <p class="speakText mb25"> |
|
45 |
+ <span v-if="transcription === null">위의 버튼을 누른 후 단어를 말해보세요!</span> |
|
46 |
+ <span v-else-if="transcription === nowWord">다시 말해보세요!</span> |
|
47 |
+ <span v-else>정답입니다! 잘했어요</span> |
|
48 |
+ </p> |
|
49 |
+ </article> |
|
50 |
+ </section> |
|
58 | 51 |
</div> |
59 |
- </div> |
|
52 |
+ </div> |
|
60 | 53 |
<div class="flex justify-center"> |
61 | 54 |
<div class="btnGroup mt50 flex justify-between"> |
62 | 55 |
<button class="popTxt" v-for="(item, index) in items" :key="index" @click="updateContent(index)" |
... | ... | @@ -75,17 +68,17 @@ |
75 | 68 |
</template> |
76 | 69 |
|
77 | 70 |
<script> |
78 |
-import axios from 'axios'; |
|
71 |
+import axios from 'axios'; |
|
79 | 72 |
import { mdiStop } from '@mdi/js'; |
80 | 73 |
export default { |
81 | 74 |
data() { |
82 | 75 |
return { |
83 | 76 |
items: [ |
84 |
- {imgSrc1: 'client/resources/img/img53_6_35s.png', imgSrc2: 'client/resources/img/img53_1_35s.png', con: { imgSrc: 'client/resources/img/img54_s.png', titleEm: 'c', title: 'loud', boxText: '명', subtitle: '구름' } }, |
|
85 |
- {imgSrc1: 'client/resources/img/img53_7_35s.png', imgSrc2: 'client/resources/img/img53_2_35s.png', con: { imgSrc: 'client/resources/img/img40_s.png', titleEm: 'a', title: 'pple', boxText: '명', subtitle: '사과' } }, |
|
86 |
- {imgSrc1: 'client/resources/img/img53_8_35s.png', imgSrc2: 'client/resources/img/img53_3_35s.png', con: { imgSrc: 'client/resources/img/31img40_s.png', titleEm: 'l', title: 'og', boxText: '명', subtitle: '통나무' } }, |
|
87 |
- {imgSrc1: 'client/resources/img/img53_9_35s.png', imgSrc2: 'client/resources/img/img53_4_35s.png', con: { imgSrc: 'client/resources/img/img41_s.png', titleEm: 'g', title: 'uitar', boxText: '명', subtitle: '기타' } }, |
|
88 |
- {imgSrc1: 'client/resources/img/img53_10_35s.png', imgSrc2: 'client/resources/img/img53_5_35s.png', con: { imgSrc: 'client/resources/img/img76_41s.png', titleEm: 'w', title: 'ater melon', boxText: '명', subtitle: '수박' } } |
|
77 |
+ { imgSrc1: 'client/resources/img/img53_6_35s.png', imgSrc2: 'client/resources/img/img53_1_35s.png', con: { imgSrc: 'client/resources/img/img54_s.png', titleEm: 'c', title: 'loud', boxText: '명', subtitle: '구름' } }, |
|
78 |
+ { imgSrc1: 'client/resources/img/img53_7_35s.png', imgSrc2: 'client/resources/img/img53_2_35s.png', con: { imgSrc: 'client/resources/img/img40_s.png', titleEm: 'a', title: 'pple', boxText: '명', subtitle: '사과' } }, |
|
79 |
+ { imgSrc1: 'client/resources/img/img53_8_35s.png', imgSrc2: 'client/resources/img/img53_3_35s.png', con: { imgSrc: 'client/resources/img/31img40_s.png', titleEm: 'l', title: 'og', boxText: '명', subtitle: '통나무' } }, |
|
80 |
+ { imgSrc1: 'client/resources/img/img53_9_35s.png', imgSrc2: 'client/resources/img/img53_4_35s.png', con: { imgSrc: 'client/resources/img/img41_s.png', titleEm: 'g', title: 'uitar', boxText: '명', subtitle: '기타' } }, |
|
81 |
+ { imgSrc1: 'client/resources/img/img53_10_35s.png', imgSrc2: 'client/resources/img/img53_5_35s.png', con: { imgSrc: 'client/resources/img/img76_41s.png', titleEm: 'w', title: 'ater melon', boxText: '명', subtitle: '수박' } } |
|
89 | 82 |
], |
90 | 83 |
currentCon: { imgSrc: 'client/resources/img/img54_s.png', titleEm: 'c', title: 'loud', boxText: '명', subtitle: '구름' }, |
91 | 84 |
selectedIndex: 0, |
... | ... | @@ -101,6 +94,7 @@ |
101 | 94 |
stream: null, // MediaStream 객체 |
102 | 95 |
|
103 | 96 |
path: mdiStop, |
97 |
+ nowWord: "cloud", |
|
104 | 98 |
}; |
105 | 99 |
}, |
106 | 100 |
methods: { |
... | ... | @@ -127,75 +121,86 @@ |
127 | 121 |
}, |
128 | 122 |
// 녹음 시작/중지 토글 |
129 | 123 |
async toggleRecording() { |
130 |
- if (this.isRecording) { |
|
131 |
- console.log('녹음 그만!'); |
|
132 |
- this.stopRecording(); // 녹음 중이면 중지 |
|
133 |
- } else { |
|
134 |
- console.log('녹음 시작!'); |
|
135 |
- await this.startRecording(); // 녹음 중이 아니면 녹음 시작 |
|
136 |
- } |
|
124 |
+ if (this.isRecording) { |
|
125 |
+ console.log('녹음 그만!'); |
|
126 |
+ this.stopRecording(); // 녹음 중이면 중지 |
|
127 |
+ } else { |
|
128 |
+ console.log('녹음 시작!'); |
|
129 |
+ await this.startRecording(); // 녹음 중이 아니면 녹음 시작 |
|
130 |
+ } |
|
137 | 131 |
}, |
138 | 132 |
// 녹음 시작 |
139 | 133 |
async startRecording() { |
140 |
- this.audioChunks = []; // 오디오 초기화 |
|
141 |
- this.stream = await navigator.mediaDevices.getUserMedia({ audio: true }); |
|
142 |
- this.mediaRecorder = new MediaRecorder(this.stream); |
|
143 |
- this.mediaRecorder.ondataavailable = (event) => { |
|
144 |
- this.audioChunks.push(event.data); // 녹음 데이터 저장 |
|
145 |
- }; |
|
146 |
- this.mediaRecorder.onstop = () => { |
|
147 |
- this.audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' }); |
|
134 |
+ this.audioChunks = []; // 오디오 초기화 |
|
135 |
+ this.stream = await navigator.mediaDevices.getUserMedia({ audio: true }); |
|
136 |
+ this.mediaRecorder = new MediaRecorder(this.stream); |
|
137 |
+ this.mediaRecorder.ondataavailable = (event) => { |
|
138 |
+ this.audioChunks.push(event.data); // 녹음 데이터 저장 |
|
139 |
+ }; |
|
140 |
+ this.mediaRecorder.onstop = () => { |
|
141 |
+ this.audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' }); |
|
148 | 142 |
|
149 |
- /******************************/ |
|
150 |
- // this.audioURL = URL.createObjectURL(this.audioBlob); // 오디오 URL 생성 |
|
151 |
- // console.log('Audio URL:', this.audioURL); |
|
152 |
- /******************************/ |
|
143 |
+ /******************************/ |
|
144 |
+ // this.audioURL = URL.createObjectURL(this.audioBlob); // 오디오 URL 생성 |
|
145 |
+ // console.log('Audio URL:', this.audioURL); |
|
146 |
+ /******************************/ |
|
153 | 147 |
|
154 |
- console.log('Recorded Audio Blob:', this.audioBlob); // 콘솔에 Blob 확인 |
|
155 |
- this.sendAudioToServer(); // 서버로 오디오 전송 |
|
156 |
- }; |
|
157 |
- this.mediaRecorder.start(); // 녹음 시작 |
|
158 |
- this.isRecording = true; // 녹음 상태 변경 |
|
148 |
+ console.log('Recorded Audio Blob:', this.audioBlob); // 콘솔에 Blob 확인 |
|
149 |
+ this.sendAudioToServer(); // 서버로 오디오 전송 |
|
150 |
+ }; |
|
151 |
+ this.mediaRecorder.start(); // 녹음 시작 |
|
152 |
+ this.isRecording = true; // 녹음 상태 변경 |
|
159 | 153 |
}, |
160 | 154 |
|
161 | 155 |
// 녹음 중지 |
162 | 156 |
stopRecording() { |
163 |
- this.mediaRecorder.stop(); // 녹음 중단 |
|
157 |
+ this.mediaRecorder.stop(); // 녹음 중단 |
|
164 | 158 |
|
165 |
- if (this.stream) { |
|
166 |
- this.stream.getTracks().forEach((track) => track.stop()); // 스트림의 모든 트랙 중지 |
|
167 |
- } |
|
159 |
+ if (this.stream) { |
|
160 |
+ this.stream.getTracks().forEach((track) => track.stop()); // 스트림의 모든 트랙 중지 |
|
161 |
+ } |
|
168 | 162 |
|
169 |
- this.isRecording = false; // 녹음 상태 변경 |
|
163 |
+ this.isRecording = false; // 녹음 상태 변경 |
|
170 | 164 |
}, |
171 | 165 |
|
172 | 166 |
// 오디오 전송 |
173 | 167 |
async sendAudioToServer() { |
174 |
- const formData = new FormData(); |
|
175 |
- formData.append('file', this.audioBlob, 'recording.wav'); |
|
176 |
- try { |
|
177 |
- const resposne = await axios.post('/api/speechToText.json', formData, { |
|
178 |
- headers: { |
|
179 |
- 'Content-Type': 'multipart/form-data', |
|
180 |
- }, |
|
181 |
- }); |
|
182 |
- this.transcription = resposne.data; |
|
183 |
- console.log(`받은 데이터 : ${this.transcription}`); |
|
184 |
- } catch (error) { |
|
185 |
- console.log('파일 전송 실패 : ', error); |
|
186 |
- } |
|
168 |
+ const formData = new FormData(); |
|
169 |
+ formData.append('file', this.audioBlob, 'recording.wav'); |
|
170 |
+ try { |
|
171 |
+ const resposne = await axios.post('/api/speechToText.json', formData, { |
|
172 |
+ headers: { |
|
173 |
+ 'Content-Type': 'multipart/form-data', |
|
174 |
+ }, |
|
175 |
+ }); |
|
176 |
+ this.transcription = resposne.data; |
|
177 |
+ console.log(`받은 데이터 : ${this.transcription}`); |
|
178 |
+ } catch (error) { |
|
179 |
+ console.log('파일 전송 실패 : ', error); |
|
180 |
+ } |
|
187 | 181 |
}, |
182 |
+ }, |
|
183 |
+ watch: { |
|
184 |
+ currentCon: { |
|
185 |
+ handler(newValue) { |
|
186 |
+ // Update nowWord when currentCon changes |
|
187 |
+ this.nowWord = newValue.titleEm + newValue.title; |
|
188 |
+ console.log('지금단어: ',this.nowWord) |
|
189 |
+ console.log('녹음결과: ',this.transcription) |
|
190 |
+ }, |
|
191 |
+ deep: true // Watch for deep changes in currentCon |
|
192 |
+ } |
|
188 | 193 |
}, |
189 | 194 |
beforeDestroy() { |
190 | 195 |
if (this.intervalId) { |
191 | 196 |
clearInterval(this.intervalId); |
192 | 197 |
} |
193 |
- } |
|
198 |
+ }, |
|
194 | 199 |
} |
195 | 200 |
</script> |
196 | 201 |
|
197 | 202 |
<style scoped> |
198 |
-.popTxt img{ |
|
203 |
+.popTxt img { |
|
199 | 204 |
position: absolute; |
200 | 205 |
top: 0; |
201 | 206 |
left: 0; |
--- client/views/pages/main/Chapter/Chapter2_4.vue
+++ client/views/pages/main/Chapter/Chapter2_4.vue
... | ... | @@ -1,10 +1,10 @@ |
1 | 1 |
<template> |
2 | 2 |
<div id="Chapter2_2" class="content-wrap"> |
3 |
- <div style="margin: 30px 0px 50px"> |
|
4 |
- <router-link to="/MyPlan.page"> |
|
5 |
- <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
- </router-link> |
|
7 |
- </div> |
|
3 |
+ <div style="margin: 30px 0px 50px; width: 20%"> |
|
4 |
+ <router-link to="/MyPlan.page"> |
|
5 |
+ <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
+ </router-link> |
|
7 |
+ </div> |
|
8 | 8 |
<div class="title-box mb25 flex align-center mt40"> |
9 | 9 |
<span class="title mr40">1. Hello WORLD</span> |
10 | 10 |
<span class="subtitle">my name is dd</span> |
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 |
<div class="pre-btn" @click="goToPage('Chapter2_9')"><img src="../../../../resources/img/left.png" alt=""> |
14 | 14 |
</div> |
15 | 15 |
<div class="content title-box"> |
16 |
- <p class="title mt25 title-bg">step2</p> |
|
16 |
+ <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p> |
|
17 | 17 |
<div class="flex align-center mb30"> |
18 | 18 |
<p class="subtitle2 mr20">다음을 듣고 맞는 단어를 선택하세요.</p> |
19 | 19 |
<!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
--- client/views/pages/main/Chapter/Chapter2_9.vue
+++ client/views/pages/main/Chapter/Chapter2_9.vue
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 |
<div class="flex justify-between align-center"> |
13 | 13 |
<div class="pre-btn" @click="goToPage('Chapter2_2')"><img src="../../../../resources/img/left.png" alt=""></div> |
14 | 14 |
<div class="content title-box"> |
15 |
- <p class="title mt25 title-bg">step2</p> |
|
15 |
+ <p class="title mt25 title-bg">STEP 2 - 단어로 공부하는 영어</p> |
|
16 | 16 |
<div class="flex align-center mb30"> |
17 | 17 |
<p class="subtitle2 mr20">앗! 잉크가 쏟아졌어! 지우개로 잉크를 지워줘!</p> |
18 | 18 |
</div> |
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?