
Merge branch 'master' of http://210.180.118.83/jichoi/lms_front
@200c8844e22408fa280ffd733e27cd9e5da3723e
--- client/views/layout/Side.vue
+++ client/views/layout/Side.vue
... | ... | @@ -25,7 +25,7 @@ |
25 | 25 |
<div class="ask mb30"> |
26 | 26 |
<p class="title1 mb15">선생님께 질문 있어요~</p> |
27 | 27 |
|
28 |
- <div class="memo mb15"><textarea name="" id="" placeholder="궁금한 것을 적어보세요."></textarea></div> |
|
28 |
+ <div class="memo mb15"><textarea name="" id="" placeholder="궁금한 것을 적어보세요." v-model="studentInfo.studentQuestion"></textarea></div> |
|
29 | 29 |
<div class="flex justify-end"><button>질문하기</button></div> |
30 | 30 |
</div> |
31 | 31 |
<!-- <div class="btn-wrap flex justify-between"> |
--- client/views/pages/main/Chapter/Chapter1_2.vue
+++ client/views/pages/main/Chapter/Chapter1_2.vue
... | ... | @@ -21,7 +21,7 @@ |
21 | 21 |
<article class="flex align-start mb10"> |
22 | 22 |
<div class="icon mr40"> |
23 | 23 |
<img src="../../../../resources/img/img37_s.png" alt=""> |
24 |
- <p class="name">발화좌</p> |
|
24 |
+ <p class="name">발화자</p> |
|
25 | 25 |
</div> |
26 | 26 |
<p class="read">What’s up man, nice to meet you Minsu. how are you today?</p> |
27 | 27 |
</article> |
... | ... | @@ -29,13 +29,13 @@ |
29 | 29 |
<p class="read mr40">What’s up man, nice to meet you Minsu. how are you today?</p> |
30 | 30 |
<div class="icon "> |
31 | 31 |
<img src="../../../../resources/img/img37_s.png" alt=""> |
32 |
- <p class="name">발화좌</p> |
|
32 |
+ <p class="name">발화자</p> |
|
33 | 33 |
</div> |
34 | 34 |
</article> |
35 | 35 |
<article class="flex align-start mb10"> |
36 | 36 |
<div class="icon mr40"> |
37 | 37 |
<img src="../../../../resources/img/img37_s.png" alt=""> |
38 |
- <p class="name">발화좌</p> |
|
38 |
+ <p class="name">발화자</p> |
|
39 | 39 |
</div> |
40 | 40 |
<p class="read">What’s up man, nice to meet you Minsu. how are you today?</p> |
41 | 41 |
</article> |
... | ... | @@ -43,7 +43,7 @@ |
43 | 43 |
<p class="read mr40">What’s up man, nice to meet you Minsu. how are you today?</p> |
44 | 44 |
<div class="icon "> |
45 | 45 |
<img src="../../../../resources/img/img37_s.png" alt=""> |
46 |
- <p class="name">발화좌</p> |
|
46 |
+ <p class="name">발화자</p> |
|
47 | 47 |
</div> |
48 | 48 |
</article> |
49 | 49 |
</div> |
--- client/views/pages/main/Chapter/Chapter2_10.vue
+++ client/views/pages/main/Chapter/Chapter2_10.vue
... | ... | @@ -15,54 +15,53 @@ |
15 | 15 |
<p class="title mt25 title-bg">step2</p> |
16 | 16 |
<div class="flex align-center mb30"> |
17 | 17 |
<p class="subtitle2 mr20">방문이 자물쇠로 잠겨져 있네? 세 개 중에 맞는 열쇠 하나를 찾아줘!</p> |
18 |
- <!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
|
19 |
- </button> --> |
|
20 | 18 |
</div> |
21 | 19 |
|
22 | 20 |
<div class="flex align-center justify-center" style="gap: 113px;"> |
23 | 21 |
<div class="imgGroup"> |
24 | 22 |
<div class="flex" style="gap: 60px;"> |
25 | 23 |
<button><img src="../../../../resources/img/img82_42s.png" alt=""> |
26 |
- <p>1</p> |
|
24 |
+ <p>Tell me</p> |
|
27 | 25 |
</button> |
28 | 26 |
<button><img src="../../../../resources/img/img159_42s.png" alt=""></button> |
29 | 27 |
<button><img src="../../../../resources/img/img83_42s.png" alt=""> |
30 |
- <p>1</p> |
|
28 |
+ <p>Why</p> |
|
31 | 29 |
</button> |
32 | 30 |
</div> |
33 |
- |
|
34 | 31 |
</div> |
35 | 32 |
<div class="pickGroup"> |
36 | 33 |
<div> |
37 |
- <article class="flex justify-center mb50" style="gap: 60px;"> |
|
34 |
+ <article class="flex justify-center mb50" style="gap: 60px;"> |
|
38 | 35 |
<img src="../../../../resources/img/img84_42s.png" alt=""> |
39 | 36 |
<div class="flex"> |
40 |
- <button><img src="../../../../resources/img/img136_71s.png" alt=""> |
|
41 |
- <p>1</p> |
|
37 |
+ <button @click="handleClick('You are so upset.', 1)"> |
|
38 |
+ <img src="../../../../resources/img/img136_71s.png" alt=""> |
|
39 |
+ <p :class="{ active: selectedButton === 1 }">1</p> |
|
42 | 40 |
</button> |
43 |
- <p>a</p> |
|
41 |
+ <p>You are so upset.</p> |
|
44 | 42 |
</div> |
45 | 43 |
</article> |
46 |
- <article class="flex justify-center mb50" style="gap: 60px;"> |
|
44 |
+ <article class="flex justify-center mb50" style="gap: 60px;"> |
|
47 | 45 |
<img src="../../../../resources/img/img85_42s.png" alt=""> |
48 | 46 |
<div class="flex"> |
49 |
- <button><img src="../../../../resources/img/img136_71s.png" alt=""> |
|
50 |
- <p>2</p> |
|
47 |
+ <button @click="handleClick('You is so upset.', 2)"> |
|
48 |
+ <img src="../../../../resources/img/img136_71s.png" alt=""> |
|
49 |
+ <p :class="{ active: selectedButton === 2 }">2</p> |
|
51 | 50 |
</button> |
52 |
- <p>a</p> |
|
51 |
+ <p>You is so upset.</p> |
|
53 | 52 |
</div> |
54 | 53 |
</article> |
55 |
- <article class="flex justify-center" style="gap: 60px;"> |
|
54 |
+ <article class="flex justify-center" style="gap: 60px;"> |
|
56 | 55 |
<img src="../../../../resources/img/img86_42s.png" alt=""> |
57 | 56 |
<div class="flex"> |
58 |
- <button><img src="../../../../resources/img/img136_71s.png" alt=""> |
|
59 |
- <p>3</p> |
|
57 |
+ <button @click="handleClick('You am so upset.', 3)"> |
|
58 |
+ <img src="../../../../resources/img/img136_71s.png" alt=""> |
|
59 |
+ <p :class="{ active: selectedButton === 3 }">3</p> |
|
60 | 60 |
</button> |
61 |
- <p>a</p> |
|
61 |
+ <p>You am so upset.</p> |
|
62 | 62 |
</div> |
63 | 63 |
</article> |
64 | 64 |
</div> |
65 |
- |
|
66 | 65 |
</div> |
67 | 66 |
</div> |
68 | 67 |
</div> |
... | ... | @@ -75,26 +74,26 @@ |
75 | 74 |
export default { |
76 | 75 |
data() { |
77 | 76 |
return { |
78 |
- } |
|
77 |
+ selectedButton: null, // 선택된 버튼을 추적하기 위한 데이터 |
|
78 |
+ }; |
|
79 | 79 |
}, |
80 | 80 |
methods: { |
81 | 81 |
goToPage(page) { |
82 | 82 |
this.$router.push({ name: page }); |
83 |
+ }, |
|
84 |
+ handleClick(text, buttonNumber) { |
|
85 |
+ this.selectedButton = buttonNumber; // 선택된 버튼 번호를 저장 |
|
86 |
+ |
|
87 |
+ if (text === 'You are so upset.') { |
|
88 |
+ alert('정답입니다!'); |
|
89 |
+ } else { |
|
90 |
+ alert('오답입니다!'); |
|
91 |
+ } |
|
83 | 92 |
} |
84 |
- }, |
|
85 |
- watch: { |
|
86 |
- |
|
87 |
- }, |
|
88 |
- computed: { |
|
89 |
- |
|
90 |
- }, |
|
91 |
- components: { |
|
92 |
- }, |
|
93 |
- mounted() { |
|
94 |
- |
|
95 | 93 |
} |
96 | 94 |
} |
97 | 95 |
</script> |
96 |
+ |
|
98 | 97 |
<style scoped> |
99 | 98 |
.imgGroup{width: fit-content;} |
100 | 99 |
.imgGroup button { |
... | ... | @@ -112,7 +111,7 @@ |
112 | 111 |
background: #ffffffb8; |
113 | 112 |
border-radius: 5px; |
114 | 113 |
padding: 10px; |
115 |
- font-size: 48px; |
|
114 |
+ font-size: 23px; |
|
116 | 115 |
font-family: 'ONEMobilePOP'; |
117 | 116 |
} |
118 | 117 |
|
... | ... | @@ -129,8 +128,18 @@ |
129 | 128 |
left: 50%; |
130 | 129 |
transform: translate(-50%, -50%); |
131 | 130 |
} |
132 |
-.pickGroup article img{object-fit: contain; width: -webkit-fill-available;} |
|
133 |
-.pickGroup article >div >p { |
|
134 |
- font-size: 64px; |
|
131 |
+ |
|
132 |
+.pickGroup article img { |
|
133 |
+ object-fit: contain; |
|
134 |
+ width: -webkit-fill-available; |
|
135 | 135 |
} |
136 |
-</style>(No newline at end of file) |
|
136 |
+ |
|
137 |
+.pickGroup article >div >p { |
|
138 |
+ font-size: 25px; |
|
139 |
+ white-space: nowrap; /* 텍스트가 줄 바꿈 없이 한 줄로 표시되도록 설정 */ |
|
140 |
+} |
|
141 |
+ |
|
142 |
+.pickGroup button p.active { |
|
143 |
+ color: #000; /* 선택된 버튼의 숫자 색을 더 진하게 */ |
|
144 |
+} |
|
145 |
+</style> |
--- client/views/pages/main/Chapter/Chapter2_13.vue
+++ client/views/pages/main/Chapter/Chapter2_13.vue
... | ... | @@ -70,9 +70,9 @@ |
70 | 70 |
</div> |
71 | 71 |
</div> |
72 | 72 |
<!-- 오답일 경우 아래의 이미지가 보여야함 --> |
73 |
- <div class="flex justify-center wrong-anwser" style="gap: 20px;"> |
|
73 |
+ <!-- <div class="flex justify-center wrong-anwser" style="gap: 20px;"> |
|
74 | 74 |
<img src="../../../../resources/img/img165_46s.png" alt=""> |
75 |
- </div> |
|
75 |
+ </div> --> |
|
76 | 76 |
|
77 | 77 |
</div> |
78 | 78 |
</div> |
--- client/views/pages/main/Chapter/Chapter2_4.vue
+++ client/views/pages/main/Chapter/Chapter2_4.vue
... | ... | @@ -53,9 +53,9 @@ |
53 | 53 |
return { |
54 | 54 |
items: [ |
55 | 55 |
{ imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img59_36s.png', title: 'apple' }, |
56 |
- { imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img58_36s.png', title: 'a'}, |
|
57 |
- { imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img57_36s.png', title: 'a' }, |
|
58 |
- { imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img56_36s.png', title: 'a' }, |
|
56 |
+ { imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img58_36s.png', title: 'cloud'}, |
|
57 |
+ { imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img57_36s.png', title: 'car' }, |
|
58 |
+ { imgSrc1: 'client/resources/img/img61_36s.png', imgSrc2: 'client/resources/img/img62_36s.png', imgSrc: 'client/resources/img/img56_36s.png', title: 'guitar' }, |
|
59 | 59 |
], |
60 | 60 |
selectedIndex: 0, |
61 | 61 |
timer: "00", |
--- client/views/pages/main/Chapter/Chapter2_8.vue
+++ client/views/pages/main/Chapter/Chapter2_8.vue
... | ... | @@ -1,78 +1,154 @@ |
1 | 1 |
<template> |
2 |
- <div id="Chapter1_1" class="content-wrap"> |
|
3 |
- <div style="margin: 30px 0px 50px"> |
|
4 |
- <router-link to="/MyPlan.page"> |
|
5 |
- <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
- </router-link> |
|
7 |
- </div> |
|
8 |
- <div class="title-box mb25 flex align-center mt40"> |
|
9 |
- <span class="title mr40">1. Hello WORLD</span> |
|
10 |
- <span class="subtitle">my name is dd</span> |
|
11 |
- </div> |
|
12 |
- <div class="flex justify-between align-center"> |
|
13 |
- <div class="pre-btn" @click="goToPage('Chapter2_9')"><img src="../../../../resources/img/left.png" alt=""></div> |
|
14 |
- <div class="content title-box"> |
|
15 |
- <p class="title mt25 title-bg">step2</p> |
|
16 |
- <div class="flex align-center mb30"> |
|
17 |
- <p class="subtitle2 mr20">앗! 퍼즐이 망가졌어! 퍼즐을 맞춰 문장을 완성해보자!</p> |
|
18 |
- <!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
|
19 |
- </button> --> |
|
20 |
- </div> |
|
21 |
- |
|
22 |
- <div class="text-ct"> |
|
23 |
- <div class="dropGroup flex align-center justify-center mt30"> |
|
24 |
- <div style="position: relative;" > |
|
25 |
- <img src="../../../../resources/img/img28_s.png" alt=""> |
|
26 |
- <button style=" left: 30px; |
|
27 |
- top: 167px;"><img src="../../../../resources/img/img29_s_01.png" alt=""><p>a</p></button> |
|
28 |
- <button style=" right: 409px; |
|
29 |
- top: 133px;"><img src="../../../../resources/img/img30_s_01.png" alt=""><p>a</p></button> |
|
30 |
- <button style=" right: 46px; |
|
31 |
- top: 128px;"><img src="../../../../resources/img/img31_s_01.png" alt=""><p>a</p></button> |
|
32 |
- |
|
33 |
- </div> |
|
34 |
- </div> |
|
35 |
- <div class="dragGroup "> |
|
36 |
- <div class="flex justify-center" style="gap: 20px;"> |
|
37 |
- <article style=" right: 0; |
|
38 |
- top: 36%; "><button><img src="../../../../resources/img/img29_s.png" alt=""><p>a</p></button></article> |
|
39 |
- <article style=" left: 0; |
|
40 |
- top: 36%; "><button><img src="../../../../resources/img/img30_s.png" alt=""><p>a</p></button></article> |
|
41 |
- <article style="left: 50%; |
|
42 |
- top: 10%;"><button><img src="../../../../resources/img/img31_s.png" alt=""><p>a</p></button></article> |
|
43 |
- </div> |
|
44 |
- |
|
45 |
- </div> |
|
46 |
- </div> |
|
47 |
- </div> |
|
48 |
- <div class="next-btn" @click="goToPage('Chapter2_12')"><img src="../../../../resources/img/right.png" alt=""></div> |
|
49 |
- </div> |
|
2 |
+ <div id="Chapter1_1" class="content-wrap"> |
|
3 |
+ <div style="margin: 30px 0px 50px"> |
|
4 |
+ <router-link to="/MyPlan.page"> |
|
5 |
+ <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
+ </router-link> |
|
50 | 7 |
</div> |
51 |
- </template> |
|
8 |
+ <div class="title-box mb25 flex align-center mt40"> |
|
9 |
+ <span class="title mr40">1. Hello WORLD</span> |
|
10 |
+ <span class="subtitle">my name is dd</span> |
|
11 |
+ </div> |
|
12 |
+ <div class="flex justify-between align-center"> |
|
13 |
+ <div class="pre-btn" @click="goToPage('Chapter2_9')"><img src="../../../../resources/img/left.png" alt=""></div> |
|
14 |
+ <div class="content title-box"> |
|
15 |
+ <p class="title mt25 title-bg">step2</p> |
|
16 |
+ <div class="flex align-center mb30"> |
|
17 |
+ <p class="subtitle2 mr20">앗! 퍼즐이 망가졌어! 퍼즐을 맞춰 문장을 완성해보자!</p> |
|
18 |
+ </div> |
|
19 |
+ |
|
20 |
+ <div class="text-ct"> |
|
21 |
+ <div class="dropGroup flex align-center justify-center mt30"> |
|
22 |
+ <div style="position: relative;"> |
|
23 |
+ <img src="../../../../resources/img/img28_s.png" alt=""> |
|
24 |
+ <button class="dropzone" data-answer="This" style="left: 30px; top: 167px;"> |
|
25 |
+ <img src="../../../../resources/img/img29_s_01.png" alt=""> |
|
26 |
+ <p style="font-size: 35px;">?</p> |
|
27 |
+ </button> |
|
28 |
+ <button class="dropzone" data-answer="is" style="right: 409px; top: 133px;"> |
|
29 |
+ <img src="../../../../resources/img/img30_s_01.png" alt=""> |
|
30 |
+ <p style="font-size: 35px;">?</p> |
|
31 |
+ </button> |
|
32 |
+ <button class="dropzone" data-answer="a pen" style="right: 46px; top: 128px;"> |
|
33 |
+ <img src="../../../../resources/img/img31_s_01.png" alt=""> |
|
34 |
+ <p style="font-size: 35px;">?</p> |
|
35 |
+ </button> |
|
36 |
+ </div> |
|
37 |
+ </div> |
|
38 |
+ <div class="dragGroup flex justify-center" style="gap: 20px;"> |
|
39 |
+ <article style="right: 0; top: 36%;"> |
|
40 |
+ <button class="draggable" data-text="This" draggable="true"> |
|
41 |
+ <img src="../../../../resources/img/img29_s.png" alt=""> |
|
42 |
+ <p style="font-size: 35px;">This</p> |
|
43 |
+ </button> |
|
44 |
+ </article> |
|
45 |
+ <article style="left: 0; top: 36%;"> |
|
46 |
+ <button class="draggable" data-text="is" draggable="true"> |
|
47 |
+ <img src="../../../../resources/img/img30_s.png" alt=""> |
|
48 |
+ <p style="font-size: 35px;">is</p> |
|
49 |
+ </button> |
|
50 |
+ </article> |
|
51 |
+ <article style="left: 50%; top: 10%;"> |
|
52 |
+ <button class="draggable" data-text="a pen" draggable="true"> |
|
53 |
+ <img src="../../../../resources/img/img31_s.png" alt=""> |
|
54 |
+ <p style="font-size: 35px;">a pen</p> |
|
55 |
+ </button> |
|
56 |
+ </article> |
|
57 |
+ </div> |
|
58 |
+ </div> |
|
59 |
+ </div> |
|
60 |
+ <div class="next-btn" @click="goToPage('Chapter2_12')"><img src="../../../../resources/img/right.png" alt=""></div> |
|
61 |
+ </div> |
|
62 |
+ </div> |
|
63 |
+</template> |
|
64 |
+ |
|
52 | 65 |
|
53 |
- <script> |
|
54 |
- export default { |
|
55 |
- data() { |
|
56 |
- return { |
|
66 |
+<script> |
|
67 |
+export default { |
|
68 |
+ data() { |
|
69 |
+ return { |
|
70 |
+ draggedElement: null, // 현재 드래그 중인 요소 |
|
71 |
+ }; |
|
72 |
+ }, |
|
73 |
+ methods: { |
|
74 |
+ goToPage(page) { |
|
75 |
+ this.$router.push({ name: page }); |
|
76 |
+ }, |
|
77 |
+ handleDragStart(event) { |
|
78 |
+ this.draggedElement = event.target; // 드래그한 요소 저장 |
|
79 |
+ event.dataTransfer.setData('text/plain', event.target.dataset.text); |
|
80 |
+ event.target.style.cursor = 'grabbing'; // 드래그 중 커서 변경 |
|
81 |
+ }, |
|
82 |
+ handleDragEnd(event) { |
|
83 |
+ event.target.style.cursor = 'grab'; // 드래그 종료 후 커서 변경 |
|
84 |
+ }, |
|
85 |
+ handleDragOver(event) { |
|
86 |
+ event.preventDefault(); // 드롭 허용 |
|
87 |
+ }, |
|
88 |
+ handleDrop(event) { |
|
89 |
+ event.preventDefault(); |
|
90 |
+ const dropZone = event.target.closest('button.dropzone'); |
|
91 |
+ const draggedText = this.draggedElement ? this.draggedElement.dataset.text : ''; |
|
92 |
+ |
|
93 |
+ if (dropZone) { |
|
94 |
+ const expectedText = dropZone.dataset.answer; |
|
95 |
+ if (draggedText === expectedText) { |
|
96 |
+ // 드래그된 텍스트가 정답인 경우 |
|
97 |
+ const rect = dropZone.getBoundingClientRect(); |
|
98 |
+ // 버튼의 이미지 및 텍스트를 드롭존에 맞게 설정 |
|
99 |
+ dropZone.querySelector('p').textContent = draggedText; |
|
100 |
+ dropZone.querySelector('img').style.display = 'none'; // 기존 이미지 숨기기 |
|
101 |
+ |
|
102 |
+ // 드래그된 버튼의 이미지와 텍스트를 드롭존에 복사 |
|
103 |
+ const draggedImage = this.draggedElement.querySelector('img').cloneNode(); |
|
104 |
+ const draggedTextElement = this.draggedElement.querySelector('p').cloneNode(); |
|
105 |
+ |
|
106 |
+ // 드롭존에 이미지 및 텍스트를 추가 |
|
107 |
+ dropZone.appendChild(draggedImage); |
|
108 |
+ dropZone.appendChild(draggedTextElement); |
|
109 |
+ |
|
110 |
+ // 드래그한 요소 숨기기 |
|
111 |
+ this.draggedElement.style.display = 'none'; |
|
112 |
+ } else { |
|
113 |
+ // 정답이 아닌 경우 |
|
114 |
+ alert('오답입니다!'); // 오답 경고 메시지 |
|
115 |
+ } |
|
57 | 116 |
} |
58 |
- }, |
|
59 |
- methods: { |
|
60 |
- goToPage(page) { |
|
61 |
- this.$router.push({ name: page }); |
|
62 |
- } |
|
63 |
- }, |
|
64 |
- watch: { |
|
65 |
- |
|
66 |
- }, |
|
67 |
- computed: { |
|
68 |
- |
|
69 |
- }, |
|
70 |
- components: { |
|
71 |
- }, |
|
72 |
- mounted() { |
|
73 |
- |
|
117 |
+ |
|
118 |
+ this.draggedElement = null; // 드래그 상태 초기화 |
|
74 | 119 |
} |
120 |
+ }, |
|
121 |
+ mounted() { |
|
122 |
+ // 드래그 가능한 요소에 드래그 시작 및 종료 이벤트 추가 |
|
123 |
+ document.querySelectorAll('.draggable').forEach(button => { |
|
124 |
+ button.addEventListener('dragstart', this.handleDragStart); |
|
125 |
+ button.addEventListener('dragend', this.handleDragEnd); |
|
126 |
+ }); |
|
127 |
+ |
|
128 |
+ // 드롭 가능한 영역에 드래그 오버 및 드롭 이벤트 추가 |
|
129 |
+ document.querySelectorAll('.dropzone').forEach(zone => { |
|
130 |
+ zone.addEventListener('dragover', this.handleDragOver); |
|
131 |
+ zone.addEventListener('drop', this.handleDrop); |
|
132 |
+ }); |
|
75 | 133 |
} |
76 |
- </script> |
|
77 |
- <style scoped> |
|
134 |
+} |
|
135 |
+</script> |
|
136 |
+ |
|
137 |
+ |
|
138 |
+ |
|
139 |
+<style scoped> |
|
140 |
+.draggable { |
|
141 |
+ cursor: grab; |
|
142 |
+} |
|
143 |
+ |
|
144 |
+.draggable:active { |
|
145 |
+ cursor: grabbing; |
|
146 |
+} |
|
147 |
+ |
|
148 |
+ |
|
149 |
+ |
|
150 |
+.dropzone img { |
|
151 |
+ display: block; /* 이미지가 항상 보이도록 설정 */ |
|
152 |
+} |
|
153 |
+ |
|
78 | 154 |
</style>(No newline at end of file) |
--- client/views/pages/main/Chapter/Chapter2_9.vue
+++ client/views/pages/main/Chapter/Chapter2_9.vue
... | ... | @@ -1,5 +1,10 @@ |
1 | 1 |
<template> |
2 | 2 |
<div id="Chapter1_1" class="content-wrap"> |
3 |
+ <div style="margin: 30px 0px 50px"> |
|
4 |
+ <router-link to="/MyPlan.page"> |
|
5 |
+ <div class="logo mb25"><img src="../../../../resources/img/logo2.png" alt=""></div> |
|
6 |
+ </router-link> |
|
7 |
+ </div> |
|
3 | 8 |
<div class="title-box mb25 flex align-center mt40"> |
4 | 9 |
<span class="title mr40">1. Hello WORLD</span> |
5 | 10 |
<span class="subtitle">my name is dd</span> |
... | ... | @@ -24,9 +29,9 @@ |
24 | 29 |
</div> |
25 | 30 |
<div class="flex align-start"> |
26 | 31 |
<div> |
27 |
- <h3>sidewalk</h3> |
|
32 |
+ <h3>mountain</h3> |
|
28 | 33 |
<div class="flex align-center mt10"> |
29 |
- <span class="title1">보도</span> |
|
34 |
+ <span class="title1">산</span> |
|
30 | 35 |
</div> |
31 | 36 |
</div> |
32 | 37 |
</div> |
... | ... | @@ -37,9 +42,9 @@ |
37 | 42 |
</div> |
38 | 43 |
<div class="flex align-start"> |
39 | 44 |
<div> |
40 |
- <h3>sidewalk</h3> |
|
45 |
+ <h3>cat</h3> |
|
41 | 46 |
<div class="flex align-center mt10"> |
42 |
- <span class="title1">보도</span> |
|
47 |
+ <span class="title1">고양이</span> |
|
43 | 48 |
</div> |
44 | 49 |
</div> |
45 | 50 |
</div> |
... | ... | @@ -52,9 +57,9 @@ |
52 | 57 |
</div> |
53 | 58 |
<div class="flex align-start"> |
54 | 59 |
<div> |
55 |
- <h3>sidewalk</h3> |
|
60 |
+ <h3>watermelon</h3> |
|
56 | 61 |
<div class="flex align-center mt10"> |
57 |
- <span class="title1">보도</span> |
|
62 |
+ <span class="title1">수박</span> |
|
58 | 63 |
</div> |
59 | 64 |
</div> |
60 | 65 |
</div> |
... | ... | @@ -65,7 +70,7 @@ |
65 | 70 |
</div> |
66 | 71 |
<div class="flex align-start"> |
67 | 72 |
<div> |
68 |
- <h3>sidewalk</h3> |
|
73 |
+ <h3>america</h3> |
|
69 | 74 |
<div class="flex align-center mt10"> |
70 | 75 |
<span class="title1">보도</span> |
71 | 76 |
</div> |
--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
... | ... | @@ -8,6 +8,20 @@ |
8 | 8 |
<p class="title">{{ roadmapData[0].unit_nm }}</p> |
9 | 9 |
<p class="subtitle">{{ roadmapData[0].book_nm }}</p> |
10 | 10 |
</div> |
11 |
+ <!-- |
|
12 |
+ <div class="race-box"> |
|
13 |
+ <div class="rabbit-start"><img src="../../../resources/img/img09_s.png" alt=""></div> |
|
14 |
+ <div class="rcon flex justify-between mb5"> |
|
15 |
+ <div class="race-btn" v-for="roadmap in roadmapData" :key="roadmap.learning_id" @click="goToPage('Chapter7')"> |
|
16 |
+ <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="2"> |
|
17 |
+ <img :src="item.imgSrc1"> |
|
18 |
+ <img :src="item.imgSrc2" :style="{ display: item.isSecondImageVisible ? 'block' : 'none' }"> |
|
19 |
+ </button> |
|
20 |
+ <p>{{getNonNullColumn(roadmap)}}</p> |
|
21 |
+ </div> |
|
22 |
+ </div> |
|
23 |
+ </div> |
|
24 |
+ --> |
|
11 | 25 |
<div class="race-box"> |
12 | 26 |
<div class="rabbit-start"><img src="../../../resources/img/img09_s.png" alt=""></div> |
13 | 27 |
<div class="rcon flex justify-end mb5"> |
... | ... | @@ -123,8 +137,160 @@ |
123 | 137 |
</div> |
124 | 138 |
</div> |
125 | 139 |
</article> |
140 |
+ <!-- 팝업 --> |
|
141 |
+ <article class="popup-wrap" v-show="searchOpen"> |
|
142 |
+ <div class="popup-box "> |
|
143 |
+ <div class="flex mb10 justify-between"> |
|
144 |
+ <p class="popup-title">알림</p> |
|
145 |
+ <button type="button" class="popup-close-btn" @click="closeBtn2"> |
|
146 |
+ <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
|
147 |
+ </button> |
|
148 |
+ </div> |
|
149 |
+ </div> |
|
150 |
+ </article> |
|
126 | 151 |
</div> |
127 | 152 |
</div> |
153 |
+ |
|
154 |
+ <!-- 팝업 --> |
|
155 |
+ <div v-show="searchOpen2" class="popup-wrap"> |
|
156 |
+ <div class="popup-box"> |
|
157 |
+ <button type="button" class="popup-close-btn" style="position:absolute; top:10px; right: 10px;" |
|
158 |
+ @click="closeModal"> |
|
159 |
+ <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
|
160 |
+ </button> |
|
161 |
+ |
|
162 |
+ <div class="mb30 text-ct"> |
|
163 |
+ <p class="title1 mb20">1단원이 끝났습니다!</p> |
|
164 |
+ <p class="title1"><em class="yellow">기념사진</em>을 촬영하러 가요</p> |
|
165 |
+ </div> |
|
166 |
+ <div class="flex justify-center"> |
|
167 |
+ <button type="button" title="사진촬영" class="new-btn" @click="openCameraModal"> |
|
168 |
+ 사진 촬영 |
|
169 |
+ </button> |
|
170 |
+ </div> |
|
171 |
+ </div> |
|
172 |
+ </div> |
|
173 |
+ <!-- 카메라 모달 --> |
|
174 |
+ <article v-show="showCameraModal" class="popup-wrap"> |
|
175 |
+ <div class="popup-box" style="top: 500px; left:500px"> |
|
176 |
+ <div class="flex mb10 justify-between"> |
|
177 |
+ <p class="popup-title">사진 촬영</p> |
|
178 |
+ <button type="button" class="popup-close-btn" @click="closeModal"> |
|
179 |
+ <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
|
180 |
+ </button> |
|
181 |
+ </div> |
|
182 |
+ <div class="box"> |
|
183 |
+ <div style="width: 100%;"> |
|
184 |
+ <div id="container" ref="container"> |
|
185 |
+ <video v-if="!photoTaken" autoplay="true" ref="modalVideoElement" class="mirrored" |
|
186 |
+ @canplay="onVideoLoaded"></video> |
|
187 |
+ </div> |
|
188 |
+ </div> |
|
189 |
+ </div> |
|
190 |
+ <div class="flex justify-center mt20"> |
|
191 |
+ <button type="button" class="new-btn" v-if="!photoTaken" @click="capturePhoto" |
|
192 |
+ :disabled="!videoReady"> |
|
193 |
+ 사진 촬영 |
|
194 |
+ </button> |
|
195 |
+ </div> |
|
196 |
+ </div> |
|
197 |
+ </article> |
|
198 |
+ |
|
199 |
+ <!-- 사진 모달 --> |
|
200 |
+ <article v-show="showPhotoModal" class="popup-wrap"> |
|
201 |
+ <div class="popup-box" style="top: 500px; left: auto"> |
|
202 |
+ <div class="flex mb10 justify-between"> |
|
203 |
+ <p class="popup-title">사진 꾸미기</p> |
|
204 |
+ <button type="button" class="popup-close-btn" @click="closePhotoModal"> |
|
205 |
+ <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
|
206 |
+ </button> |
|
207 |
+ </div> |
|
208 |
+ <div class="flex justify-between align-center" style="gap: 40px;"> |
|
209 |
+ <div class="content" style="padding: 30px; min-width: 401px; min-height: 710px;"> |
|
210 |
+ <div class="tool"> |
|
211 |
+ <div class="flex justify-center mb20" style="gap: 20px;"> |
|
212 |
+ <button class="popTxt" style="width: 101px;" v-for="(item, index) in items_photo" |
|
213 |
+ :key="index" @click="updateContent(index)" |
|
214 |
+ :class="{ active: selectedIndex === index }"> |
|
215 |
+ <img :src="item.imgSrc1" style="display: block;"> |
|
216 |
+ <img :src="item.imgSrc2" v-if="selectedIndex === index" style="display: block;"> |
|
217 |
+ </button> |
|
218 |
+ </div> |
|
219 |
+ </div> |
|
220 |
+ |
|
221 |
+ <div class="stickers" v-show="!stickersVisible"> |
|
222 |
+ <div class="toolbar"> |
|
223 |
+ <label for="brushSize" style="font-size: 9px;">펜 굵기</label> |
|
224 |
+ <input type="color" v-model="color" /> |
|
225 |
+ <input type="range" id="brushSize" min="1" max="10" v-model="brushSize" |
|
226 |
+ @input="updateBrushSize" style="width: 100px; margin-left: 5px;" /> |
|
227 |
+ <button class="new-btn" style="font-size: 9px;" @click="setTool('draw')">펜</button> |
|
228 |
+ <button class="new-btn" style="font-size: 9px;" |
|
229 |
+ @click="setTool('eraser')">지우개</button> |
|
230 |
+ <button class="new-btn" style="font-size: 9px;" @click="clearAll">전체 |
|
231 |
+ 지우개</button> |
|
232 |
+ </div> |
|
233 |
+ </div> |
|
234 |
+ |
|
235 |
+ <div class="stickers" v-show="stickersVisible"> |
|
236 |
+ <button><img src="../../../resources/img/img146_75s.png" alt=""></button> |
|
237 |
+ <button><img src="../../../resources/img/img147_75s.png" alt=""></button> |
|
238 |
+ <button><img src="../../../resources/img/img148_75s.png" alt=""></button> |
|
239 |
+ <button><img src="../../../resources/img/img149_75s.png" alt=""></button> |
|
240 |
+ <button><img src="../../../resources/img/img150_75s.png" alt=""></button> |
|
241 |
+ <button><img src="../../../resources/img/img151_75s.png" alt=""></button> |
|
242 |
+ <button><img src="../../../resources/img/img152_75s.png" alt=""></button> |
|
243 |
+ <button><img src="../../../resources/img/img153_75s.png" alt=""></button> |
|
244 |
+ <button><img src="../../../resources/img/img154_75s.png" alt=""></button> |
|
245 |
+ <button><img src="../../../resources/img/img155_75s.png" alt=""></button> |
|
246 |
+ <button><img src="../../../resources/img/img156_75s.png" alt=""></button> |
|
247 |
+ <button><img src="../../../resources/img/img157_75s.png" alt=""></button> |
|
248 |
+ <button><img src="../../../resources/img/img158_75s.png" alt=""></button> |
|
249 |
+ </div> |
|
250 |
+ </div> |
|
251 |
+ <div> |
|
252 |
+ <div class="content" style="height: 549px; |
|
253 |
+ position: relative; |
|
254 |
+ width: 973px; |
|
255 |
+ display: flex; |
|
256 |
+ justify-content: center; |
|
257 |
+ align-items: center;"> |
|
258 |
+ <canvas ref="canvas" style="position: absolute;"></canvas> |
|
259 |
+ </div> |
|
260 |
+ <div class="btn-wrap flex justify-center mt40" style="gap: 40px;"> |
|
261 |
+ <button class="login-btn" @click="openCameraModal"> |
|
262 |
+ <img src="../../../resources/img/btn07_s.png" alt=""> |
|
263 |
+ <p>재촬영</p> |
|
264 |
+ </button> |
|
265 |
+ |
|
266 |
+ <button class="login-btn" type="submit" @click="goToPage('PhotoEdit')"> |
|
267 |
+ <img src="../../../resources/img/btn07_s.png" alt=""> |
|
268 |
+ <p>완성</p> |
|
269 |
+ </button> |
|
270 |
+ </div> |
|
271 |
+ </div> |
|
272 |
+ <div class="content" style="padding: 30px; min-width: 401px; min-height: 710px;"> |
|
273 |
+ <div class="mb20"> |
|
274 |
+ <p class="popup-title" style="font-size: 32px">랜덤 단어</p> |
|
275 |
+ </div> |
|
276 |
+ <div class="flex-column" style="gap: 10px;"> |
|
277 |
+ <button class="login-btn"><img src="../../../resources/img/img141_75s.png" alt=""> |
|
278 |
+ <p class="title">a</p> |
|
279 |
+ </button> |
|
280 |
+ <button class="login-btn"><img src="../../../resources/img/img152_75s_01.png" alt=""> |
|
281 |
+ <p class="title">a</p> |
|
282 |
+ </button> |
|
283 |
+ <button class="login-btn"><img src="../../../resources/img/img144_75s.png" alt=""> |
|
284 |
+ <p class="title" style="color: #fff;">a</p> |
|
285 |
+ </button> |
|
286 |
+ <button class="login-btn"><img src="../../../resources/img/img145_75s.png" alt=""> |
|
287 |
+ <p class="title mt20" style="color: #fff;">a</p> |
|
288 |
+ </button> |
|
289 |
+ </div> |
|
290 |
+ </div> |
|
291 |
+ </div> |
|
292 |
+ </div> |
|
293 |
+ </article> |
|
128 | 294 |
</div> |
129 | 295 |
</div> |
130 | 296 |
</template> |
... | ... | @@ -146,6 +312,16 @@ |
146 | 312 |
isSecondImageVisible: false |
147 | 313 |
}, |
148 | 314 |
], |
315 |
+ items_photo: [ |
|
316 |
+ { |
|
317 |
+ imgSrc1: 'client/resources/img/btn20_75s_normal.png', //펜 선택되지 않음 |
|
318 |
+ imgSrc2: 'client/resources/img/btn20_75s_click.png' //펜 선택됨 |
|
319 |
+ }, |
|
320 |
+ { |
|
321 |
+ imgSrc1: 'client/resources/img/btn21_75s_normal.png', //스티커 선택되지 않음 |
|
322 |
+ imgSrc2: 'client/resources/img/btn21_75s_click.png' //스티커 선택됨 |
|
323 |
+ }, |
|
324 |
+ ], |
|
149 | 325 |
mdiMagnify: mdiMagnify, |
150 | 326 |
mdiWindowClose: mdiWindowClose, |
151 | 327 |
mdiHeart: mdiHeart, |
... | ... | @@ -162,6 +338,24 @@ |
162 | 338 |
canvasHeight: 0, |
163 | 339 |
selectedIndex: 0, //툴 선택 여부 인덱스 |
164 | 340 |
stickersVisible: false, // 스티커 표시 여부 |
341 |
+ |
|
342 |
+ //사진 꾸미기 관련 변수 |
|
343 |
+ drawHistory: [], //도형 기록 |
|
344 |
+ tempLines: [], //펜 기록 |
|
345 |
+ stickers: [], //스티커 파일 기록 |
|
346 |
+ draggingStickerIndex: null, //스티커 드래그 |
|
347 |
+ activeStickerIndex: null, // 현재 활성화된 스티커의 인덱스 |
|
348 |
+ nextLineId: 0, //획 아이디 |
|
349 |
+ tool: 'draw', //툴 결정 |
|
350 |
+ color: '#000000', //펜 기본 색상 |
|
351 |
+ isDrawing: false, //그리는 중인지 판단하는 변수 |
|
352 |
+ brushSize: 5, // 초기 펜 굵기 |
|
353 |
+ startX: 0, |
|
354 |
+ startY: 0, |
|
355 |
+ canvasRect: { |
|
356 |
+ topLeft: { x: 0, y: 0 }, |
|
357 |
+ bottomRight: { x: 0, y: 0 } |
|
358 |
+ }, |
|
165 | 359 |
|
166 | 360 |
|
167 | 361 |
roadViewTF: false, |
... | ... | @@ -241,6 +435,7 @@ |
241 | 435 |
console.error("Error updating schedule:", error); |
242 | 436 |
}); |
243 | 437 |
}, |
438 |
+ |
|
244 | 439 |
fetchRoadmapData() { |
245 | 440 |
axios({ |
246 | 441 |
url: "/unitLearning/find.json", |
... | ... | @@ -261,8 +456,75 @@ |
261 | 456 |
console.error("Error fetching roadmap data:", error); |
262 | 457 |
}); |
263 | 458 |
}, |
459 |
+ toggleImage(index) { |
|
460 |
+ this.items[index].isSecondImageVisible = !this.items[index].isSecondImageVisible; |
|
461 |
+ }, |
|
462 |
+ toggleImageAndShowPopup(index, dataNum) { |
|
463 |
+ this.toggleImage(index); |
|
464 |
+ if (dataNum === '11') { |
|
465 |
+ this.searchOpen2 = true; |
|
466 |
+ } |
|
467 |
+ }, |
|
468 |
+ ShowPopup() { |
|
469 |
+ this.searchOpen2 = true; // 촬영 여부 묻는 모달창 열기 |
|
470 |
+ }, |
|
471 |
+ updateContent(index) { |
|
472 |
+ this.selectedIndex = index; |
|
473 |
+ |
|
474 |
+ // 선택된 버튼이 스티커 버튼(인덱스 1)인지 확인 |
|
475 |
+ if (index === 1) { |
|
476 |
+ this.stickersVisible = true; // 스티커 툴 보이기 |
|
477 |
+ } else { |
|
478 |
+ this.stickersVisible = false; // 스티커 툴 숨기기 |
|
479 |
+ } |
|
480 |
+ }, |
|
264 | 481 |
goToPage(page) { |
265 | 482 |
this.$router.push({ name: page }); |
483 |
+ }, |
|
484 |
+ openCameraModal() { |
|
485 |
+ this.closeModal(); |
|
486 |
+ this.closePhotoModal(); |
|
487 |
+ |
|
488 |
+ this.drawHistory = []; |
|
489 |
+ this.stickers = []; |
|
490 |
+ this.tempLines = []; |
|
491 |
+ this.videoReady = false; // 비디오 준비 상태 초기화 |
|
492 |
+ |
|
493 |
+ this.showCameraModal = true; |
|
494 |
+ navigator.mediaDevices.getUserMedia({ video: true }) |
|
495 |
+ .then(stream => { |
|
496 |
+ const modalVideo = this.$refs.modalVideoElement; |
|
497 |
+ modalVideo.srcObject = stream; |
|
498 |
+ this.stream = stream; |
|
499 |
+ modalVideo.addEventListener('loadedmetadata', this.adjustContainerSize); |
|
500 |
+ }) |
|
501 |
+ .catch(error => { |
|
502 |
+ console.log("error>>>>>>>>", error); |
|
503 |
+ }); |
|
504 |
+ }, |
|
505 |
+ closeModal() { //웹캠 및 모든 팝업 닫기 |
|
506 |
+ // this.showModal = false; |
|
507 |
+ this.searchOpen = false; |
|
508 |
+ this.searchOpen2 = false; |
|
509 |
+ this.showCameraModal = false; |
|
510 |
+ this.photoTaken = false; |
|
511 |
+ this.photo = null; |
|
512 |
+ this.showPhotoModal = false; |
|
513 |
+ |
|
514 |
+ //스트림 종료 |
|
515 |
+ if (this.stream) { |
|
516 |
+ let tracks = this.stream.getTracks(); |
|
517 |
+ tracks.forEach(track => track.stop()); |
|
518 |
+ this.stream = null; |
|
519 |
+ } |
|
520 |
+ }, |
|
521 |
+ closePhotoModal() { //사진꾸미기 팝업 닫기 |
|
522 |
+ this.showPhotoModal = false; |
|
523 |
+ this.closeModal(); |
|
524 |
+ }, |
|
525 |
+ onVideoLoaded() { |
|
526 |
+ this.videoReady = true; |
|
527 |
+ this.adjustContainerSize(); |
|
266 | 528 |
}, |
267 | 529 |
adjustContainerSize() { |
268 | 530 |
const video = this.$refs.modalVideoElement; |
... | ... | @@ -283,6 +545,296 @@ |
283 | 545 |
closeBtn() { |
284 | 546 |
this.searchOpen = false; |
285 | 547 |
}, |
548 |
+ capturePhoto() { |
|
549 |
+ // 사진 촬영 기능 구현 |
|
550 |
+ console.log("cam on"); |
|
551 |
+ |
|
552 |
+ if (!this.videoReady) return; // 비디오가 준비되지 않았으면 사진을 찍지 않음 |
|
553 |
+ |
|
554 |
+ const video = this.$refs.modalVideoElement; |
|
555 |
+ const canvas = document.createElement('canvas'); |
|
556 |
+ |
|
557 |
+ canvas.width = video.videoWidth; |
|
558 |
+ canvas.height = video.videoHeight; |
|
559 |
+ this.canvasWidth = video.videoWidth; |
|
560 |
+ this.canvasHeight = video.videoHeight; |
|
561 |
+ const context = canvas.getContext('2d'); |
|
562 |
+ context.translate(canvas.width, 0); |
|
563 |
+ context.scale(-1, 1); |
|
564 |
+ context.drawImage(video, 0, 0, canvas.width, canvas.height); |
|
565 |
+ this.photo = canvas.toDataURL('image/png'); |
|
566 |
+ this.photoTaken = true; |
|
567 |
+ this.showPhotoModal = true; |
|
568 |
+ console.log("PhotoModal open"); |
|
569 |
+ this.$nextTick(() => { |
|
570 |
+ console.log("canvas setup"); |
|
571 |
+ // console.log("Photo data>>>>", this.photo); |
|
572 |
+ this.setupCanvas(); |
|
573 |
+ }); |
|
574 |
+ |
|
575 |
+ }, |
|
576 |
+ setupCanvas() { |
|
577 |
+ const canvas = this.$refs.canvas; |
|
578 |
+ // const container = this.$refs.container; |
|
579 |
+ if (!canvas) { |
|
580 |
+ console.error("Canvas reference not found"); |
|
581 |
+ resolve(); |
|
582 |
+ return; |
|
583 |
+ } |
|
584 |
+ const context = canvas.getContext('2d'); |
|
585 |
+ if (!context) { |
|
586 |
+ console.error("Canvas context not found"); |
|
587 |
+ return; |
|
588 |
+ } |
|
589 |
+ const image = new Image(); |
|
590 |
+ image.src = this.photo; |
|
591 |
+ // console.log("Photo data>>>>", image.src); |
|
592 |
+ image.onload = () => { |
|
593 |
+ console.log("Image loaded successfully"); |
|
594 |
+ // this.canvasWidth = image.width; |
|
595 |
+ // this.canvasHeight = image.height; |
|
596 |
+ //이미지 크기가 캔버스와 안맞으면 이미지 불러오는데에 에러 남 |
|
597 |
+ // container.style.width = this.canvasWidth; |
|
598 |
+ // container.style.height = this.canvasHeight; |
|
599 |
+ |
|
600 |
+ canvas.width = this.canvasWidth; |
|
601 |
+ canvas.height = this.canvasHeight; |
|
602 |
+ |
|
603 |
+ const rect = canvas.getBoundingClientRect(); |
|
604 |
+ // 좌측 상단 좌표 |
|
605 |
+ const topLeft = { |
|
606 |
+ x: rect.left, |
|
607 |
+ y: rect.top |
|
608 |
+ }; |
|
609 |
+ |
|
610 |
+ // 우측 하단 좌표 |
|
611 |
+ const bottomRight = { |
|
612 |
+ x: rect.right, |
|
613 |
+ y: rect.bottom |
|
614 |
+ }; |
|
615 |
+ |
|
616 |
+ // 캔버스 크기 초기화 |
|
617 |
+ this.updateCanvasRect(); |
|
618 |
+ |
|
619 |
+ // 윈도우 리사이즈 이벤트 리스너 추가 |
|
620 |
+ window.addEventListener('resize', this.updateCanvasRect); |
|
621 |
+ |
|
622 |
+ // 클릭 이벤트 핸들러 추가 |
|
623 |
+ this.$refs.canvas.addEventListener('click', this.handleCanvasClick); |
|
624 |
+ |
|
625 |
+ |
|
626 |
+ // canvas.width = canvas.clientWidth; |
|
627 |
+ // canvas.height = canvas.clientHeight; |
|
628 |
+ // this.canvasWidth = canvas.clientWidth; |
|
629 |
+ // this.canvasHeight = canvas.clientHeight; |
|
630 |
+ |
|
631 |
+ context.clearRect(0, 0, canvas.width, canvas.height); // 이전 이미지 있으면 초기화 |
|
632 |
+ context.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight); |
|
633 |
+ this.addCanvasEventListeners(); //추가해야함 |
|
634 |
+ }; |
|
635 |
+ image.onerror = (error) => { |
|
636 |
+ console.error("Error loading image: ", error); |
|
637 |
+ }; |
|
638 |
+ }, |
|
639 |
+ |
|
640 |
+ addCanvasEventListeners() { |
|
641 |
+ const canvas = this.$refs.canvas; |
|
642 |
+ canvas.addEventListener('mousedown', this.onMouseDown); |
|
643 |
+ canvas.addEventListener('mouseup', this.onMouseUp); |
|
644 |
+ canvas.addEventListener('mousemove', this.onMouseMove); |
|
645 |
+ canvas.addEventListener('click', this.onCanvasClick); |
|
646 |
+ }, |
|
647 |
+ setTool(tool) { |
|
648 |
+ this.tool = tool; |
|
649 |
+ }, |
|
650 |
+ updateBrushSize() { |
|
651 |
+ // 펜 굵기 변경 로직 |
|
652 |
+ if (this.tool === 'draw') { |
|
653 |
+ this.setBrushSize(this.brushSize); |
|
654 |
+ } |
|
655 |
+ }, |
|
656 |
+ setBrushSize(size) { |
|
657 |
+ this.brushSize = size; |
|
658 |
+ const context = this.$refs.canvas.getContext('2d'); |
|
659 |
+ context.lineWidth = size; |
|
660 |
+ }, |
|
661 |
+ // 캔버스 크기 갱신 함수 |
|
662 |
+ updateCanvasRect() { |
|
663 |
+ const rect = this.$refs.canvas.getBoundingClientRect(); |
|
664 |
+ this.canvasRect = { |
|
665 |
+ topLeft: { x: rect.left, y: rect.top }, |
|
666 |
+ bottomRight: { x: rect.right, y: rect.bottom } |
|
667 |
+ }; |
|
668 |
+ console.log(">>>>>>>>>2222", rect.left); |
|
669 |
+ }, |
|
670 |
+ getCanvasPosition(event) { |
|
671 |
+ |
|
672 |
+ const rect = this.canvasRect; |
|
673 |
+ console.log(">>>>>>>>>", this.canvasRect); |
|
674 |
+ this.updateCanvasRect(); |
|
675 |
+ |
|
676 |
+ // 윈도우 리사이즈 이벤트 리스너 추가 |
|
677 |
+ window.addEventListener('resize', this.updateCanvasRect); |
|
678 |
+ |
|
679 |
+ // 클릭 이벤트 핸들러 추가 |
|
680 |
+ this.$refs.canvas.addEventListener('click', this.handleCanvasClick); |
|
681 |
+ |
|
682 |
+ // // 좌측 상단 좌표 |
|
683 |
+ // const topLeft = { |
|
684 |
+ // x: rect.left, |
|
685 |
+ // y: rect.top |
|
686 |
+ // }; |
|
687 |
+ |
|
688 |
+ // // 우측 하단 좌표 |
|
689 |
+ // const bottomRight = { |
|
690 |
+ // x: rect.right, |
|
691 |
+ // y: rect.bottom |
|
692 |
+ // }; |
|
693 |
+ |
|
694 |
+ // console.log(this.scrollLeft) |
|
695 |
+ |
|
696 |
+ const x = event.clientX - rect.topLeft.x |
|
697 |
+ const y = event.clientY - rect.topLeft.y |
|
698 |
+ |
|
699 |
+ |
|
700 |
+ console.log(`클릭한 좌표: x=${event.clientX}, y=${event.clientY}`); |
|
701 |
+ console.log(`계산베이스 좌표: x=${rect.topLeft.x}, y=${rect.topLeft.y}`); |
|
702 |
+ console.log(`계산베이스 좌표: x=${rect.topLeft.x}, y=${rect.topLeft.y}`); |
|
703 |
+ console.log(`계산된 좌표: x=${x}, y=${y}`); |
|
704 |
+ return { |
|
705 |
+ x, y |
|
706 |
+ }; |
|
707 |
+ }, |
|
708 |
+ onMouseDown(event) { |
|
709 |
+ |
|
710 |
+ // 캔버스 크기 초기화 |
|
711 |
+ this.updateCanvasRect(); |
|
712 |
+ |
|
713 |
+ // 윈도우 리사이즈 이벤트 리스너 추가 |
|
714 |
+ window.addEventListener('resize', this.updateCanvasRect); |
|
715 |
+ |
|
716 |
+ // 클릭 이벤트 핸들러 추가 |
|
717 |
+ this.$refs.canvas.addEventListener('click', this.handleCanvasClick); |
|
718 |
+ |
|
719 |
+ const { x, y } = this.getCanvasPosition(event); |
|
720 |
+ this.startX = x; |
|
721 |
+ this.startY = y; |
|
722 |
+ const context = this.$refs.canvas.getContext('2d'); |
|
723 |
+ context.strokeStyle = this.color; |
|
724 |
+ context.lineWidth = this.brushSize; // 브러시 크기 설정 |
|
725 |
+ if (this.tool === 'draw') { |
|
726 |
+ context.beginPath(); |
|
727 |
+ context.moveTo(this.startX, this.startY); |
|
728 |
+ this.nextLineId++; |
|
729 |
+ } |
|
730 |
+ this.isDrawing = true; |
|
731 |
+ }, |
|
732 |
+ onMouseUp(event) { |
|
733 |
+ if (!this.isDrawing) return; |
|
734 |
+ const { x, y } = this.getCanvasPosition(event); |
|
735 |
+ const context = this.$refs.canvas.getContext('2d'); |
|
736 |
+ context.strokeStyle = this.color; |
|
737 |
+ context.lineWidth = this.brushSize; // 브러시 크기 설정 |
|
738 |
+ if (this.tool === 'rectangle') { |
|
739 |
+ context.strokeRect(this.startX, this.startY, x - this.startX, y - this.startY); |
|
740 |
+ this.drawHistory.push({ type: 'rectangle', startX: this.startX, startY: this.startY, endX: x, endY: y, color: this.color }); |
|
741 |
+ } else if (this.tool === 'circle') { |
|
742 |
+ context.beginPath(); |
|
743 |
+ const radius = Math.sqrt(Math.pow((x - this.startX), 2) + Math.pow((y - this.startY), 2)); |
|
744 |
+ context.arc(this.startX, this.startY, radius, 0, 2 * Math.PI); |
|
745 |
+ context.stroke(); |
|
746 |
+ this.drawHistory.push({ type: 'circle', startX: this.startX, startY: this.startY, radius, color: this.color }); |
|
747 |
+ } else if (this.tool === 'draw') { |
|
748 |
+ context.lineTo(x, y); |
|
749 |
+ context.stroke(); |
|
750 |
+ this.tempLines.push({ id: this.nextLineId, startX: this.startX, startY: this.startY, endX: x, endY: y, color: this.color }); |
|
751 |
+ } |
|
752 |
+ this.isDrawing = false; |
|
753 |
+ }, |
|
754 |
+ onMouseMove(event) { |
|
755 |
+ if (!this.isDrawing || this.tool !== 'draw') return; |
|
756 |
+ const { x, y } = this.getCanvasPosition(event); |
|
757 |
+ const context = this.$refs.canvas.getContext('2d'); |
|
758 |
+ context.strokeStyle = this.color; |
|
759 |
+ context.lineWidth = this.brushSize; // 브러시 크기 설정 |
|
760 |
+ context.lineTo(x, y); |
|
761 |
+ context.stroke(); |
|
762 |
+ this.tempLines.push({ id: this.nextLineId, startX: this.startX, startY: this.startY, endX: x, endY: y, color: this.color }); |
|
763 |
+ this.startX = x; |
|
764 |
+ this.startY = y; |
|
765 |
+ }, |
|
766 |
+ onCanvasClick(event) { |
|
767 |
+ if (this.tool === 'eraser') { |
|
768 |
+ const { x, y } = this.getCanvasPosition(event); |
|
769 |
+ this.eraseDrawing(x, y); |
|
770 |
+ } |
|
771 |
+ }, |
|
772 |
+ eraseDrawing(x, y) { |
|
773 |
+ const eraserRadius = 10; |
|
774 |
+ this.drawHistory = this.drawHistory.filter(item => { |
|
775 |
+ if (item.type === 'rectangle') { |
|
776 |
+ return !(x >= item.startX && x <= item.endX && y >= item.startY && y <= item.endY); |
|
777 |
+ } else if (item.type === 'circle') { |
|
778 |
+ const distance = Math.sqrt(Math.pow((x - item.startX), 2) + Math.pow((y - item.startY), 2)); |
|
779 |
+ return !(distance <= item.radius); |
|
780 |
+ } |
|
781 |
+ }); |
|
782 |
+ const linesToDelete = this.tempLines.filter(line => { |
|
783 |
+ const distanceToLine = this.distanceToLineSegment(line.startX, line.startY, line.endX, line.endY, x, y); |
|
784 |
+ return distanceToLine <= 10; |
|
785 |
+ }).map(line => line.id); |
|
786 |
+ this.tempLines = this.tempLines.filter(line => !linesToDelete.includes(line.id)); |
|
787 |
+ this.redraw(); |
|
788 |
+ }, |
|
789 |
+ distanceToLineSegment(x1, y1, x2, y2, px, py) { |
|
790 |
+ const lengthSquared = Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2); |
|
791 |
+ if (lengthSquared === 0) return Math.sqrt(Math.pow(px - x1, 2) + Math.pow(py - y1, 2)); |
|
792 |
+ const t = Math.max(0, Math.min(1, ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / lengthSquared)); |
|
793 |
+ const projX = x1 + t * (x2 - x1); |
|
794 |
+ const projY = y1 + t * (y2 - y1); |
|
795 |
+ return Math.sqrt(Math.pow(px - projX, 2) + Math.pow(py - projY, 2)); |
|
796 |
+ }, |
|
797 |
+ clearAll() { |
|
798 |
+ this.drawHistory = []; |
|
799 |
+ this.stickers = []; |
|
800 |
+ this.tempLines = []; |
|
801 |
+ this.redraw(); |
|
802 |
+ }, |
|
803 |
+ redraw() { |
|
804 |
+ const canvas = this.$refs.canvas; |
|
805 |
+ const context = canvas.getContext('2d'); |
|
806 |
+ const image = new Image(); |
|
807 |
+ image.src = this.photo; |
|
808 |
+ image.onload = () => { |
|
809 |
+ context.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
|
810 |
+ context.drawImage(image, 0, 0, this.canvasWidth, this.canvasHeight); |
|
811 |
+ this.drawHistory.forEach(item => { |
|
812 |
+ context.strokeStyle = item.color; |
|
813 |
+ if (item.type === 'draw') { |
|
814 |
+ context.beginPath(); |
|
815 |
+ context.moveTo(item.startX, item.startY); |
|
816 |
+ context.lineTo(item.endX, item.endY); |
|
817 |
+ context.stroke(); |
|
818 |
+ } else if (item.type === 'rectangle') { |
|
819 |
+ context.strokeRect(item.startX, item.startY, item.endX - item.startX, item.endY - item.startY); |
|
820 |
+ } else if (item.type === 'circle') { |
|
821 |
+ context.beginPath(); |
|
822 |
+ context.arc(item.startX, item.startY, item.radius, 0, 2 * Math.PI); |
|
823 |
+ context.stroke(); |
|
824 |
+ } |
|
825 |
+ }); |
|
826 |
+ this.tempLines.forEach(line => { |
|
827 |
+ context.strokeStyle = line.color; |
|
828 |
+ context.beginPath(); |
|
829 |
+ context.moveTo(line.startX, line.startY); |
|
830 |
+ context.lineTo(line.endX, line.endY); |
|
831 |
+ context.stroke(); |
|
832 |
+ }); |
|
833 |
+ this.stickers.forEach((sticker, index) => { |
|
834 |
+ context.drawImage(sticker.img, sticker.x, sticker.y, sticker.width, sticker.height); |
|
835 |
+ }); |
|
836 |
+ }; |
|
837 |
+ }, |
|
286 | 838 |
getNonNullColumn(item) { |
287 | 839 |
if (item.prblm_id !== null) return '문제'; |
288 | 840 |
if (item.wd_book_id !== null) return '단어장'; |
--- client/views/pages/main/MyPlan2.vue
+++ client/views/pages/main/MyPlan2.vue
... | ... | @@ -24,11 +24,11 @@ |
24 | 24 |
<td><input type="checkbox" class="ui-checkbox mr10" v-model="book.isSelected"></td> |
25 | 25 |
<td><img src="../../../resources/img/img214_19s.png" alt=""></td> |
26 | 26 |
<td class="text-lf"> |
27 |
- <p class="title1">{{ book.book_nm }}</p> |
|
28 |
- <p class="title2">grade 3</p> |
|
27 |
+ <p class="title1">{{ book.bookName }}</p> |
|
28 |
+ <p class="title2">{{ book.unitName }}</p> |
|
29 | 29 |
</td> |
30 | 30 |
<td> <button type="button" title="확인" class="new-btn" |
31 |
- @click="buttonSearch(book.book_nm, book.book_id)"> |
|
31 |
+ @click="buttonSearch(book.bookName, book.bookId, book.unitId)"> |
|
32 | 32 |
시간입력 |
33 | 33 |
</button></td> |
34 | 34 |
</tr> |
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 |
<p class="title1">{{ book.scheduleTime }}</p> |
55 | 55 |
</div> |
56 | 56 |
<div class="title-box mb10"> <span class="title">{{ book.bookNm }}</span></div> |
57 |
- <p class="title2">wirte a</p> |
|
57 |
+ <p class="title2">{{ book.unitNm }}</p> |
|
58 | 58 |
</div> |
59 | 59 |
<div class=""> <img src="../../../resources/img/img214_19s.png" alt=""></div> |
60 | 60 |
</div> |
... | ... | @@ -159,9 +159,10 @@ |
159 | 159 |
closeModal() { |
160 | 160 |
this.showModal = false; |
161 | 161 |
}, |
162 |
- buttonSearch(book_nm, book_id) { |
|
162 |
+ buttonSearch(book_nm, book_id, unit_id) { |
|
163 | 163 |
this.nowID = book_id |
164 | 164 |
this.nowName = book_nm |
165 |
+ this.nowunitID = unit_id |
|
165 | 166 |
this.searchOpen = true; |
166 | 167 |
}, |
167 | 168 |
closeBtn() { |
... | ... | @@ -173,14 +174,15 @@ |
173 | 174 |
alert('교재를 선택해 주세요.'); |
174 | 175 |
} else { |
175 | 176 |
if (this.checkedItems.length === 1) { |
176 |
- if (this.unitList.find(item => item === this.checkedItems[0])) { |
|
177 |
+ if (this.unitList.find(item => item === this.checkedItems[0].value)) { |
|
177 | 178 |
alert('이미 지정된 시간입니다.'); |
178 | 179 |
} else { |
179 | 180 |
this.addToNewDataArray(this.checkedItems[0]); |
180 | 181 |
this.searchOpen = false; |
181 | 182 |
this.nowID = "" |
183 |
+ this.nowunitID = "" |
|
182 | 184 |
this.nowName = "" |
183 |
- this.unitList.push(this.checkedItems[0]) |
|
185 |
+ this.unitList.push(this.checkedItems[0].value) |
|
184 | 186 |
this.checkedItems = [] |
185 | 187 |
} |
186 | 188 |
} else if (this.checkedItems.length > 1) { |
... | ... | @@ -199,17 +201,18 @@ |
199 | 201 |
scheduleTime: selectedTime.time, |
200 | 202 |
scheduleUnit: selectedTime.value, |
201 | 203 |
bookId: this.nowID, |
204 |
+ unitId: this.nowunitID, |
|
202 | 205 |
stdId: "2" |
203 | 206 |
}; |
204 | 207 |
this.newDataArray.push(newEntry); |
205 | 208 |
}, |
206 | 209 |
async insertSchedule() { |
207 |
- |
|
208 | 210 |
this.newDataArray = this.DataArray.map(item => ({ |
209 | 211 |
scheduleUnit: item.scheduleUnit, |
210 | 212 |
bookId: item.bookId, |
213 |
+ unitId: item.unitId, |
|
211 | 214 |
stdId: item.stdId |
212 |
- })); |
|
215 |
+ })); |
|
213 | 216 |
try { |
214 | 217 |
for (let data of this.newDataArray) { |
215 | 218 |
await axios.post('/schedule/insertSchedule.json', data); |
... | ... | @@ -225,26 +228,7 @@ |
225 | 228 |
return a.scheduleUnit - b.scheduleUnit; |
226 | 229 |
}); |
227 | 230 |
|
228 |
- this.DataArray = sortedArray; |
|
229 |
- }, |
|
230 |
- fetchBooks() { |
|
231 |
- axios({ |
|
232 |
- url: "/book/findAll.json", |
|
233 |
- method: "post", |
|
234 |
- headers: { |
|
235 |
- "Content-Type": "application/json; charset=UTF-8", |
|
236 |
- }, |
|
237 |
- }) |
|
238 |
- .then(response => { |
|
239 |
- this.books = response.data.map(book => ({ |
|
240 |
- ...book, |
|
241 |
- isSelected: false |
|
242 |
- })); |
|
243 |
- }) |
|
244 |
- .catch(error => { |
|
245 |
- console.error("fetchBooks - error: ", error); |
|
246 |
- alert("교재 목록을 불러오는 중 오류가 발생했습니다."); |
|
247 |
- }); |
|
231 |
+ this.DataArray = sortedArray; |
|
248 | 232 |
}, |
249 | 233 |
searchBook() { |
250 | 234 |
this.books = "" |
... | ... | @@ -263,6 +247,38 @@ |
263 | 247 |
console.error("fetchUnits - error:", error); |
264 | 248 |
alert("단원 목록을 불러오는 중 오류가 발생했습니다."); |
265 | 249 |
}); |
250 |
+ }, |
|
251 |
+ fetchUnits() { |
|
252 |
+ axios.post("unit/findAll.json", { |
|
253 |
+ headers: { |
|
254 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
255 |
+ } |
|
256 |
+ }) |
|
257 |
+ .then(response => { |
|
258 |
+ this.books = response.data.map(book => ({ |
|
259 |
+ ...book, |
|
260 |
+ isSelected: false |
|
261 |
+ })); |
|
262 |
+ this.searchUnit() |
|
263 |
+ }) |
|
264 |
+ .catch(error => { |
|
265 |
+ console.error("fetchBooks - error: ", error); |
|
266 |
+ alert("교재 목록을 불러오는 중 오류가 발생했습니다."); |
|
267 |
+ }); |
|
268 |
+ }, searchUnit() { |
|
269 |
+ axios.post("schedule/selectSchedule.json", {stdId:"2"}, { |
|
270 |
+ headers: { |
|
271 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
272 |
+ } |
|
273 |
+ }) |
|
274 |
+ .then(response => { |
|
275 |
+ const units = response.data.map(item => item.schdl_unit); |
|
276 |
+ this.unitList.push(...units); |
|
277 |
+ }) |
|
278 |
+ .catch(error => { |
|
279 |
+ console.error("searchUnit - error: ", error); |
|
280 |
+ alert("교재 목록을 불러오는 중 오류가 발생했습니다."); |
|
281 |
+ }); |
|
266 | 282 |
} |
267 | 283 |
}, |
268 | 284 |
watch: { |
... | ... | @@ -276,7 +292,7 @@ |
276 | 292 |
}, |
277 | 293 |
mounted() { |
278 | 294 |
console.log('Main2 mounted'); |
279 |
- this.fetchBooks(); |
|
295 |
+ this.fetchUnits(); |
|
280 | 296 |
} |
281 | 297 |
} |
282 | 298 |
</script> |
--- client/views/pages/main/PreviewNote.vue
+++ client/views/pages/main/PreviewNote.vue
... | ... | @@ -6,20 +6,14 @@ |
6 | 6 |
<p class="title">단원</p> |
7 | 7 |
<div class="row-bd"></div> |
8 | 8 |
<div> |
9 |
- <p class="title mr40 mb10">1. Hello WORLD</p> |
|
9 |
+ <p class="title mr40 mb10">{{ unitData.unit_nm }}</p> |
|
10 | 10 |
<p class="subtitle">my name is dd</p> |
11 | 11 |
</div> |
12 | 12 |
</div> |
13 |
- <!-- <button type="button" title="바로가기" class="yellow-btn" @click="goToPage('MyPlan2')"> |
|
14 |
- 바로가기 |
|
15 |
- </button> --> |
|
16 | 13 |
</div> |
17 | 14 |
</div> |
18 | 15 |
<div class="title-box flex justify-between mb20 mt30"> |
19 | 16 |
<p class="title">오답노트</p> |
20 |
- <!-- <select name="" id=""> |
|
21 |
- <option value="">A반</option> |
|
22 |
- </select> --> |
|
23 | 17 |
</div> |
24 | 18 |
<div class="wrap" style="border-radius: 0;"> |
25 | 19 |
|
... | ... | @@ -30,27 +24,17 @@ |
30 | 24 |
<col style="width: 70%;"> |
31 | 25 |
<col style="width: 15%;"> |
32 | 26 |
</colgroup> |
33 |
- <tr> |
|
34 |
- |
|
27 |
+ <tr v-for="note in wrongAnswerNotes" :key="note.prblmLogId"> |
|
35 | 28 |
<td><img src="../../../resources/img/img214_19s.png" alt=""></td> |
36 | 29 |
<td class="text-lf"> |
37 |
- <p class="title1">중간평가</p> |
|
38 |
- <p class="title2">wirte a</p> |
|
30 |
+ <p class="title1">{{ note.evalType }}</p> |
|
31 |
+ <p class="title2">{{ note.prblmExpln }}</p> |
|
39 | 32 |
</td> |
40 |
- <td> <button type="button" title="" class="new-btn" @click="buttonSearch"> |
|
33 |
+ <td> |
|
34 |
+ <button type="button" title="" class="new-btn" @click="viewDetail(note.prblmId)"> |
|
41 | 35 |
View Detail |
42 |
- </button></td> |
|
43 |
- </tr> |
|
44 |
- <tr> |
|
45 |
- |
|
46 |
- <td><img src="../../../resources/img/img214_19s.png" alt=""></td> |
|
47 |
- <td class="text-lf"> |
|
48 |
- <p class="title1">중간평가</p> |
|
49 |
- <p class="title2">wirte a</p> |
|
36 |
+ </button> |
|
50 | 37 |
</td> |
51 |
- <td> <button type="button" title="" class="new-btn" @click="buttonSearch"> |
|
52 |
- View Detail |
|
53 |
- </button></td> |
|
54 | 38 |
</tr> |
55 | 39 |
</table> |
56 | 40 |
<div class="flex justify-end"> |
... | ... | @@ -64,57 +48,55 @@ |
64 | 48 |
</template> |
65 | 49 |
|
66 | 50 |
<script> |
51 |
+import axios from 'axios'; |
|
52 |
+ |
|
67 | 53 |
export default { |
68 | 54 |
data() { |
69 | 55 |
return { |
70 |
- timer: '00', |
|
71 |
- showButton1: false, |
|
72 |
- showButton2: false, |
|
73 |
- showButton3: false, |
|
74 |
- showButton4: false, |
|
56 |
+ currentStdId: "1", // 임시 학생 아이디 |
|
57 |
+ currentUnitId: "1", // 임시 유닛 아이디 |
|
58 |
+ wrongAnswerNotes: [], // 오답 노트 목록 데이터 |
|
59 |
+ unitData: {}, |
|
75 | 60 |
} |
76 | 61 |
}, |
77 | 62 |
methods: { |
78 |
- goToPage(page) { |
|
79 |
- this.$router.push({ name: page }); |
|
63 |
+ |
|
64 |
+ // 오답노트 상세 보기 버튼 클릭 |
|
65 |
+ viewDetail(prblmId) { |
|
66 |
+ // 상세 보기 페이지로 이동하는 로직을 추가 할 예정 |
|
67 |
+ console.log('링크될 문제 ID:', prblmId); |
|
80 | 68 |
}, |
81 |
- handleDrag(dragNumber) { |
|
82 |
- // Drag 버튼 숨기기 |
|
83 |
- // 여기서는 상태 관리를 통해 버튼을 제어합니다. |
|
84 |
- if (dragNumber === 1) { |
|
85 |
- this.showButton1 = false; |
|
86 |
- } else if (dragNumber === 2) { |
|
87 |
- this.showButton2 = false; |
|
88 |
- } else if (dragNumber === 3) { |
|
89 |
- this.showButton3 = false; |
|
90 |
- } |
|
91 |
- }, |
|
92 |
- showButton(dropNumber) { |
|
93 |
- // Drop 영역의 이미지 클릭 이벤트 핸들러 설정 |
|
94 |
- // 여기서는 상태 관리를 통해 버튼을 보이게 합니다. |
|
95 |
- if (dropNumber === 1) { |
|
96 |
- this.showButton1 = true; |
|
97 |
- } else if (dropNumber === 2) { |
|
98 |
- this.showButton2 = true; |
|
99 |
- } else if (dropNumber === 3) { |
|
100 |
- this.showButton3 = true; |
|
101 |
- } else if (dropNumber === 4) { |
|
102 |
- this.showButton4 = true; |
|
103 |
- } |
|
104 |
- }, |
|
105 |
- startTimer() { |
|
106 |
- if (this.intervalId) { |
|
107 |
- clearInterval(this.intervalId); |
|
108 |
- } |
|
109 |
- this.timer = 5; |
|
110 |
- this.intervalId = setInterval(() => { |
|
111 |
- if (this.timer > 0) { |
|
112 |
- this.timer--; |
|
113 |
- } else { |
|
114 |
- clearInterval(this.intervalId); |
|
69 |
+ |
|
70 |
+ fetchUnitDetail() { |
|
71 |
+ axios.post('/unit/unitDetail.json', { |
|
72 |
+ unitId: this.currentUnitId |
|
73 |
+ }) |
|
74 |
+ .then(response => { |
|
75 |
+ console.log(response.data[0]); |
|
76 |
+ if (response.data.length > 0) { |
|
77 |
+ this.unitData = response.data[0]; |
|
115 | 78 |
} |
116 |
- }, 1000); |
|
79 |
+ }) |
|
80 |
+ .catch(error => { |
|
81 |
+ console.error('단원 정보를 불러오는 중 오류 발생:', error); |
|
82 |
+ }) |
|
83 |
+ }, |
|
84 |
+ |
|
85 |
+ // 오답노트 목록을 가져오는 API 호출 |
|
86 |
+ fetchWrongAnswerNotes() { |
|
87 |
+ axios.post('/problemLog/getPreviewNoteList.json', { |
|
88 |
+ stdId: this.currentStdId, |
|
89 |
+ unitId: this.currentUnitId |
|
90 |
+ }) |
|
91 |
+ .then(response => { |
|
92 |
+ console.log(response.data); |
|
93 |
+ this.wrongAnswerNotes = response.data; |
|
94 |
+ }) |
|
95 |
+ .catch(error => { |
|
96 |
+ console.error('오답노트를 불러오는 중 오류 발생:', error); |
|
97 |
+ }); |
|
117 | 98 |
} |
99 |
+ |
|
118 | 100 |
}, |
119 | 101 |
watch: { |
120 | 102 |
|
... | ... | @@ -125,7 +107,9 @@ |
125 | 107 |
components: { |
126 | 108 |
}, |
127 | 109 |
mounted() { |
128 |
- |
|
110 |
+ console.log('PreviewNote mounted'); |
|
111 |
+ this.fetchUnitDetail(); |
|
112 |
+ this.fetchWrongAnswerNotes(); |
|
129 | 113 |
} |
130 | 114 |
} |
131 | 115 |
</script> |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?