jichoi / lms_front star
정다정 2024-09-11
240911 정다정 대화지문 단어,문장 설명 추가
@9edc4aa35dec4cff692e35a82090ee4673164984
client/views/pages/main/Chapter/Chapter1_1.vue
--- client/views/pages/main/Chapter/Chapter1_1.vue
+++ client/views/pages/main/Chapter/Chapter1_1.vue
@@ -1,88 +1,373 @@
 <template>
-  <div id="Chapter1_1" class="content-wrap">
-    <div style="margin: 30px 0px 50px; width: 20%">
-      <router-link to="/MyPlan.page">
-        <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div>
-      </router-link>
-    </div>
-    <div class="title-box mb25 flex align-center mt40">
-      <span class="title mr40">1. Hello WORLD</span>
-      <span class="subtitle">my name is dd</span>
-    </div>
-    <div class="flex justify-between align-center">
-      <div class="pre-btn" @click="goToPage('Chapter1')"><img src="../../../../resources/img/left.png" alt=""></div>
-      <div class="content title-box">
-        <p class="title mt25 title-bg">step1. Hello WORLD</p>
-
-        <div class="imgGroup">
-          <img src="../../../../resources/img/img35_s.png" data-num="1">
-
+    <div id="Chapter1_1" class="content-wrap">
+        <div style="margin: 30px 0px 50px; width: 20%">
+            <router-link to="/MyPlan.page">
+                <div class="logo mb25">
+                    <img src="../../../../resources/img/logo2.png" alt="" />
+                </div>
+            </router-link>
         </div>
-        <div class="textareaGroup">
-          <textarea>Bike lanes are important because they ket, bike riders and all other people safe. Before bike lanes, people rode on the sidewalk or in the same lanes as the cars on the street. Riding a bike on the sidewalk can cause you to crash into someone who is walking by. And riding a bike in the same lanes as cars can be unsafe, too, Bikes move more slowly than cars, so people driving behind bikes will try to go around them. These cars could hit the bike riders or other cars. </textarea>
-          <div id="popup" class="popup">
-            <div class="imgGroup mb10">
-              <img src="../../../../resources/img/img36_s.png" data-num="1">
+        <div class="title-box mb25 flex align-center mt40" style="justify-content: space-between">
+            <div>
+                <span class="title mr40">1. Hello WORLD</span>
+                <span class="subtitle">my name is dd</span>
             </div>
-              <h3>sidewalk</h3>
-             <div class="flex align-center  justify-center mt10">
-                <p class="yellow-box">명</p>
-                <span class="title1">보도</span>
-             </div>
-          </div>
+            <div class="flex">
+                <TextToImage />
+                <button class="completeBtn" @click="complete">학습 종료</button>
+            </div>
         </div>
-      </div>
-      <div class="next-btn" @click="goToPage('Chapter1_2')"><img src="../../../../resources/img/right.png" alt=""></div>
+        <div class="flex justify-between align-center">
+            <div class="pre-btn" style="visibility: hidden" @click="goToPage('Chapter1_1')">
+                <img src="../../../../resources/img/left.png" alt="" />
+            </div>
+            <div class="content title-box">
+                <p class="title mt25 title-bg">step1. Hello WORLD</p>
+                <div class="flex align-center ml50 mb15" style="margin-top: -30px; gap: 10px">
+                    <h4>설명에 맞춰 영어 문장의 의미를 이해해봅시다. 대화문을 클릭해보세요!</h4>
+                    <div class="listen-btn">
+                        <img src="../../../../resources/img/btn10_s.png" alt="" @click="playAudio" />
+                        <audio
+                            id="audio-player"
+                            src="client/resources/audio/passage/passage_explanation.mp3"
+                            preload="auto"
+                        ></audio>
+                    </div>
+                </div>
+                <div class="flex justify-center" style="gap: 50px">
+                    <div class="readGroup">
+                        <div>
+                            <div class="textbox">
+                                <article
+                                    v-for="(line, index) in combinedLines"
+                                    :key="index"
+                                    :class="['flex', 'align-center', 'mb10', { 'justify-end': index % 2 !== 0 }]"
+                                >
+                                    <div v-if="index % 2 === 0" class="icon mr40">
+                                        <img src="../../../../resources/img/img37_s.png" alt="" />
+                                        <p class="name">{{ speakerA_name }}</p>
+                                    </div>
+                                    <p
+                                        v-if="index % 2 === 0"
+                                        class="read"
+                                        @click="handleSelectLine(line)"
+                                        :style="getStyle(line)"
+                                    >
+                                        {{ line }}
+                                    </p>
+
+                                    <p
+                                        v-if="index % 2 !== 0"
+                                        class="read mr40"
+                                        @click="handleSelectLine(line)"
+                                        :style="getStyle(line)"
+                                    >
+                                        {{ line }}
+                                    </p>
+                                    <div v-if="index % 2 !== 0" class="icon">
+                                        <img src="../../../../resources/img/img37_s.png" alt="" />
+                                        <p class="name">{{ speakerB_name }}</p>
+                                    </div>
+                                </article>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="button-box">
+                        <button class="word" @click="wordQuestion">단어 설명</button>
+                        <button class="passage" @click="passageQuestion">문장 설명</button>
+                    </div>
+                </div>
+            </div>
+            <div class="next-btn" @click="goToNextPage">
+                <img src="../../../../resources/img/right.png" alt="" />
+            </div>
+        </div>
+        <div class="popup-wrap" v-if="popupOpen">
+            <div class="popup-container flex-column">
+                <div class="popup-header flex align-center">
+                    <p>선생님의 한 마디</p>
+                    <img
+                        class="look-btn"
+                        @click="handlePopupClose"
+                        src="../../../../resources/img/btn25_93t_normal.png"
+                        alt=""
+                    />
+                </div>
+                <div>
+                    <p class="popup-content mt30" v-html="formattedExplanation"></p>
+                </div>
+            </div>
+        </div>
     </div>
