jichoi / lms_front star
이은진 이은진 08-20
240820 이은진 대시보드 사진 기능 추가
@194517e85fc277ca408728af3f6027e416504438
client/views/pages/main/AIDashboard.vue
--- client/views/pages/main/AIDashboard.vue
+++ client/views/pages/main/AIDashboard.vue
@@ -220,8 +220,7 @@
             showModal: false,
             searchOpen: false,  // 사진 상세보기 모달창
             searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창
-            showCameraModal: false, // 카메라 모달창
-            showPhotoModal: false, // 사진꾸미기 모달창
+            showCameraModal: false, // 카메라 모달창 
             photoTaken: false,
             photo: null,    //캡쳐 사진 
             stream: null,
@@ -229,7 +228,6 @@
             isHidden: false,
             images: [],
 
-            photoTaken: false
 
         }
     },
@@ -330,7 +328,6 @@
             this.showCameraModal = false;
             this.photoTaken = false;
             this.photo = null;
-            this.showPhotoModal = false;
 
             //스트림 종료
             if (this.stream) {
client/views/pages/main/Dashboard.vue
--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
@@ -132,31 +132,14 @@
                     </div>
                 </div>
                 <div class="race-btn">
-                    <div class="rabbit-running" style="
-    display: flex;
-"><img class="rabbit-end" src="../../../resources/img/img138_72s.png" alt=""
+                    <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>
-
-                <button class="login-btn mt50" type="submit" style="width: 100%;" @click="finishSchedule"><img
-                        src="../../../resources/img/btn07_s.png" alt="" style="width: 100%; height: 100px;">
-                    <p>학습 종료하기</p>
-                </button>
                 <div class="complete-wrap smt50 myphoto">
-                    <h2 class="mb40">이 단원을 끝낸 친구들</h2>
-                    <article class=" flex-column" style="gap: 5px;">
-                        <div class="flex" style="gap: 5px;">
-                            <div @click="buttonSearch2" class="photo"><img src="../../../resources/img/img143_75s.png"
-                                    alt="">
-                            </div>
-                            <div @click="buttonSearch" class="photo"><img src="../../../resources/img/img143_75s.png"
-                                    alt="">
-                            </div>
-                        </div>
-                    </article>
                     <!-- 팝업 -->
                     <article class="popup-wrap" v-show="searchOpen">
                         <div class="popup-box ">
@@ -203,110 +186,56 @@
                         <div style="width: 100%;">
                             <div id="container" ref="container">
                                 <video v-if="!photoTaken" autoplay="true" ref="modalVideoElement" class="mirrored"
-                                    @canplay="onVideoLoaded"></video>
+                                    @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 type="button" class="new-btn" v-if="!photoTaken" @click="capturePhoto"
-                            :disabled="!videoReady">
-                            사진 촬영
-                        </button>
+                        <button class="new-btn" @click="takePhoto">사진 찍기</button>
                     </div>
                 </div>
             </article>
+        </div>
 
-            <!-- 사진 모달 -->
-            <article v-show="showPhotoModal" class="popup-wrap">
-                <div class="popup-box" style="top: 500px; left: auto">
-                    <div class="flex mb10 justify-between">
-                        <p class="popup-title">사진 꾸미기</p>
-                        <button type="button" class="popup-close-btn" @click="closePhotoModal">
+
+
+        <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" style="gap: 5px;">
+                <div class="flex" style="gap: 5px; flex-wrap: wrap;">
+                    <div v-for="(image, index) in images" :key="image.fileId" @click="buttonSearch(image)"
+                        class="photo">
+                        <img :src="image.url" :alt="image.fileNm" reloadable="true" />
+                    </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="flex justify-between align-center" style="gap: 40px;">
-                        <div class="content" style="padding: 30px; min-width: 401px; min-height: 710px;">
-                            <div class="tool">
-                                <div class="flex justify-center mb20" style="gap: 20px;">
-                                    <button class="popTxt" style="width: 101px;" v-for="(item, index) in items_photo"
-                                        :key="index" @click="updateContent(index)"
-                                        :class="{ active: selectedIndex === index }">
-                                        <img :src="item.imgSrc1" style="display: block;">
-                                        <img :src="item.imgSrc2" v-if="selectedIndex === index" style="display: block;">
-                                    </button>
-                                </div>
-                            </div>
-
-                            <div class="stickers" v-show="!stickersVisible">
-                                <div class="toolbar">
-                                    <label for="brushSize" style="font-size: 9px;">펜 굵기</label>
-                                    <input type="color" v-model="color" />
-                                    <input type="range" id="brushSize" min="1" max="10" v-model="brushSize"
-                                        @input="updateBrushSize" style="width: 100px; margin-left: 5px;" />
-                                    <button class="new-btn" style="font-size: 9px;" @click="setTool('draw')">펜</button>
-                                    <button class="new-btn" style="font-size: 9px;"
-                                        @click="setTool('eraser')">지우개</button>
-                                    <button class="new-btn" style="font-size: 9px;" @click="clearAll">전체
-                                        지우개</button>
-                                </div>
-                            </div>
-
-                            <div class="stickers" v-show="stickersVisible">
-                                <button><img src="../../../resources/img/img146_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img147_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img148_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img149_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img150_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img151_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img152_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img153_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img154_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img155_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img156_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img157_75s.png" alt=""></button>
-                                <button><img src="../../../resources/img/img158_75s.png" alt=""></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>
-                            <div class="content" style="height: 549px; 
-                                    position: relative;
-                                    width: 973px; 
-                                    display: flex; 
-                                    justify-content: center; 
-                                    align-items: center;">
-                                <canvas ref="canvas" style="position: absolute;"></canvas>
-                            </div>
-                            <div class="btn-wrap flex justify-center mt40" style="gap: 40px;">
-                                <button class="login-btn" @click="openCameraModal">
-                                    <img src="../../../resources/img/btn07_s.png" alt="">
-                                    <p>재촬영</p>
-                                </button>
-
-                                <button class="login-btn" type="submit" @click="goToPage('PhotoEdit')">
-                                    <img src="../../../resources/img/btn07_s.png" alt="">
-                                    <p>완성</p>
-                                </button>
-                            </div>
-                        </div>
-                        <div class="content" style="padding: 30px; min-width: 401px; min-height: 710px;">
-                            <div class="mb20">
-                                <p class="popup-title" style="font-size: 32px">랜덤 단어</p>
-                            </div>
-                            <div class="flex-column" style="gap: 10px;">
-                                <button class="login-btn"><img src="../../../resources/img/img141_75s.png" alt="">
-                                    <p class="title">a</p>
-                                </button>
-                                <button class="login-btn"><img src="../../../resources/img/img152_75s_01.png" alt="">
-                                    <p class="title">a</p>
-                                </button>
-                                <button class="login-btn"><img src="../../../resources/img/img144_75s.png" alt="">
-                                    <p class="title" style="color: #fff;">a</p>
-                                </button>
-                                <button class="login-btn"><img src="../../../resources/img/img145_75s.png" alt="">
-                                    <p class="title mt20" style="color: #fff;">a</p>
-                                </button>
-                            </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>
@@ -332,53 +261,21 @@
                     isSecondImageVisible: false
                 },
             ],
