jichoi / lms_front star
홍아랑 홍아랑 2024-08-21
240821 웹캠 모달창 예외처리 코드 수정
@3f53c1c73e86bd24a2f175ab064268d92bf09719
client/views/pages/main/Dashboard.vue
--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
@@ -1,741 +1,1021 @@
 <template>
-    <p class="title1" v-if="state === 'finish'">오늘 공부를 다했어요! 너무 고생했어요!</p>
-    <p class="title1" v-else-if="state === 'notRegistered'">지금은 학습 루트가 등록이 안됐어요! 학습 일정에서 학습루트를 등록해볼까요?</p>
-    <p class="title1" v-else-if="state === 'noProblem'">교재에 등록된 문제가 없습니다.</p>
-    <div v-else class="main">
-        <div class="race-wrap">
-            <div class="title-box">
-                <p class="title" style="margin-top: 7rem;">{{ titleUnitName }}</p>
-                <p class="subtitle">{{ titleBookName }}</p>
-            </div>
-            <div class="race-box">
-
-
-                <div class="rabbit-start"><img src="../../../resources/img/img09_s.png" alt=""
-                        :style="{ display: rabbitPos[0] ? 'block' : 'none' }"></div>
-                <div class="rcon flex justify-end mb5">
-                    <div class="race-btn" @click="goToPage('Chapter1')">
-
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[1] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="1">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[1] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[1] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[0] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter2')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[2] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="2">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[2] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[2] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[1] }}</p>
-                    </div>
-                </div>
-                <div class="lcon flex justify-between mb5">
-                    <div class="race-btn" @click="goToPage('Chapter2_8')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[7] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="7">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[7] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[7] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[6] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter6')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[6] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="6">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[6] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[6] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[5] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter2_8')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[5] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="5">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[5] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[5] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[4] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter2_7')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[4] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="4">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[4] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[4] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[3] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter2_8')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[3] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="3">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[3] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[3] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[2] }}</p>
-                    </div>
-                </div>
-                <div class="rcon flex">
-                    <div class="race-btn" @click="goToPage('Chapter8')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[8] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="8">
-                            <img :src="item.imgSrc3" :style="{ display: !rabbitCompl[8] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc4" :style="{ display: rabbitCompl[8] ? 'block' : 'none' }">
-                        </button>
-                        <p class="long">{{ labeledItems[7] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter2_8')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[9] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="9">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[9] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[9] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[8] }}</p>
-                    </div>
-                    <div class="race-btn" @click="goToPage('Chapter10')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[10] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
-                            data-num="10">
-                            <img :src="item.imgSrc1" :style="{ display: !rabbitCompl[10] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc2" :style="{ display: rabbitCompl[10] ? 'block' : 'none' }">
-                        </button>
-                        <p>{{ labeledItems[9] }}</p>
-                    </div>
-
-                    <div class="race-btn" @click="goToPage('Chapter2_8')">
-                        <div class="rabbit-running"><img src="../../../resources/img/img09_s.png" alt=""
-                                :style="{ display: rabbitPos[11] ? 'block' : 'none' }"></div>
-                        <button class="popTxt" v-for="(item, index) in items" :key="index"
-                            @click="toggleImageAndShowPopup(index, '11')" data-num="11">
-                            <img :src="item.imgSrc3" :style="{ display: !rabbitCompl[11] ? 'block' : 'none' }">
-                            <img :src="item.imgSrc4" :style="{ display: rabbitCompl[11] ? 'block' : 'none' }">
-                        </button>
-                        <p class="long">{{ labeledItems[10] }}</p>
-                    </div>
-                </div>
-                <div class="race-btn">
-                    <div class="rabbit-running" style=" display: flex;"><img class="rabbit-end"
-                            src="../../../resources/img/img138_72s.png" alt=""
-                            :style="{ display: rabbitEnd ? 'block' : 'none' }">
-                        <img class="fireworks-end" src="../../../resources/img/fireworks.gif" alt=""
-                            :style="{ display: rabbitEnd ? 'block' : 'none' }">
-                    </div>
-                </div>
-            </div>
-
-            <!-- 팝업 -->
-            <div v-show="searchOpen2" class="popup-wrap">
-                <div class="popup-box">
-                    <button type="button" class="popup-close-btn" style="position:absolute; top:10px; right: 10px;"
-                        @click="closeModal">
-                        <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
-                    </button>
-
-                    <div class="mb30 text-ct">
-                        <p class="title1 mb20">1단원이 끝났습니다!</p>
-                        <p class="title1"><em class="yellow">기념사진</em>을 촬영하러 가요</p>
-                    </div>
-                    <div class="flex justify-center">
-                        <button type="button" title="사진촬영" class="new-btn" @click="openCameraModal">
-                            사진 촬영
-                        </button>
-                    </div>
-                </div>
-            </div>
-            <!-- 카메라 모달 -->
-            <article v-show="showCameraModal" class="popup-wrap">
-                <div class="popup-box" style="top: 500px; left:500px">
-                    <div class="flex mb10 justify-between">
-                        <p class="popup-title">사진 촬영</p>ㄹ
-                        <button type="button" class="popup-close-btn" @click="closeModal">
-                            <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
-                        </button>
-                    </div>
-                    <div class="box">
-                        <div style="width: 100%;">
-                            <div id="container" ref="container">
-                                <video v-if="!photoTaken" autoplay="true" ref="modalVideoElement" class="mirrored"
-                                    @canplay="onVideoLoaded" style="position: absolute;">
-                                </video>
-                                <img src="../../../resources/img/camera-rabbit.png" class="camera-rabbit"
-                                    style="position: absolute; ">
-                                <canvas ref="canvas" style="pointer-events: none;"></canvas>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="flex justify-center mt20">
-                        <button class="new-btn" @click="takePhoto">사진 찍기</button>
-                    </div>
-                </div>
-            </article>
+  <p class="title1" v-if="state === 'finish'">
+    오늘 공부를 다했어요! 너무 고생했어요!
+  </p>
+  <p class="title1" v-else-if="state === 'notRegistered'">
+    지금은 학습 루트가 등록이 안됐어요! 학습 일정에서 학습루트를 등록해볼까요?
+  </p>
+  <p class="title1" v-else-if="state === 'noProblem'">
+    교재에 등록된 문제가 없습니다.
+  </p>
+  <div v-else class="main">
+    <div class="race-wrap">
+      <div class="title-box">
+        <p class="title" style="margin-top: 7rem">{{ titleUnitName }}</p>
+        <p class="subtitle">{{ titleBookName }}</p>
+      </div>
+      <div class="race-box">
+        <div class="rabbit-start">
+          <img
+            src="../../../resources/img/img09_s.png"
+            alt=""
+            :style="{ display: rabbitPos[0] ? 'block' : 'none' }"
+          />
         </div>
-
-
-
-        <div class="complete-wrap  myphoto">
-            <button class="login-btn mt10" type="submit" style="width: 100%;" @click="finishSchedule"><img
-                    src="../../../resources/img/btn07_s.png" alt="" style="width: 100%; height: 100px;">
-                <p>학습 종료하기</p>
+        <div class="rcon flex justify-end mb5">
+          <div class="race-btn" @click="goToPage('Chapter1')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[1] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="1"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[1] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[1] ? 'block' : 'none' }"
+              />
             </button>
-            <h2 class="mb40 mt10">이 단원을 끝낸 친구들</h2>
-
-            <article class="flex-column">
-                <div class="flex-row">
-                    <div class="flex" style="gap: 5px; flex-wrap: wrap;">
-                        <div v-for="(image, index) in images" :key="image.fileId" @click="buttonSearch(image)"
-                            class="photo" style="margin-bottom: 5px;">
-                            <img :src="image.url" :alt="image.fileNm" reloadable="true" style="height: 100%;" />
-                        </div>
-                    </div>
-                </div>
-            </article>
-            <article class="popup-wrap" v-show="searchOpen">
-                <div class="popup-box ">
-                    <div class="flex mb10  justify-between">
-                        <p class="popup-title">알림</p>
-                        <button type="button" class="popup-close-btn" @click="closeModal">
-                            <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
-                        </button>
-                    </div>
-                    <div class="box">
-                        <div style="width: 910px;"><img src="../../../resources/img/img140_747s.png" alt=""></div>
-                    </div>
-                    <div class="flex justify-between mt20">
-                        <div class="text  flex">
-                            <p class="title2 date ml30">2024-08-06</p>
-                            <span class=" title1 ml30">1단원을 마친 <em class="yellow">가나다</em>친구</span>
-                        </div>
-                        <div class="title2 flex align-center" style="gap: 10px;"><svg-icon type="mdi" :path="mdiHeart"
-                                style="color: #FFBA08;"></svg-icon>
-                            <p><em class="yellow">1</em></p>
-                        </div>
-                    </div>
-                </div>
-            </article>
+            <p>{{ labeledItems[0] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter2')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[2] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="2"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[2] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[2] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[1] }}</p>
+          </div>
         </div>
+        <div class="lcon flex justify-between mb5">
+          <div class="race-btn" @click="goToPage('Chapter2_8')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[7] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="7"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[7] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[7] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[6] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter6')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[6] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="6"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[6] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[6] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[5] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter2_8')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[5] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="5"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[5] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[5] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[4] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter2_7')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[4] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="4"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[4] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[4] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[3] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter2_8')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[3] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="3"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[3] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[3] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[2] }}</p>
+          </div>
+        </div>
+        <div class="rcon flex">
+          <div class="race-btn" @click="goToPage('Chapter8')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[8] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="8"
+            >
+              <img
+                :src="item.imgSrc3"
+                :style="{ display: !rabbitCompl[8] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc4"
+                :style="{ display: rabbitCompl[8] ? 'block' : 'none' }"
+              />
+            </button>
+            <p class="long">{{ labeledItems[7] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter2_8')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[9] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="9"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[9] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[9] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[8] }}</p>
+          </div>
+          <div class="race-btn" @click="goToPage('Chapter10')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[10] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImage(index)"
+              data-num="10"
+            >
+              <img
+                :src="item.imgSrc1"
+                :style="{ display: !rabbitCompl[10] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc2"
+                :style="{ display: rabbitCompl[10] ? 'block' : 'none' }"
+              />
+            </button>
+            <p>{{ labeledItems[9] }}</p>
+          </div>
+
+          <div class="race-btn" @click="goToPage('Chapter2_8')">
+            <div class="rabbit-running">
+              <img
+                src="../../../resources/img/img09_s.png"
+                alt=""
+                :style="{ display: rabbitPos[11] ? 'block' : 'none' }"
+              />
+            </div>
+            <button
+              class="popTxt"
+              v-for="(item, index) in items"
+              :key="index"
+              @click="toggleImageAndShowPopup(index, '11')"
+              data-num="11"
+            >
+              <img
+                :src="item.imgSrc3"
+                :style="{ display: !rabbitCompl[11] ? 'block' : 'none' }"
+              />
+              <img
+                :src="item.imgSrc4"
+                :style="{ display: rabbitCompl[11] ? 'block' : 'none' }"
+              />
+            </button>
+            <p class="long">{{ labeledItems[10] }}</p>
+          </div>
+        </div>
+        <div class="race-btn">
+          <div class="rabbit-running" style="display: flex">
+            <img
+              class="rabbit-end"
+              src="../../../resources/img/img138_72s.png"
+              alt=""
+              :style="{ display: rabbitEnd ? 'block' : 'none' }"
+            />
+            <img
+              class="fireworks-end"
+              src="../../../resources/img/fireworks.gif"
+              alt=""
+              :style="{ display: rabbitEnd ? 'block' : 'none' }"
+            />
+          </div>
+        </div>
+      </div>
+
+      <!-- 팝업 -->
+      <div v-show="searchOpen2" class="popup-wrap">
+        <div class="popup-box">
+          <button
+            type="button"
+            class="popup-close-btn"
+            style="position: absolute; top: 10px; right: 10px"
+            @click="closeModal"
+          >
+            <svg-icon
+              type="mdi"
+              :path="mdiWindowClose"
+              class="close-btn"
+            ></svg-icon>
+          </button>
+
+          <div class="mb30 text-ct">
+            <p class="title1 mb20">1단원이 끝났습니다!</p>
+            <p class="title1">
+              <em class="yellow">기념사진</em>을 촬영하러 가요
+            </p>
+          </div>
+          <div class="flex justify-center">
+            <button
+              type="button"
+              title="사진촬영"
+              class="new-btn"
+              @click="openCameraModal"
+            >
+              사진 촬영
+            </button>
+          </div>
+        </div>
+      </div>
+      <!-- 카메라 모달 -->
+      <article v-show="showCameraModal" class="popup-wrap">
+        <div class="popup-box" style="top: 500px; left: 500px">
+          <div class="flex mb10 justify-between">
+            <p class="popup-title">사진 촬영</p>
+            <button type="button" class="popup-close-btn" @click="closeModal">
+              <svg-icon
+                type="mdi"
+                :path="mdiWindowClose"
+                class="close-btn"
+              ></svg-icon>
+            </button>
+          </div>
+          <div class="box">
+            <div style="width: 100%">
+              <div id="container" ref="container">
+                <video
+                  v-if="!photoTaken"
+                  autoplay="true"
+                  ref="modalVideoElement"
+                  class="mirrored"
+                  @canplay="onVideoLoaded"
+                  style="position: absolute"
+                ></video>
+                <img
+                  src="../../../resources/img/camera-rabbit.png"
+                  class="camera-rabbit"
+                  style="position: absolute"
+                />
+                <canvas ref="canvas" style="pointer-events: none"></canvas>
+              </div>
+            </div>
+          </div>
+          <div class="flex justify-center mt20">
+            <button class="new-btn" @click="takePhoto">사진 찍기</button>
+          </div>
+        </div>
+      </article>
     </div>
+
+    <div class="complete-wrap myphoto">
+      <button
+        class="login-btn mt10"
+        type="submit"
+        style="width: 100%"
+        @click="finishSchedule"
+      >
+        <img
+          src="../../../resources/img/btn07_s.png"
+          alt=""
+          style="width: 100%; height: 100px"
+        />
+        <p>학습 종료하기</p>
+      </button>
+      <h2 class="mb40 mt10">이 단원을 끝낸 친구들</h2>
+
+      <article class="flex-column">
+        <div class="flex-row">
+          <div class="flex" style="gap: 5px; flex-wrap: wrap">
+            <div
+              v-for="(image, index) in images"
+              :key="image.fileId"
+              @click="buttonSearch(image)"
+              class="photo"
+              style="margin-bottom: 5px"
+            >
+              <img
+                :src="image.url"
+                :alt="image.fileNm"
+                reloadable="true"
+                style="height: 100%"
+              />
+            </div>
+          </div>
+        </div>
+      </article>
+      <article class="popup-wrap" v-show="searchOpen">
+        <div class="popup-box">
+          <div class="flex mb10 justify-between">
+            <p class="popup-title">알림</p>
+            <button type="button" class="popup-close-btn" @click="closeModal">
+              <svg-icon
+                type="mdi"
+                :path="mdiWindowClose"
+                class="close-btn"
+              ></svg-icon>
+            </button>
+          </div>
+          <div class="box">
+            <div style="width: 910px">
+              <img src="../../../resources/img/img140_747s.png" alt="" />
+            </div>
+          </div>
+          <div class="flex justify-between mt20">
+            <div class="text flex">
+              <p class="title2 date ml30">2024-08-06</p>
+              <span class="title1 ml30"
+                >1단원을 마친 <em class="yellow">가나다</em>친구</span
+              >
+            </div>
+            <div class="title2 flex align-center" style="gap: 10px">
+              <svg-icon
+                type="mdi"
+                :path="mdiHeart"
+                style="color: #ffba08"
+              ></svg-icon>
+              <p><em class="yellow">1</em></p>
+            </div>
+          </div>
+        </div>
+      </article>
+    </div>
+  </div>
 </template>
 
 <script>
-import SvgIcon from '@jamescoyle/vue-icon';
-import { mdiMagnify, mdiHeart, mdiWindowClose } from '@mdi/js';
-import axios from 'axios';
-import { mapGetters } from 'vuex';
+import SvgIcon from "@jamescoyle/vue-icon";
+import { mdiMagnify, mdiHeart, mdiWindowClose } from "@mdi/js";
+import axios from "axios";
+import { mapGetters } from "vuex";
 
 export default {
-    data() {
-        return {
-            items: [
-                {
-                    imgSrc1: 'client/resources/img/img11_1_s.png',
-                    imgSrc2: 'client/resources/img/img12_1_s.png',
-                    imgSrc3: 'client/resources/img/img11_2_s.png',
-                    imgSrc4: 'client/resources/img/img12_2_s.png',
-                    isSecondImageVisible: false
-                },
-            ],
-            mdiMagnify: mdiMagnify,
-            mdiWindowClose: mdiWindowClose,
-            mdiHeart: mdiHeart,
-            showModal: false,
-            searchOpen: false,  // 사진 상세보기 모달창
-            searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창
-            showCameraModal: false, // 카메라 모달창 
-            photoTaken: false,
-            photo: null,    //캡쳐 사진 
-            stream: null,
+  data() {
+    return {
+      items: [
+        {
+          imgSrc1: "client/resources/img/img11_1_s.png",
+          imgSrc2: "client/resources/img/img12_1_s.png",
+          imgSrc3: "client/resources/img/img11_2_s.png",
+          imgSrc4: "client/resources/img/img12_2_s.png",
+          isSecondImageVisible: false,
+        },
+      ],
+      mdiMagnify: mdiMagnify,
+      mdiWindowClose: mdiWindowClose,
+      mdiHeart: mdiHeart,
+      showModal: false,
+      searchOpen: false, // 사진 상세보기 모달창
+      searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창
+      showCameraModal: false, // 카메라 모달창
+      photoTaken: false,
+      photo: null, //캡쳐 사진
+      stream: null,
 
+      roadmapData: [],
+      labeledItems: [],
 
-            roadmapData: [],
-            labeledItems: [],
+      problemCounter: 0,
+      wordCounter: 0,
+      textCounter: 0,
+      evalCounter: 0,
+      book_id: null,
+      unit_id: null,
 
-            problemCounter: 0,
-            wordCounter: 0,
-            textCounter: 0,
-            evalCounter: 0,
-            book_id: null,
-            unit_id: null,
+      schedules: [],
+      nowSchedule: "",
+      state: "",
+      rabbitPos: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+      rabbitCompl: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+      rabbitEnd: false,
 
-            schedules: [],
-            nowSchedule: "",
-            state: '',
-            rabbitPos: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            rabbitCompl: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-            rabbitEnd: false,
+      titleUnitName: "",
+      titleBookName: "",
 
-            titleUnitName: "",
-            titleBookName: "",
+      images: [],
+      unit_id: "",
+      book_id: "",
+    };
+  },
+  methods: {
+    checkAndFetchData() {
+      console.log("받은 Book ID:", this.getBookId);
+      console.log("받은 Unit ID:", this.getUnitId);
+      const book_id = this.getBookId;
+      const unit_id = this.getUnitId;
 
-            images: [],
-            unit_id: "",
-            book_id: "",
-        }
+      if (!book_id || !unit_id) {
+        console.error("book_id 또는 unit_id가 설정되지 않았습니다.");
+        return;
+      }
+      this.fetchImage(unit_id);
+      this.fetchSchedule(unit_id, book_id);
+      this.fetchRoadmapData(unit_id, book_id);
+      this.fetchRabbit();
+
+      this.unit_id = unit_id;
+      this.book_id = book_id;
+
+      if (this.$route.query.reCapture == "true") {
+        this.openCameraModal();
+      }
     },
-    methods: {
-        checkAndFetchData() {
-            console.log("받은 Book ID:", this.getBookId);
-            console.log("받은 Unit ID:", this.getUnitId);
-            const book_id = this.getBookId;
-            const unit_id = this.getUnitId;
 
-            if (!book_id || !unit_id) {
-                console.error("book_id 또는 unit_id가 설정되지 않았습니다.");
-                return;
-            }
-            this.fetchImage(unit_id);
-            this.fetchSchedule(unit_id, book_id);
-            this.fetchRoadmapData(unit_id, book_id);
-            this.fetchRabbit();
-
-            this.unit_id = unit_id
-            this.book_id = book_id
-
-            if (this.$route.query.reCapture == 'true') {
-                this.openCameraModal()
-            }
+    //은진
+    async findFile(file_mng_id) {
+      try {
+        const res = await axios({
+          url: "/file/find.json",
+          method: "post",
+          headers: {
+            "Content-Type": "application/json; charset=UTF-8",
+          },
+          data: {
+            file_mng_id: file_mng_id,
+          },
+        });
+        return res.data.list[0];
+      } catch (error) {
+        console.log("result - error : ", error);
+        return null;
+      }
+    },
+    fetchImage(unit_id) {
+      axios({
+        url: "/photo/photoUnitList.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
         },
-
-        //은진
-        async findFile(file_mng_id) {
-            try {
-                const res = await axios({
-                    url: "/file/find.json",
-                    method: "post",
-                    headers: {
-                        "Content-Type": "application/json; charset=UTF-8",
-                    },
-                    data: {
-                        file_mng_id: file_mng_id,
-                    },
-                });
-                return res.data.list[0];
-            } catch (error) {
-                console.log("result - error : ", error);
-                return null;
-            }
+        data: {
+          unitId: unit_id,
+          sclsId: "1",
         },
-        fetchImage(unit_id) {
-            axios({
-                url: "/photo/photoUnitList.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    unitId: unit_id,
-                    sclsId: "1"
-                }
+      })
+        .then((response) => {
+          this.file_mng_id = response.data;
+
+          const findFilePromises = this.file_mng_id.map((id) =>
+            this.findFile(id.file_mng_id)
+          );
+
+          return Promise.all(findFilePromises);
+        })
+        .then((fileResults) => {
+          // Format file results to include image URL
+          this.images = fileResults
+            .map((file) => {
+              if (file) {
+                return {
+                  url: "http://localhost:9080/" + `${file.fileRpath}`,
+                  fileId: file.fileId,
+                  fileNm: file.fileNm,
+                  // Add any other properties you need here
+                };
+              }
+              return null;
             })
-                .then(response => {
-                    this.file_mng_id = response.data;
+            .filter((image) => image !== null);
+        })
+        .catch((error) => {
+          console.error("Error fetching images:", error);
+        });
+    },
+    goToPageImg(page) {
+      const canvas = document.querySelector("canvas");
+      const dataURL = canvas.toDataURL("image/png");
 
-                    const findFilePromises = this.file_mng_id.map(id =>
-                        this.findFile(id.file_mng_id)
-                    );
+      this.$router.push({
+        name: page,
+        query: { image: encodeURIComponent(dataURL) },
+      });
+    },
 
-                    return Promise.all(findFilePromises);
-                })
-                .then(fileResults => {
-                    // Format file results to include image URL
-                    this.images = fileResults.map(file => {
-                        if (file) {
-                            return {
-                                url: "http://localhost:9080/" + `${file.fileRpath}`,
-                                fileId: file.fileId,
-                                fileNm: file.fileNm,
-                                // Add any other properties you need here
-                            };
-                        }
-                        return null;
-                    }).filter(image => image !== null);
-                })
-                .catch(error => {
-                    console.error("Error fetching images:", error);
-                });
-        },
-        goToPageImg(page) {
-            const canvas = document.querySelector('canvas');
-            const dataURL = canvas.toDataURL('image/png');
+    fetchRabbit() {
+      for (var i = 0; i < 12; i++) {
+        this.rabbitPos[i] = false;
+      }
 
-            this.$router.push({ name: page, query: { image: encodeURIComponent(dataURL) } });
-        },
+      if (this.$route.query.value) {
+        this.rabbitPos[parseInt(this.$route.query.value, 10) + 1] = true;
+        for (var i = 0; i < this.$route.query.value; i++) {
+          this.rabbitCompl[i + 1] = true;
+        }
 
-        fetchRabbit() {
-            for (var i = 0; i < 12; i++) {
-                this.rabbitPos[i] = false
-            }
-
-            if (this.$route.query.value) {
-                this.rabbitPos[parseInt(this.$route.query.value, 10) + 1] = true
-                for (var i = 0; i < this.$route.query.value; i++) {
-                    this.rabbitCompl[i + 1] = true
-                }
-
-                if (this.$route.query.value === '11') {
-                    this.rabbitEnd = true;
-                    setTimeout(() => {
-                        this.searchOpen2 = true;
-                    }, 1000);
-                }
-
-            }
-            else
-                this.rabbitPos[0] = true
-        },
-        fetchSchedule(unit_id, book_id) {
-            axios({
-                url: "/schedule/selectSchedule.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    stdId: "2",
-                }
-            }).then(response => {
-                this.schedules = response.data;
-
-                if (this.schedules.length == 0) {
-                    this.state = 'notRegistered';
-                } else {
-                    const allFinished = this.schedules.every(schedule => schedule.finish === "T");
-                    if (allFinished) {
-                        this.state = 'finish';
-                    } else {
-                        this.nowSchedule = this.schedules.find(schedule => schedule.finish === null || schedule.finish === "F");
-                        if (this.nowSchedule) {
-                            this.fetchRoadmapData(unit_id, book_id);
-                            this.state = 'studying';
-                        } else {
-                            this.state = 'notRegistered';
-                        }
-                    }
-                }
-            })
-                .catch(error => {
-                    console.error("Error fetching roadmap data:", error);
-                });
-        },
-        finishSchedule() {
-            axios({
-                url: "/schedule/scheduleUpdate.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    scheduleId: this.nowSchedule.schdl_id,
-                    finish: "T"
-                }
-            })
-                .then(response => {
-                    const nextSchedule = this.schedules.find(schedule => schedule.schdl_id > this.nowSchedule.schdl_id);
-                    alert("학습을 완료했습니다!");
-
-                    if (nextSchedule) {
-                        this.nowSchedule = nextSchedule;
-                        this.fetchSchedule(nextSchedule.unit_id, nextSchedule.book_id);
-                        this.fetchRoadmapData(nextSchedule.unit_id, nextSchedule.book_id);
-                        this.$router.push({ name: 'Dashboard', query: { unit_id: nextSchedule.unit_id, book_id: nextSchedule.book_id } });
-                    } else {
-                        alert("모든 학습을 완료했습니다!");
-                        this.state = 'finish';
-                    }
-                })
-                .catch(error => {
-                    console.error("Error updating schedule:", error);
-                });
-        },
-        fetchRoadmapData(unit_id, book_id) {
-            axios({
-                url: "/unitLearning/find.json",
-                method: "post",
-                headers: {
-                    "Content-Type": "application/json; charset=UTF-8",
-                },
-                data: {
-                    unit_id: unit_id,
-                    book_id: book_id
-                }
-            })
-                .then(response => {
-                    if (response.data.length != 0) {
-                        this.roadmapData = response.data;
-                        this.titleUnitName = this.roadmapData[0].unit_nm
-                        this.titleBookName = this.roadmapData[0].book_nm
-                        this.labeledItems = this.processedRoadmap;
-                    } else {
-                        this.state = "noProblem"
-                    }
-                })
-                .catch(error => {
-                    this.state = "noProblem"
-                    console.error("Error fetching roadmap data:", error);
-                });
-        },
-        toggleImage(index) {
-            this.items[index].isSecondImageVisible = !this.items[index].isSecondImageVisible;
-        },
-        ShowPopup() {
-            this.searchOpen2 = true;  // 촬영 여부 묻는 모달창 열기
-        },
-        goToPage(page) {
-            const { unit_id, book_id } = this.$route.query;
-            this.$router.push({ name: page, query: { unit_id, book_id } });
-        },
-        openCameraModal() {
-            this.closeModal();
-
-            this.showCameraModal = true;
-            navigator.mediaDevices.getUserMedia({ video: true })
-                .then(stream => {
-                    const modalVideo = this.$refs.modalVideoElement;
-                    modalVideo.srcObject = stream;
-                    this.stream = stream;
-                })
-                .catch(error => {
-                    console.log("error>>>>>>>>", error);
-                });
-        },
-        closeModal() {  //웹캠 및 모든 팝업 닫기
-            // this.showModal = false;
-            this.searchOpen = false;
-            this.searchOpen2 = false;
-            this.showCameraModal = false;
-            this.photoTaken = false;
-            this.photo = null;
-
-            //스트림 종료
-            if (this.stream) {
-                let tracks = this.stream.getTracks();
-                tracks.forEach(track => track.stop());
-                this.stream = null;
-            }
-        },
-
-        onVideoLoaded() {
-            const video = this.$refs.modalVideoElement;
-            const canvas = this.$refs.canvas;
-            const ctx = canvas.getContext('2d');
-
-            canvas.width = video.videoWidth;
-            canvas.height = video.videoHeight;
-        }, takePhoto() {
-            const video = this.$refs.modalVideoElement;
-            const canvas = this.$refs.canvas;
-            const ctx = canvas.getContext('2d');
-
-            ctx.save(); // 현재 상태 저장
-
-            // 캔버스 좌우 반전
-            ctx.scale(-1, 1);
-            ctx.drawImage(video, -canvas.width, 0, canvas.width, canvas.height);
-
-            ctx.restore();
-
-            const overlayImg = new Image();
-            overlayImg.src = 'client/resources/img/camera-rabbit.png';
-            overlayImg.onload = () => {
-                const overlayWidth = canvas.width * 0.4;
-                const overlayHeight = (overlayImg.height / overlayImg.width) * overlayWidth;
-                const overlayX = canvas.width - overlayWidth;
-                const overlayY = canvas.height - overlayHeight;
-
-                // 오버레이 이미지 그리기
-                ctx.drawImage(overlayImg, overlayX, overlayY, overlayWidth, overlayHeight);
-
-                // 사진 저장 함수 호출
-                const dataURL = canvas.toDataURL('image/png');
-                this.$router.push({ name: 'PhotoEdit', query: { image: encodeURIComponent(dataURL), unit_id: this.unit_id, book_id: this.book_id } });
-            };
-        },
-
-
-
-        buttonSearch() {
-            this.searchOpen = true;
-        },
-        buttonSearch2() {
+        if (this.$route.query.value === "11") {
+          this.rabbitEnd = true;
+          setTimeout(() => {
             this.searchOpen2 = true;
-        },
-        closeBtn() {
-            this.searchOpen = false;
-        },
-    },
-    components: {
-        SvgIcon,
-    },
-    mounted() {
-        console.log('main mounted');
-        this.checkAndFetchData();
-        // const { book_id, unit_id } = this.$route.query;
-    },
-    watch: {
-        getBookId(newBookId) {
-            this.checkAndFetchData();
-        },
-        getUnitId(newUnitId) {
-            this.checkAndFetchData();
+          }, 1000);
         }
+      } else this.rabbitPos[0] = true;
     },
-    computed: {
-        ...mapGetters(['getBookId', 'getUnitId']),
+    fetchSchedule(unit_id, book_id) {
+      axios({
+        url: "/schedule/selectSchedule.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
+        },
+        data: {
+          stdId: "2",
+        },
+      })
+        .then((response) => {
+          this.schedules = response.data;
 
-        processedRoadmap() {
-            let problemCounter = 0;
-            let wordCounter = 0;
-            let textCounter = 0;
-            let evalCounter = 0;
+          if (this.schedules.length == 0) {
+            this.state = "notRegistered";
+          } else {
+            const allFinished = this.schedules.every(
+              (schedule) => schedule.finish === "T"
+            );
+            if (allFinished) {
+              this.state = "finish";
+            } else {
+              this.nowSchedule = this.schedules.find(
+                (schedule) =>
+                  schedule.finish === null || schedule.finish === "F"
+              );
+              if (this.nowSchedule) {
+                this.fetchRoadmapData(unit_id, book_id);
+                this.state = "studying";
+              } else {
+                this.state = "notRegistered";
+              }
+            }
+          }
+        })
+        .catch((error) => {
+          console.error("Error fetching roadmap data:", error);
+        });
+    },
+    finishSchedule() {
+      axios({
+        url: "/schedule/scheduleUpdate.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
+        },
+        data: {
+          scheduleId: this.nowSchedule.schdl_id,
+          finish: "T",
+        },
+      })
+        .then((response) => {
+          const nextSchedule = this.schedules.find(
+            (schedule) => schedule.schdl_id > this.nowSchedule.schdl_id
+          );
+          alert("학습을 완료했습니다!");
 
-            return this.roadmapData.map(item => {
-                if (item.wd_book_id !== null) {
-                    wordCounter++;
-                    return `단어장${wordCounter}`;
-                } else if (item.text_id !== null) {
-                    textCounter++;
-                    return `지문${textCounter}`;
-                } else if (item.eval_id !== null) {
-                    evalCounter++;
-                    return evalCounter === 1 ? '중간평가' : '최종평가';
-                } else {
-                    problemCounter++;
-                    return `문제${problemCounter}`;
-                }
+          if (nextSchedule) {
+            this.nowSchedule = nextSchedule;
+            this.fetchSchedule(nextSchedule.unit_id, nextSchedule.book_id);
+            this.fetchRoadmapData(nextSchedule.unit_id, nextSchedule.book_id);
+            this.$router.push({
+              name: "Dashboard",
+              query: {
+                unit_id: nextSchedule.unit_id,
+                book_id: nextSchedule.book_id,
+              },
             });
-        }
+          } else {
+            alert("모든 학습을 완료했습니다!");
+            this.state = "finish";
+          }
+        })
+        .catch((error) => {
+          console.error("Error updating schedule:", error);
+        });
     },
-    beforeDestroy() {
-        // 컴포넌트가 파괴되기 전에 리스너 제거
-        window.removeEventListener('resize', this.updateCanvasRect);
-        this.$refs.canvas.removeEventListener('click', this.handleCanvasClick);
-    }
-}
+    fetchRoadmapData(unit_id, book_id) {
+      axios({
+        url: "/unitLearning/find.json",
+        method: "post",
+        headers: {
+          "Content-Type": "application/json; charset=UTF-8",
+        },
+        data: {
+          unit_id: unit_id,
+          book_id: book_id,
+        },
+      })
+        .then((response) => {
+          if (response.data.length != 0) {
+            this.roadmapData = response.data;
+            this.titleUnitName = this.roadmapData[0].unit_nm;
+            this.titleBookName = this.roadmapData[0].book_nm;
+            this.labeledItems = this.processedRoadmap;
+          } else {
+            this.state = "noProblem";
+          }
+        })
+        .catch((error) => {
+          this.state = "noProblem";
+          console.error("Error fetching roadmap data:", error);
+        });
+    },
+    toggleImage(index) {
+      this.items[index].isSecondImageVisible =
+        !this.items[index].isSecondImageVisible;
+    },
+    ShowPopup() {
+      this.searchOpen2 = true; // 촬영 여부 묻는 모달창 열기
+    },
+    goToPage(page) {
+      const { unit_id, book_id } = this.$route.query;
+      this.$router.push({ name: page, query: { unit_id, book_id } });
+    },
+    openCameraModal() {
+      this.closeModal();
+
+      this.showCameraModal = true;
+      navigator.mediaDevices
+        .getUserMedia({ video: true })
+        .then((stream) => {
+          const modalVideo = this.$refs.modalVideoElement;
+          modalVideo.srcObject = stream;
+          this.stream = stream;
+        })
+        .catch((error) => {
+          console.log("error>>>>>>>>", error);
+          alert("웹캠이 필요한 기능입니다!");
+          this.closeModal(); // 모달창을 닫음
+        });
+    },
+    closeModal() {
+      //웹캠 및 모든 팝업 닫기
+      // this.showModal = false;
+      this.searchOpen = false;
+      this.searchOpen2 = false;
+      this.showCameraModal = false;
+      this.photoTaken = false;
+      this.photo = null;
+
+      //스트림 종료
+      if (this.stream) {
+        let tracks = this.stream.getTracks();
+        tracks.forEach((track) => track.stop());
+        this.stream = null;
+      }
+    },
+
+    onVideoLoaded() {
+      const video = this.$refs.modalVideoElement;
+      const canvas = this.$refs.canvas;
+      const ctx = canvas.getContext("2d");
+
+      canvas.width = video.videoWidth;
+      canvas.height = video.videoHeight;
+    },
+    takePhoto() {
+      const video = this.$refs.modalVideoElement;
+      const canvas = this.$refs.canvas;
+      const ctx = canvas.getContext("2d");
+
+      ctx.save(); // 현재 상태 저장
+
+      // 캔버스 좌우 반전
+      ctx.scale(-1, 1);
+      ctx.drawImage(video, -canvas.width, 0, canvas.width, canvas.height);
+
+      ctx.restore();
+
+      const overlayImg = new Image();
+      overlayImg.src = "client/resources/img/camera-rabbit.png";
+      overlayImg.onload = () => {
+        const overlayWidth = canvas.width * 0.4;
+        const overlayHeight =
+          (overlayImg.height / overlayImg.width) * overlayWidth;
+        const overlayX = canvas.width - overlayWidth;
+        const overlayY = canvas.height - overlayHeight;
+
+        // 오버레이 이미지 그리기
+        ctx.drawImage(
+          overlayImg,
+          overlayX,
+          overlayY,
+          overlayWidth,
+          overlayHeight
+        );
+
+        // 사진 저장 함수 호출
+        const dataURL = canvas.toDataURL("image/png");
+        this.$router.push({
+          name: "PhotoEdit",
+          query: {
+            image: encodeURIComponent(dataURL),
+            unit_id: this.unit_id,
+            book_id: this.book_id,
+          },
+        });
+      };
+    },
+
+    buttonSearch() {
+      this.searchOpen = true;
+    },
+    buttonSearch2() {
+      this.searchOpen2 = true;
+    },
+    closeBtn() {
+      this.searchOpen = false;
+    },
+  },
+  components: {
+    SvgIcon,
+  },
+  mounted() {
+    console.log("main mounted");
+    this.checkAndFetchData();
+    // const { book_id, unit_id } = this.$route.query;
+  },
+  watch: {
+    getBookId(newBookId) {
+      this.checkAndFetchData();
+    },
+    getUnitId(newUnitId) {
+      this.checkAndFetchData();
+    },
+  },
+  computed: {
+    ...mapGetters(["getBookId", "getUnitId"]),
+
+    processedRoadmap() {
+      let problemCounter = 0;
+      let wordCounter = 0;
+      let textCounter = 0;
+      let evalCounter = 0;
+
+      return this.roadmapData.map((item) => {
+        if (item.wd_book_id !== null) {
+          wordCounter++;
+          return `단어장${wordCounter}`;
+        } else if (item.text_id !== null) {
+          textCounter++;
+          return `지문${textCounter}`;
+        } else if (item.eval_id !== null) {
+          evalCounter++;
+          return evalCounter === 1 ? "중간평가" : "최종평가";
+        } else {
+          problemCounter++;
+          return `문제${problemCounter}`;
+        }
+      });
+    },
+  },
+  beforeDestroy() {
+    // 컴포넌트가 파괴되기 전에 리스너 제거
+    window.removeEventListener("resize", this.updateCanvasRect);
+    this.$refs.canvas.removeEventListener("click", this.handleCanvasClick);
+  },
+};
 </script>
 
 <style scoped>
 .body {
-    width: 1435px;
-    height: auto;
-    margin: 0 auto;
+  width: 1435px;
+  height: auto;
+  margin: 0 auto;
 }
 
 #container {
-    position: relative;
-    margin: auto;
-    border: 10px #333 solid;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    z-index: 100;
+  position: relative;
+  margin: auto;
+  border: 10px #333 solid;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 100;
 }
 
 video {
-    width: 100%;
-    height: auto;
-    background-color: #666;
+  width: 100%;
+  height: 100%;
+  background-color: #666;
 }
 
 .mirrored {
-    transform: scaleX(-1);
+  transform: scaleX(-1);
 }
 
 .new-btn:disabled {
-    background-color: #FFF3D7;
-    cursor: not-allowed;
+  background-color: #fff3d7;
+  cursor: not-allowed;
 }
 
 .sticker {
-    position: absolute;
-    cursor: move;
+  position: absolute;
+  cursor: move;
 }
 
 .sticker-handle {
-    width: 15px;
-    height: 15px;
-    background: rgba(255, 255, 255, 0.521);
-    position: absolute;
-    bottom: 0;
-    right: 0;
-    cursor: nwse-resize;
-    font-size: 13px;
-    font-weight: bolder;
-    color: rgb(63, 63, 63);
+  width: 15px;
+  height: 15px;
+  background: rgba(255, 255, 255, 0.521);
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  cursor: nwse-resize;
+  font-size: 13px;
+  font-weight: bolder;
+  color: rgb(63, 63, 63);
 }
 
 .sticker-delete {
-    position: absolute;
-    top: 0;
-    right: 0;
-    background: rgba(255, 0, 0, 0.425);
-    color: white;
-    padding: 5px;
-    cursor: pointer;
+  position: absolute;
+  top: 0;
+  right: 0;
+  background: rgba(255, 0, 0, 0.425);
+  color: white;
+  padding: 5px;
+  cursor: pointer;
 }
 
 .toolbar {
-    display: flex;
-    justify-content: center;
-    margin-top: 10px;
+  display: flex;
+  justify-content: center;
+  margin-top: 10px;
 }
 
 .toolbar button {
-    margin: 5px;
-    padding: 5px 10px;
-    cursor: pointer;
+  margin: 5px;
+  padding: 5px 10px;
+  cursor: pointer;
 }
 
 .toolbar input {
-    margin: 5px;
+  margin: 5px;
 }
 
 .rabbit-end {
-    cursor: pointer;
-    display: block;
-    position: absolute;
-    bottom: 0px;
-    left: -15px;
-    z-index: 10000;
+  cursor: pointer;
+  display: block;
+  position: absolute;
+  bottom: 0px;
+  left: -15px;
+  z-index: 10000;
 }
 
 .rabbit-running {
-    position: absolute;
-    bottom: 40px;
-    right: 110px;
-    z-index: 10000;
-    transform: scaleX(-1);
-    transition: all 0.5s ease-in-out;
+  position: absolute;
+  bottom: 40px;
+  right: 110px;
+  z-index: 10000;
+  transform: scaleX(-1);
+  transition: all 0.5s ease-in-out;
 }
 
 .fireworks-end {
-    position: absolute;
-    bottom: 70px;
-    left: -40px;
-    width: 20rem;
+  position: absolute;
+  bottom: 70px;
+  left: -40px;
+  width: 20rem;
 }
-
 
 .camera-rabbit {
-    position: absolute;
-    right: 0;
-    bottom: 0;
-    width: 40%;
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  width: 40%;
 }
-</style>
(파일 끝에 줄바꿈 문자 없음)
+</style>
Add a comment
List