-  </div>
 </template>
 
 <script>
+import TextToImage from '../../../component/TextToImage.vue';
+import axios from 'axios';
 export default {
-  data() {
-    return {
-    }
-  },
-  methods: {
-    goToPage(page) {
-      this.$router.push({ name: page });
-    }
-  },
-  watch: {
+    data() {
+        return {
+            text_data: null, // 받아온 지문 정보
+            speakerA_name: null,
+            speakerB_name: null,
+            speakerA: [],
+            speakerB: [],
 
-  },
-  computed: {
+            seq: this.$store.getters.seqNum,
+            selectedLine: null, // 선택한 지문
+            explanation_response: null, // 설명 응답
 
-  },
-  components: {
-  },
-  mounted() {
-    const textArea = this.$refs.textArea;
-      const popup = this.$refs.popup;
+            popupOpen: false,
+        };
+    },
+    methods: {
+        complete() {
+            const { unit_id, book_id } = this.$route.query;
+            this.$router.push({
+                name: 'Dashboard',
+                query: { value: this.seq, unit_id, book_id },
+            });
+        },
+        goToPage(page) {
+            this.$router.push({ name: page });
+        },
+        goToNextPage() {
+            alert('지문 학습 완료!');
+            this.complete();
+        },
+        // 대화 지문 API
+        async fetchText() {
+            axios({
+                url: '/text/selectOneText.json',
+                method: 'post',
+                headers: {
+                    'Content-Type': 'application/json; charset=UTF-8',
+                },
+                data: {
+                    textId: this.textId,
+                },
+            })
+                .then((response) => {
+                    this.text_data = response.data[0].text_cnt;
+                    this.splitConversation();
+                })
+                .catch((err) => {
+                    console.log('지문 에러 : ', err);
+                });
+        },
+        // 대화 지문 split
+        splitConversation() {
+            const lines = this.text_data.split('/');
+            const speakers = {};
 
-      textArea.addEventListener('mousemove', (event) => {
-         const text = textArea.value;
-         const words = text.split(' ');
-         const selectionStart = textArea.selectionStart;
-         const selectionEnd = textArea.selectionEnd;
+            lines.forEach((line) => {
+                const [speaker, message] = line.trim().split(':');
 
-         if (selectionStart !== selectionEnd) {
-            const selectedText = text.substring(selectionStart, selectionEnd);
-            const rect = textArea.getBoundingClientRect();
-            popup.style.left = `${event.clientX}px`;
-            popup.style.top = `${event.clientY + window.scrollY}px`;
-            popup.innerHTML = `You selected: ${selectedText}`;
-            popup.style.display = 'block';
-         } else {
-            popup.style.display = 'none';
-         }
-      });
+                if (!speakers.speakerA_name && !speakers.speakerB_name) {
+                    // 첫 번째 발화자를 speakerA_name으로 설정
+                    speakers.speakerA_name = speaker.trim();
+                    this.speakerA.push(message.trim());
+                } else if (
+                    speakers.speakerA_name &&
+                    !speakers.speakerB_name &&
+                    speakers.speakerA_name !== speaker.trim()
+                ) {
+                    // 두 번째 발화자를 speakerB_name으로 설정
+                    speakers.speakerB_name = speaker.trim();
+                    this.speakerB.push(message.trim());
+                } else if (speaker.trim() === speakers.speakerA_name) {
+                    // speakerA_name에 내용 추가
+                    this.speakerA.push(message.trim());
+                } else if (speaker.trim() === speakers.speakerB_name) {
+                    // speakerB_name에 내용 추가
+                    this.speakerB.push(message.trim());
+                }
+            });
 
-      document.addEventListener('click', (event) => {
-         if (!textArea.contains(event.target) && !popup.contains(event.target)) {
-            popup.style.display = 'none';
-         }
-      });
-  }
+            this.speakerA_name = speakers.speakerA_name;
+            this.speakerB_name = speakers.speakerB_name;
+        },
+
+        playAudio() {
+            const audio = document.getElementById('audio-player');
+            audio.play();
+            console.log('playing');
+        },
+
+        // 검색할 지문 선택
+        handleSelectLine(line) {
+            this.selectedLine = line;
+            // console.log('선택된 지문 : ', this.selectedLine);
+        },
+
+        getStyle(line) {
+            return {
+                backgroundColor: this.selectedLine === line ? '#ffc980' : '',
+                fontSize: this.selectedLine === line ? '40px' : '',
+                boxShadow: this.selectedLine === line ? 'rgba(0, 0, 0, 0.24) 0px 3px 8px' : '',
+                fontWeight: this.selectedLine === line ? 'bold' : '',
+                cursour: 'pointer',
+            };
+        },
+
+        // 단어 설명
+        wordQuestion() {
+            // console.log('line : ', this.selectedLine);
+            if (this.selectedLine === null) {
+                alert('궁금한 대화문을 선택해주세요');
+                return;
+            }
+            axios({
+                url: 'http://165.229.169.32:35716/word_question',
+                method: 'post',
+                headers: {
+                    'Content-Type': 'application/json; charset=UTF-8',
+                },
+                data: {
+                    word: this.selectedLine,
+                },
+            })
+                .then((response) => {
+                    // console.log('word 지문 응답 : ', response.data.explanation);
+                    this.explanation_response = response.data.explanation;
+                    this.handlePopupOpen();
+                })
+                .catch((err) => {
+                    console.log('word 지문 에러 : ', err);
+                });
+        },
+
+        // 지문 설명
+        passageQuestion() {
+            // console.log('line : ', this.selectedLine);
+            if (this.selectedLine === null) {
+                alert('궁금한 대화문을 선택해주세요');
+                return;
+            }
+            axios({
+                url: 'http://165.229.169.32:35716/passage_question',
+                method: 'post',
+                headers: {
+                    'Content-Type': 'application/json; charset=UTF-8',
+                },
+                data: {
+                    passage: this.selectedLine,
+                },
+            })
+                .then((response) => {
+                    // console.log('passage 지문 응답 : ', response.data.explanation);
+                    this.explanation_response = response.data.explanation;
+                    this.handlePopupOpen();
+                })
+                .catch((err) => {
+                    console.log('passage 지문 에러 : ', err);
+                });
+        },
+
+        /* 팝업 */
+        handlePopupOpen() {
+            this.popupOpen = true;
+        },
+
+        handlePopupClose() {
+            this.popupOpen = false;
+            this.explanation_response = null;
+            this.selectedLine = null;
+        },
+    },
+    watch: {},
+    computed: {
+        textId() {
+            //console.log("지문 화면 아이디 : ", this.$store.getters.getTextId);
+            return this.$store.getters.getTextId;
+        },
+        combinedLines() {
+            const maxLength = Math.max(this.speakerA.length, this.speakerB.length);
+            const lines = [];
+
+            for (let i = 0; i < maxLength; i++) {
+                if (i < this.speakerA.length) {
+                    lines.push(this.speakerA[i]);
+                }
+                if (i < this.speakerB.length) {
+                    lines.push(this.speakerB[i]);
+                }
+            }
+            return lines;
+        },
+        // 지문 포맷팅
+        formattedExplanation() {
+            return this.explanation_response.replace(/\n/g, '<br>').replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
+        },
+    },
+    components: {
+        TextToImage: TextToImage,
+    },
+    mounted() {
+        this.fetchText();
+    },
+};
+</script>
+
+<style scoped>
+.completeBtn {
+    margin-right: 100px;
+    background-color: #ffba08;
+    padding: 10px 30px;
+    border-radius: 10px;
+    font-size: 28px;
+    font-family: 'ONEMobilePOPOTF';
 }