-            items_photo: [
-                {
-                    imgSrc1: 'client/resources/img/btn20_75s_normal.png',   //펜 선택되지 않음
-                    imgSrc2: 'client/resources/img/btn20_75s_click.png' //펜 선택됨
-                },
-                {
-                    imgSrc1: 'client/resources/img/btn21_75s_normal.png',   //스티커 선택되지 않음
-                    imgSrc2: 'client/resources/img/btn21_75s_click.png'     //스티커 선택됨
-                },
-            ],
             mdiMagnify: mdiMagnify,
             mdiWindowClose: mdiWindowClose,
             mdiHeart: mdiHeart,
             showModal: false,
             searchOpen: false,  // 사진 상세보기 모달창
             searchOpen2: false, // 단원 마친 후, 사진 촬영 여부 선택 모달창
-            showCameraModal: false, // 카메라 모달창
-            showPhotoModal: false, // 사진꾸미기 모달창
+            showCameraModal: false, // 카메라 모달창 
             photoTaken: false,
-            photo: null,    //캡쳐 사진
-            videoReady: false, // 비디오 준비 상태를 나타내는 플래그
+            photo: null,    //캡쳐 사진 
             stream: null,
-            canvasWidth: 0,
-            canvasHeight: 0,
-            selectedIndex: 0,   //툴 선택 여부 인덱스
-            stickersVisible: false, // 스티커 표시 여부 
 