-</script>
(No newline at end of file)
+
+.button-box {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: space-evenly;
+}
+
+.button-box button {
+    font-family: 'ONEMobilePOPOTF';
+    font-size: 25px;
+    color: #fff;
+    padding: 20px 70px;
+    border-radius: 15px;
+    box-shadow: rgba(136, 165, 191, 0.48) 6px 2px 16px 0px, rgba(255, 255, 255, 0.8) -6px -2px 16px 0px;
+}
+
+.word {
+    background-color: #28b863;
+}
+
+.passage {
+    background-color: #9528b7;
+}
+
+.popup-container {
+    background-color: #fff;
+    position: absolute;
+    width: 120rem;
+    height: 60rem;
+    padding: 30px;
+    border-radius: 10px;
+    top: 25rem;
+    left: 40rem;
+    overflow: scroll;
+    overflow-x: hidden;
+}
+
+.popup-header {
+    justify-content: space-between;
+}
+
+.popup-header p {
+    font-size: 30px;
+    font-family: 'ONEMobilePOPOTF';
+    color: #6327b9;
+}
+
+.popup-content {
+    font-size: 24px;
+    padding: 20px;
+}
+</style>
client/views/pages/main/Chapter/Chapter1_2.vue
--- client/views/pages/main/Chapter/Chapter1_2.vue
+++ client/views/pages/main/Chapter/Chapter1_2.vue
@@ -110,8 +110,9 @@
             this.$router.push({ name: page });
         },
         goToNextPage() {
-            alert('지문 학습 완료!');
+            // alert('지문 학습 완료!');
             this.complete();
+            this.goToPage('Chapter1_1');
         },
         // 대화 지문 API
         async fetchText() {
Add a comment
List