-            //사진 꾸미기 관련 변수
-            drawHistory: [],    //도형 기록
-            tempLines: [],  //펜 기록
-            stickers: [],   //스티커 파일 기록
-            draggingStickerIndex: null, //스티커 드래그
-            activeStickerIndex: null,  // 현재 활성화된 스티커의 인덱스
-            nextLineId: 0,  //획 아이디
-            tool: 'draw',   //툴 결정
-            color: '#000000',   //펜 기본 색상
-            isDrawing: false,   //그리는 중인지 판단하는 변수
-            brushSize: 5,  // 초기 펜 굵기
-            startX: 0,
-            startY: 0,
-            canvasRect: {
-                topLeft: { x: 0, y: 0 },
-                bottomRight: { x: 0, y: 0 }
-            },
+
             roadmapData: [],
             labeledItems: [],
-            
+
             problemCounter: 0,
             wordCounter: 0,
             textCounter: 0,
@@ -392,10 +289,78 @@
             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,
+
+            images: [],
+            unit_id: "",
+            book_id: "",
         }
     },
     methods: {
         //은진
+        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() {
+            axios({
+                url: "/photo/photoUnitList.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: {
+                    unitId: "UNIT_000000000000001",
+                    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;
+                    }).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');
+
+            this.$router.push({ name: page, query: { image: encodeURIComponent(dataURL) } });
+        },
+
         fetchRabbit() {
             for (var i = 0; i < 12; i++) {
                 this.rabbitPos[i] = false
@@ -467,7 +432,7 @@
                     finish: "T"
                 }
             })
-            .then(response => {
+                .then(response => {
                     const nextSchedule = this.schedules.find(schedule => schedule.schdl_id > this.nowSchedule.schdl_id);
                     alert("학습을 완료했습니다!");
                     window.location.reload();
@@ -494,40 +459,24 @@
                     book_id: book_id
                 }
             })
-            .then(response => {
-                if (response.data.length != 0) {
+                .then(response => {
+                    if (response.data.length != 0) {
                         this.roadmapData = response.data;
                         this.labeledItems = this.processedRoadmap;
-                } else {
+                    } else {
                         this.state = "noProblem"
-                 }
-            })
-            .catch(error => {
+                    }
+                })
+                .catch(error => {
                     this.state = "noProblem"
                     console.error("Error fetching roadmap data:", error);
-            });
+                });
         },
         toggleImage(index) {
             this.items[index].isSecondImageVisible = !this.items[index].isSecondImageVisible;
         },
-        toggleImageAndShowPopup(index, dataNum) {
-            this.toggleImage(index);
-            if (dataNum === '11') {
-                this.searchOpen2 = true;
-            }
-        },
         ShowPopup() {
             this.searchOpen2 = true;  // 촬영 여부 묻는 모달창 열기
-        },
-        updateContent(index) {
-            this.selectedIndex = index;
-
-            // 선택된 버튼이 스티커 버튼(인덱스 1)인지 확인
-            if (index === 1) {
-                this.stickersVisible = true;  // 스티커 툴 보이기
-            } else {
-                this.stickersVisible = false; // 스티커 툴 숨기기
-            }
         },
         goToPage(page) {
             const { unit_id, book_id } = this.$route.query;
@@ -535,12 +484,6 @@
         },
         openCameraModal() {
             this.closeModal();
-            this.closePhotoModal();
-
-            this.drawHistory = [];
-            this.stickers = [];
-            this.tempLines = [];
-            this.videoReady = false; // 비디오 준비 상태 초기화
 
             this.showCameraModal = true;
             navigator.mediaDevices.getUserMedia({ video: true })
@@ -548,7 +491,6 @@
                     const modalVideo = this.$refs.modalVideoElement;
                     modalVideo.srcObject = stream;
                     this.stream = stream;
-                    modalVideo.addEventListener('loadedmetadata', this.adjustContainerSize);
                 })
                 .catch(error => {
                     console.log("error>>>>>>>>", error);
@@ -561,7 +503,6 @@
             this.showCameraModal = false;
             this.photoTaken = false;
             this.photo = null;
-            this.showPhotoModal = false;
 
             //스트림 종료
             if (this.stream) {
@@ -570,24 +511,46 @@
                 this.stream = null;
             }
         },
-        closePhotoModal() { //사진꾸미기 팝업 닫기
-            this.showPhotoModal = false;
-            this.closeModal();
-        },
+
         onVideoLoaded() {
-            this.videoReady = true;
-            this.adjustContainerSize();
-        },
-        adjustContainerSize() {
             const video = this.$refs.modalVideoElement;
-            const container = this.$refs.container;
-            const body = this.$refs.body;
-            if (video && container) {
-                container.style.width = `${video.videoWidth}px`;
-                container.style.height = `${video.videoHeight}px`;
-                body.style.height = `${video.videoHeight}px`;
-            }
+            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;
         },
@@ -597,320 +560,26 @@
         closeBtn() {
             this.searchOpen = false;
         },
-        capturePhoto() {
-            // 사진 촬영 기능 구현
-            console.log("cam on");
-
-            if (!this.videoReady) return; // 비디오가 준비되지 않았으면 사진을 찍지 않음
-
-            const video = this.$refs.modalVideoElement;
-            const canvas = document.createElement('canvas');
-
-            canvas.width = video.videoWidth;
-            canvas.height = video.videoHeight;
-            this.canvasWidth = video.videoWidth;
-            this.canvasHeight = video.videoHeight;
-            const context = canvas.getContext('2d');
-            context.translate(canvas.width, 0);
-            context.scale(-1, 1);
-            context.drawImage(video, 0, 0, canvas.width, canvas.height);
-            this.photo = canvas.toDataURL('image/png');
-            this.photoTaken = true;
-            this.showPhotoModal = true;
-            console.log("PhotoModal open");
-            this.$nextTick(() => {
-                console.log("canvas setup");
-                // console.log("Photo data>>>>", this.photo);
-                this.setupCanvas();
-            });
-
-        },
-        setupCanvas() {
-            const canvas = this.$refs.canvas;
-            // const container = this.$refs.container;
-            if (!canvas) {
-                console.error("Canvas reference not found");
-                resolve();
-                return;
-            }
-            const context = canvas.getContext('2d');
-            if (!context) {
-                console.error("Canvas context not found");
-                return;
-            }
-            const image = new Image();
-            image.src = this.photo;
-            // console.log("Photo data>>>>", image.src);
-            image.onload = () => {
-                console.log("Image loaded successfully");
-                // this.canvasWidth = image.width;
-                // this.canvasHeight = image.height;
-                //이미지 크기가 캔버스와 안맞으면 이미지 불러오는데에 에러 남
-                // container.style.width = this.canvasWidth;
-                // container.style.height = this.canvasHeight;
-
-                canvas.width = this.canvasWidth;
-                canvas.height = this.canvasHeight;
-
-                const rect = canvas.getBoundingClientRect();
-                // 좌측 상단 좌표
-                const topLeft = {
-                    x: rect.left,
-                    y: rect.top
-                };
-
-                // 우측 하단 좌표
-                const bottomRight = {
-                    x: rect.right,
-                    y: rect.bottom
-                };
-
-                // 캔버스 크기 초기화
-                this.updateCanvasRect();
-
-                // 윈도우 리사이즈 이벤트 리스너 추가
-                window.addEventListener('resize', this.updateCanvasRect);
-
-                // 클릭 이벤트 핸들러 추가
-                this.$refs.canvas.addEventListener('click', this.handleCanvasClick);
-
-
-                // canvas.width = canvas.clientWidth;
-                // canvas.height = canvas.clientHeight;
-                // this.canvasWidth = canvas.clientWidth;
-                // this.canvasHeight = canvas.clientHeight;
-
-                context.clearRect(0, 0, canvas.width, canvas.height);  // 이전 이미지 있으면 초기화
-                context.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight);
-                this.addCanvasEventListeners(); //추가해야함
-            };
-            image.onerror = (error) => {
-                console.error("Error loading image: ", error);
-            };
-        },
-
-        addCanvasEventListeners() {
-            const canvas = this.$refs.canvas;
-            canvas.addEventListener('mousedown', this.onMouseDown);
-            canvas.addEventListener('mouseup', this.onMouseUp);
-            canvas.addEventListener('mousemove', this.onMouseMove);
-            canvas.addEventListener('click', this.onCanvasClick);
-        },
-        setTool(tool) {
-            this.tool = tool;
-        },
-        updateBrushSize() {
-            // 펜 굵기 변경 로직
-            if (this.tool === 'draw') {
-                this.setBrushSize(this.brushSize);
-            }
-        },
-        setBrushSize(size) {
-            this.brushSize = size;
-            const context = this.$refs.canvas.getContext('2d');
-            context.lineWidth = size;
-        },
-        // 캔버스 크기 갱신 함수
-        updateCanvasRect() {
-            const rect = this.$refs.canvas.getBoundingClientRect();
-            this.canvasRect = {
-                topLeft: { x: rect.left, y: rect.top },
-                bottomRight: { x: rect.right, y: rect.bottom }
-            };
-            console.log(">>>>>>>>>2222", rect.left);
-        },
-        getCanvasPosition(event) {
-
-            const rect = this.canvasRect;
-            console.log(">>>>>>>>>", this.canvasRect);
-            this.updateCanvasRect();
-
-            // 윈도우 리사이즈 이벤트 리스너 추가
-            window.addEventListener('resize', this.updateCanvasRect);
-
-            // 클릭 이벤트 핸들러 추가
-            this.$refs.canvas.addEventListener('click', this.handleCanvasClick);
-
-            // // 좌측 상단 좌표
-            // const topLeft = {
-            //     x: rect.left,
-            //     y: rect.top
-            // };
-
-            // // 우측 하단 좌표
-            // const bottomRight = {
-            //     x: rect.right,
-            //     y: rect.bottom
-            // };
-
-            // console.log(this.scrollLeft)
-
-            const x = event.clientX - rect.topLeft.x
-            const y = event.clientY - rect.topLeft.y
-
-
-            console.log(`클릭한 좌표: x=${event.clientX}, y=${event.clientY}`);
-            console.log(`계산베이스 좌표: x=${rect.topLeft.x}, y=${rect.topLeft.y}`);
-            console.log(`계산베이스 좌표: x=${rect.topLeft.x}, y=${rect.topLeft.y}`);
-            console.log(`계산된 좌표: x=${x}, y=${y}`);
-            return {
-                x, y
-            };
-        },
-        onMouseDown(event) {
-
-            // 캔버스 크기 초기화
-            this.updateCanvasRect();
-
-            // 윈도우 리사이즈 이벤트 리스너 추가
-            window.addEventListener('resize', this.updateCanvasRect);
-
-            // 클릭 이벤트 핸들러 추가
-            this.$refs.canvas.addEventListener('click', this.handleCanvasClick);
-
-            const { x, y } = this.getCanvasPosition(event);
-            this.startX = x;
-            this.startY = y;
-            const context = this.$refs.canvas.getContext('2d');
-            context.strokeStyle = this.color;
-            context.lineWidth = this.brushSize;  // 브러시 크기 설정
-            if (this.tool === 'draw') {
-                context.beginPath();
-                context.moveTo(this.startX, this.startY);
-                this.nextLineId++;
-            }
-            this.isDrawing = true;
-        },
-        onMouseUp(event) {
-            if (!this.isDrawing) return;
-            const { x, y } = this.getCanvasPosition(event);
-            const context = this.$refs.canvas.getContext('2d');
-            context.strokeStyle = this.color;
-            context.lineWidth = this.brushSize;  // 브러시 크기 설정
-            if (this.tool === 'rectangle') {
-                context.strokeRect(this.startX, this.startY, x - this.startX, y - this.startY);
-                this.drawHistory.push({ type: 'rectangle', startX: this.startX, startY: this.startY, endX: x, endY: y, color: this.color });
-            } else if (this.tool === 'circle') {
-                context.beginPath();
-                const radius = Math.sqrt(Math.pow((x - this.startX), 2) + Math.pow((y - this.startY), 2));
-                context.arc(this.startX, this.startY, radius, 0, 2 * Math.PI);
-                context.stroke();
-                this.drawHistory.push({ type: 'circle', startX: this.startX, startY: this.startY, radius, color: this.color });
-            } else if (this.tool === 'draw') {
-                context.lineTo(x, y);
-                context.stroke();
-                this.tempLines.push({ id: this.nextLineId, startX: this.startX, startY: this.startY, endX: x, endY: y, color: this.color });
-            }
-            this.isDrawing = false;
-        },
-        onMouseMove(event) {
-            if (!this.isDrawing || this.tool !== 'draw') return;
-            const { x, y } = this.getCanvasPosition(event);
-            const context = this.$refs.canvas.getContext('2d');
-            context.strokeStyle = this.color;
-            context.lineWidth = this.brushSize;  // 브러시 크기 설정
-            context.lineTo(x, y);
-            context.stroke();
-            this.tempLines.push({ id: this.nextLineId, startX: this.startX, startY: this.startY, endX: x, endY: y, color: this.color });
-            this.startX = x;
-            this.startY = y;
-        },
-        onCanvasClick(event) {
-            if (this.tool === 'eraser') {
-                const { x, y } = this.getCanvasPosition(event);
-                this.eraseDrawing(x, y);
-            }
-        },
-        eraseDrawing(x, y) {
-            const eraserRadius = 10;
-            this.drawHistory = this.drawHistory.filter(item => {
-                if (item.type === 'rectangle') {
-                    return !(x >= item.startX && x <= item.endX && y >= item.startY && y <= item.endY);
-                } else if (item.type === 'circle') {
-                    const distance = Math.sqrt(Math.pow((x - item.startX), 2) + Math.pow((y - item.startY), 2));
-                    return !(distance <= item.radius);
-                }
-            });
-            const linesToDelete = this.tempLines.filter(line => {
-                const distanceToLine = this.distanceToLineSegment(line.startX, line.startY, line.endX, line.endY, x, y);
-                return distanceToLine <= 10;
-            }).map(line => line.id);
-            this.tempLines = this.tempLines.filter(line => !linesToDelete.includes(line.id));
-            this.redraw();
-        },
-        distanceToLineSegment(x1, y1, x2, y2, px, py) {
-            const lengthSquared = Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2);
-            if (lengthSquared === 0) return Math.sqrt(Math.pow(px - x1, 2) + Math.pow(py - y1, 2));
-            const t = Math.max(0, Math.min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / lengthSquared));
-            const projX = x1 + t * (x2 - x1);
-            const projY = y1 + t * (y2 - y1);
-            return Math.sqrt(Math.pow(px - projX, 2) + Math.pow(py - projY, 2));
-        },
-        clearAll() {
-            this.drawHistory = [];
-            this.stickers = [];
-            this.tempLines = [];
-            this.redraw();
-        },
-        redraw() {
-            const canvas = this.$refs.canvas;
-            const context = canvas.getContext('2d');
-            const image = new Image();
-            image.src = this.photo;
-            image.onload = () => {
-                context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
-                context.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight);
-                this.drawHistory.forEach(item => {
-                    context.strokeStyle = item.color;
-                    if (item.type === 'draw') {
-                        context.beginPath();
-                        context.moveTo(item.startX, item.startY);
-                        context.lineTo(item.endX, item.endY);
-                        context.stroke();
-                    } else if (item.type === 'rectangle') {
-                        context.strokeRect(item.startX, item.startY, item.endX - item.startX, item.endY - item.startY);
-                    } else if (item.type === 'circle') {
-                        context.beginPath();
-                        context.arc(item.startX, item.startY, item.radius, 0, 2 * Math.PI);
-                        context.stroke();
-                    }
-                });
-                this.tempLines.forEach(line => {
-                    context.strokeStyle = line.color;
-                    context.beginPath();
-                    context.moveTo(line.startX, line.startY);
-                    context.lineTo(line.endX, line.endY);
-                    context.stroke();
-                });
-                this.stickers.forEach((sticker, index) => {
-                    context.drawImage(sticker.img, sticker.x, sticker.y, sticker.width, sticker.height);
-                });
-            };
-        },
-        showConfirm(type) {
-            let message = '';
-            if (type === 'cancel') {
-                message = '삭제하시겠습니까?';
-            } else if (type === 'reset') {
-                message = '초기화하시겠습니까?';
-            } else if (type === 'save') {
-                message = '등록하시겠습니까?';
-            }
-
-            if (confirm(message)) {
-                this.goBack();
-            }
-        },
     },
     components: {
         SvgIcon,
     },
     mounted() {
+        this.fetchImage();
         const { book_id, unit_id } = this.$route.query;
+
         console.log('main mounted');
         this.fetchSchedule(unit_id, book_id);
         this.fetchRoadmapData(unit_id, book_id);
         this.fetchRabbit();
+
+        this.onVideoLoaded();
+        this.unit_id = unit_id
+        this.book_id = book_id
+
+        if (this.$route.query.reCapture == 'true') {
+            this.openCameraModal()
+        }
     },
     computed: {
         processedRoadmap() {
@@ -1044,4 +713,12 @@
     left: -40px;
     width: 20rem;
 }
+
+
+.camera-rabbit {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    width: 40%;
+}
 </style>
(파일 끝에 줄바꿈 문자 없음)
client/views/pages/main/PhotoEdit.vue
--- client/views/pages/main/PhotoEdit.vue
+++ client/views/pages/main/PhotoEdit.vue
@@ -41,12 +41,14 @@
       imageSrc: '',
       file: '',
       fileId: '',
+      unit_id: '',
+      book_id: '',
     }
   },
   methods: {
     recapture() {
-      // this.$router.push({ name: 'Dashboard', query: { reCapture: 'true', unit_id, book_id } });
-      this.$router.push({ name: 'AIDashboard', query: { reCapture: 'true' } });
+      // this.$router.push({ name: 'Dashboard', query: { reCapture: 'true', unit_id, book_id } }); 
+      this.$router.push({ name: 'Dashboard', query: { reCapture: 'true', unit_id: this.unit_id, book_id: this.book_id } });
     },
     async fetchImageAsFile(imageUrl, filename = "image.jpg") {
       try {
@@ -109,7 +111,7 @@
             "fileMngId": this.fileId
           }
         });
-        this.$router.push({ name: 'AIDashboard' });
+        this.$router.push({ name: 'Dashboard', query: { unit_id: this.unit_id, book_id: this.book_id } });
       } catch (error) {
         console.error("사진 삽입 오류:", error);
       }
@@ -130,6 +132,8 @@
   components: {
   },
   mounted() {
+    this.book_id = this.$route.query.book_id;
+    this.unit_id = this.$route.query.unit_id;
     this.fetchPhoto();
   }
 }
Add a comment
List