
--- client/resources/css/reset.css
+++ client/resources/css/reset.css
... | ... | @@ -80,20 +80,20 @@ |
80 | 80 |
|
81 | 81 |
} |
82 | 82 |
html, |
83 |
-body{height: 100%; background-color: #eaedf4;} |
|
83 |
+body{ background-color: #eaedf4;} |
|
84 | 84 |
body{position:relative;text-align: left; overflow-x: hidden; width: 1920px;} |
85 | 85 |
::-webkit-scrollbar {width: 10px; height: 10px;} |
86 | 86 |
::-webkit-scrollbar-track {border-radius: 5px;background-color: #EAEDF4;} |
87 | 87 |
::-webkit-scrollbar-thumb { border-radius: 5px; background-color: #FFBA08;} |
88 | 88 |
#root, #app{ |
89 |
- height: 100%; |
|
89 |
+ /* height: 100%; */ |
|
90 | 90 |
} |
91 | 91 |
input, select, span,p, label { |
92 | 92 |
font-size: 16px; |
93 | 93 |
} |
94 | 94 |
input::placeholder{color: #8C8E92;} |
95 | 95 |
input[type="text"]{ padding:10px 20px; width: 100%; } |
96 |
- |
|
96 |
+input#file-upload-button{padding: 10px ;} |
|
97 | 97 |
|
98 | 98 |
button{ |
99 | 99 |
border: none; |
... | ... | @@ -112,4 +112,24 @@ |
112 | 112 |
border: 0;} |
113 | 113 |
thead{background-color: #eaedf4;} |
114 | 114 |
tbody tr{border-bottom: #eaedf4 1px solid; cursor: pointer;} |
115 |
-td{padding: 10px ; text-align: center;}(파일 끝에 줄바꿈 문자 없음) |
|
115 |
+td{padding: 10px ; text-align: center;} |
|
116 |
+ |
|
117 |
+/* .btn-upload { |
|
118 |
+ width: 100px; |
|
119 |
+ height: 40px; |
|
120 |
+ background: #f0f0f0; |
|
121 |
+ border: 1px solid rgb(77,77,77); |
|
122 |
+ font-weight: 500; |
|
123 |
+ cursor: pointer; |
|
124 |
+ display: flex; |
|
125 |
+ align-items: center; |
|
126 |
+ justify-content: center; |
|
127 |
+ &:hover { |
|
128 |
+ background: rgb(77,77,77); |
|
129 |
+ color: #fff; |
|
130 |
+ } |
|
131 |
+ } |
|
132 |
+ |
|
133 |
+ #file { |
|
134 |
+ display: none; |
|
135 |
+ } */(파일 끝에 줄바꿈 문자 없음) |
--- client/resources/css/style.css
+++ client/resources/css/style.css
... | ... | @@ -277,7 +277,7 @@ |
277 | 277 |
background-image: url('../img/img199_12p.png'); |
278 | 278 |
width: 367px; |
279 | 279 |
height: 182px; |
280 |
- padding: 20px 46px 20px 31px; |
|
280 |
+ padding: 20px 50px 20px 40px; |
|
281 | 281 |
color: #fff; |
282 | 282 |
} |
283 | 283 |
.mypage .textbook{font-family: 'ONEMobilePOPOTF';} |
... | ... | @@ -285,15 +285,17 @@ |
285 | 285 |
.mypage .textbook .text {border-radius: 12px 12px 0px 0px; height: 68px; |
286 | 286 |
} |
287 | 287 |
.mypage .textbook .box{height: 199px; text-align: center; padding: 10px;} |
288 |
-.mypage .textbook:nth-child(1) .text{background-color: #DB2B39;} |
|
288 |
+.mypage .book-red .text{background-color: #DB2B39;} |
|
289 | 289 |
/* .mypage .textbook:nth-child(2) .text */ |
290 |
-.mypage .textbook:nth-child(3) .text{background-color:#2D7DD2;} |
|
291 |
-.mypage .textbook:nth-child(4) .text{ background-color: #3066BE;} |
|
292 |
-.mypage .textbook .box{height: 199px; text-align: center; padding: 10px;} |
|
293 |
-.mypage .textbook:nth-child(1){border: #DB2B39 solid 6px;} |
|
290 |
+.mypage .book-blue .text{background-color:#2D7DD2;} |
|
291 |
+.mypage .book-navy .text{ background-color: #3066BE;} |
|
292 |
+.mypage .book-gray > .text{ background-color: #F7F8F9;} |
|
293 |
+.mypage .textbook .box{ text-align: center; padding: 10px;} |
|
294 |
+.mypage .book-red{border: #DB2B39 solid 6px;} |
|
294 | 295 |
/* .mypage .textbook:nth-child(2) .text */ |
295 |
-.mypage .textbook:nth-child(3){border:#2D7DD2 solid 6px;} |
|
296 |
-.mypage .textbook:nth-child(4){ border: #3066BE solid 6px;} |
|
296 |
+.mypage .book-blue{border:#2D7DD2 solid 6px;} |
|
297 |
+.mypage .book-navy{ border: #3066BE solid 6px;} |
|
298 |
+.mypage .book-gray{ border: #8C8E92 solid 1px;} |
|
297 | 299 |
.mypage em.orange { |
298 | 300 |
color: #FFBA08; |
299 | 301 |
} |
... | ... | @@ -439,10 +441,15 @@ |
439 | 441 |
width: 1063px; |
440 | 442 |
} |
441 | 443 |
|
442 |
-.rabbit { |
|
444 |
+.rabbit-start { |
|
443 | 445 |
position: absolute; |
444 | 446 |
top: -45px; |
445 | 447 |
left: 393px; |
448 |
+} |
|
449 |
+.rabbit-end { |
|
450 |
+ position: absolute; |
|
451 |
+ bottom: 24px; |
|
452 |
+ right: 40px; |
|
446 | 453 |
} |
447 | 454 |
|
448 | 455 |
.rabbit img { |
... | ... | @@ -468,6 +475,13 @@ |
468 | 475 |
.race-btn p.long { |
469 | 476 |
width: fit-content; |
470 | 477 |
} |
478 |
+/* .popup-yellow{ |
|
479 |
+ background-image: url('../img/img139_72s.png'); |
|
480 |
+ min-width: 439px !important; |
|
481 |
+ min-height: 244px !important; |
|
482 |
+ background-color: transparent !important; |
|
483 |
+ border: 0 !important; |
|
484 |
+} */ |
|
471 | 485 |
/* 사진촬영 */ |
472 | 486 |
.camera{background-color: #000;} |
473 | 487 |
.camera .header{height: 110px; background-color: #eaedf4; padding: 0 60px;} |
... | ... | @@ -498,6 +512,20 @@ |
498 | 512 |
.complete-wrap img{width: inherit;} |
499 | 513 |
.complete-wrap .photo{cursor: pointer; width: 200px; height: 130px; } |
500 | 514 |
/* 챕터 */ |
515 |
+.time-hint{ |
|
516 |
+ position: absolute; |
|
517 |
+ top: 50px; |
|
518 |
+ right: 50px; |
|
519 |
+ text-align: center; |
|
520 |
+} |
|
521 |
+.hint-btn{ |
|
522 |
+ background-image: url('../img/btn01.png'); |
|
523 |
+ width: 110px; |
|
524 |
+ height: 45px; |
|
525 |
+ padding: 5px 20px; |
|
526 |
+ font-size: 28px; |
|
527 |
+ font-family: 'ONEMobilePOP'; |
|
528 |
+} |
|
501 | 529 |
.content-wrap { |
502 | 530 |
margin: 90px 60px 0 60px; |
503 | 531 |
|
... | ... | @@ -739,9 +767,6 @@ |
739 | 767 |
width: 560px; |
740 | 768 |
} |
741 | 769 |
.time-bg{ |
742 |
- position: absolute; |
|
743 |
- top: 50px; |
|
744 |
- right: 50px; |
|
745 | 770 |
text-align: center; |
746 | 771 |
font-family: 'neodgm'; background-image: url('../img/img55_s.png'); width: 110px; height: 128px;} |
747 | 772 |
.time-bg > div{position: relative;} |
... | ... | @@ -828,7 +853,7 @@ |
828 | 853 |
.side_t{ |
829 | 854 |
background-color: #fff; |
830 | 855 |
width: 360px; |
831 |
- height: 100%; |
|
856 |
+ /* height: 100%; */ |
|
832 | 857 |
padding: 25px 40px; |
833 | 858 |
} |
834 | 859 |
|
... | ... | @@ -847,7 +872,7 @@ |
847 | 872 |
to { opacity:1; transform:translate3d(0, 0, 0); } |
848 | 873 |
} |
849 | 874 |
|
850 |
-select{min-width: 128px; border-radius: 5px; padding: 10px 20px; font-size: 18px;} |
|
875 |
+select{min-width: 128px; border-radius: 5px; padding: 10px 20px; font-size: 18px; } |
|
851 | 876 |
select option{font-size: 20px; font-weight: bold;} |
852 | 877 |
|
853 | 878 |
|
... | ... | @@ -860,7 +885,7 @@ |
860 | 885 |
.class .member::before{content: ""; background-image: url('../img/img171_82t.png'); width: 20px; height: 22px; position: absolute; left: -28px;} |
861 | 886 |
.class .btnGroup, .textbook .text .btnGroup {width: initial;} |
862 | 887 |
.class button, .textbook button{font-size: 19px; font-family: 'Pretendard-Regular';} |
863 |
-.textbook{width: 300px; border: #FFBA08 solid 6px; border-radius: 20px; font-size: 19px;} |
|
888 |
+.textbook{width: 100%; border: #FFBA08 solid 6px; border-radius: 20px; font-size: 19px;} |
|
864 | 889 |
.textbook-add{width: 300px; height: 354px; background-color: #F8F9FB; border: #75767A solid 2px; border-radius: 20px; font-size: 19px;} |
865 | 890 |
.textbook .box{height: 250px;} |
866 | 891 |
.textbook .text{height: 97px; background-color: #FFBA08; border-radius: 0px 0px 12px 12px; padding: 20px;} |
... | ... | @@ -915,7 +940,7 @@ |
915 | 940 |
font-family: 'Pretendard-Bold'; |
916 | 941 |
} |
917 | 942 |
.new-btn{ |
918 |
- padding: 5px 20px; |
|
943 |
+ padding: 10px 30px; |
|
919 | 944 |
font-size: 20px; |
920 | 945 |
font-family: 'Pretendard-Bold'; |
921 | 946 |
border-radius: 5px; |
... | ... | @@ -1013,7 +1038,7 @@ |
1013 | 1038 |
border: #FFBA08 solid 2px; |
1014 | 1039 |
cursor: pointer; |
1015 | 1040 |
} |
1016 |
-.bookmanage-btn:hover{background-color: #FFF3D7;} |
|
1041 |
+ |
|
1017 | 1042 |
.hidden-tr { |
1018 | 1043 |
display: none; |
1019 | 1044 |
} |
... | ... | @@ -1025,4 +1050,41 @@ |
1025 | 1050 |
background-color: #fff; |
1026 | 1051 |
|
1027 | 1052 |
} |
1053 |
+ |
|
1054 |
+/* 로드맵 */ |
|
1055 |
+.mypage .big{width: 48%; height: 100%;} |
|
1056 |
+.mypage .big > .text { |
|
1057 |
+ border-radius: 19px 19px 0px 0px; border-bottom: 1px solid #8C8E92;} |
|
1058 |
+ .mypage .big > .box{ |
|
1059 |
+ overflow-x: auto; |
|
1060 |
+ margin: 4rem 3rem; |
|
1061 |
+ height: 100%; |
|
1062 |
+ max-height: calc(100% - 16rem); |
|
1063 |
+ } |
|
1064 |
+ .dropbox{ |
|
1065 |
+ color: #8C8E92; |
|
1066 |
+ border: #8C8E92 dotted 1px; |
|
1067 |
+ background-color: #EAEDF4; |
|
1068 |
+ border-radius: 20px; |
|
1069 |
+ min-height: 20rem; |
|
1070 |
+ } |
|
1071 |
+ .dropbox p{line-height: 20rem;} |
|
1072 |
+ |
|
1073 |
+ |
|
1074 |
+ /* 단원 버튼 */ |
|
1075 |
+ .unit-pagination button { |
|
1076 |
+ font-size: 2rem; |
|
1077 |
+ font-family: 'Pretendard-Regular'; |
|
1078 |
+ padding: 5px 30px; |
|
1079 |
+ border: #c6c6c6 3px solid; |
|
1080 |
+ border-radius: 5px; |
|
1081 |
+ color: #331600; |
|
1082 |
+ background-color: #EAEDF4 |
|
1083 |
+} |
|
1084 |
+ |
|
1085 |
+ .unit-pagination .selected-btn { |
|
1086 |
+ background-color:#c6c6c6; |
|
1087 |
+ /* color: #fff; */ |
|
1088 |
+ font-family: 'Pretendard-ExtraBold'; |
|
1089 |
+} |
|
1028 | 1090 |
/* ------------------------선생님 --------------------- */(파일 끝에 줄바꿈 문자 없음) |
+++ client/resources/img/img222_57s.png
Binary file is not shown |
--- client/views/layout/Header.vue
+++ client/views/layout/Header.vue
... | ... | @@ -102,7 +102,7 @@ |
102 | 102 |
|
103 | 103 |
// 페이징 정보 |
104 | 104 |
page: 1, |
105 |
- pageSize: 3, |
|
105 |
+ pageSize: 2, |
|
106 | 106 |
totalpages: null, |
107 | 107 |
|
108 | 108 |
// 사용자 정보 |
--- client/views/layout/Side.vue
+++ client/views/layout/Side.vue
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 |
<div class="profile mb30"> |
5 | 5 |
<div class="flex align-start"> |
6 | 6 |
<img src="../../resources/img/img16_s.png" alt=""> |
7 |
- <div class="ml25" style="width: 100%;"> |
|
7 |
+ <div class="ml25" > |
|
8 | 8 |
<p class="name mb10">학생이름</p> |
9 | 9 |
<p class="mb5">xx중학교 3학년 x반</p> |
10 | 10 |
<progress-bar :progress="progress"></progress-bar> |
--- client/views/layout/Side_t.vue
+++ client/views/layout/Side_t.vue
... | ... | @@ -26,16 +26,17 @@ |
26 | 26 |
<router-link to="/Home.page" class="tpt">홈</router-link> |
27 | 27 |
<router-link to="/Board.page" class="tpt">게시판</router-link> |
28 | 28 |
<router-link to="/StudentList.page" class="tpt">학생목록</router-link> |
29 |
- <router-link to="/textbook.page" class="tpt">교재</router-link> |
|
29 |
+ <router-link to="/C_Textbook.page" class="tpt">교재</router-link> |
|
30 | 30 |
</details> |
31 | 31 |
</div> |
32 | 32 |
<div> |
33 | 33 |
<details> |
34 | 34 |
<summary>교재 관리</summary> |
35 |
- <router-link to="/Board.page" class="tpt">홈</router-link> |
|
36 |
- <router-link to="/Board.page" class="tpt">게시판</router-link> |
|
37 |
- <router-link to="/Board.page" class="tpt">학생목록</router-link> |
|
38 |
- <router-link to="/Board.page" class="tpt">교재</router-link> |
|
35 |
+ <router-link to="/textbook.page" class="tpt">홈</router-link> |
|
36 |
+ <router-link to="/TextList.page" class="tpt">지문</router-link> |
|
37 |
+ <router-link to="/QuestionList.page" class="tpt">문제</router-link> |
|
38 |
+ <router-link to="/VocaList.page" class="tpt">단어장</router-link> |
|
39 |
+ <router-link to="/ExamList.page" class="tpt">평가</router-link> |
|
39 | 40 |
</details> |
40 | 41 |
</div> |
41 | 42 |
</div> |
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
... | ... | @@ -35,6 +35,7 @@ |
35 | 35 |
import Chapter3_1 from "./main/Chapter/Chapter3_1.vue"; |
36 | 36 |
import Chapter3_2 from "./main/Chapter/Chapter3_2.vue"; |
37 | 37 |
import Chapter3_3 from "./main/Chapter/Chapter3_3.vue"; |
38 |
+import Chapter3_3_1 from "./main/Chapter/Chapter3_3_1.vue"; |
|
38 | 39 |
import Chapter3_4 from "./main/Chapter/Chapter3_4.vue"; |
39 | 40 |
import Chapter3_5 from "./main/Chapter/Chapter3_5.vue"; |
40 | 41 |
import Chapter3_6 from "./main/Chapter/Chapter3_6.vue"; |
... | ... | @@ -66,16 +67,32 @@ |
66 | 67 |
import StudentList from "./teacher/StudentList.vue"; |
67 | 68 |
import StudentDetail from "./teacher/StudentDetail.vue"; |
68 | 69 |
import textbook from "./teacher/textbook.vue"; |
70 |
+import C_Textbook from "./teacher/C_Textbook.vue"; |
|
71 |
+import C_TextBookDetail from "./teacher/C_TextBookDetail.vue"; |
|
72 |
+import C_TextList from "./teacher/C_TextList .vue"; |
|
73 |
+import C_TextInsert from "./teacher/C_TextInsert.vue"; |
|
74 |
+import C_QuestionList from "./teacher/C_QuestionList.vue"; |
|
75 |
+import C_QuestionInsert from "./teacher/C_QuestionInsert.vue"; |
|
76 |
+import C_Voca_List from "./teacher/C_Voca_List.vue"; |
|
77 |
+import C_ExamList from "./teacher/C_ExamList.vue"; |
|
78 |
+import C_ExamDetail from "./teacher/C_ExamDetail.vue"; |
|
79 |
+import C_ExamInsert from "./teacher/C_ExamInsert.vue"; |
|
69 | 80 |
import TextBookDetail from "./teacher/TextBookDetail.vue"; |
70 | 81 |
import Home from "./teacher/Home.vue"; |
71 | 82 |
import ClassDetail from "./teacher/ClassDetail.vue"; |
72 | 83 |
import TextList from "./teacher/TextList.vue"; |
73 | 84 |
import TextInsert from "./teacher/TextInsert.vue"; |
85 |
+import TextDetail from "./teacher/TextDetail.vue"; |
|
74 | 86 |
import QuestionList from "./teacher/QuestionList.vue"; |
75 | 87 |
import QuestionInsert from "./teacher/QuestionInsert.vue"; |
88 |
+import QuestionDetail from "./teacher/QuestionDetail.vue"; |
|
76 | 89 |
import VocaList from "./teacher/VocaList.vue"; |
90 |
+import VocaInsert from "./teacher/VocaInsert.vue"; |
|
91 |
+import VocaDetail from "./teacher/VocaDetail.vue"; |
|
77 | 92 |
import ExamList from "./teacher/ExamList.vue"; |
78 | 93 |
import ExamDetail from "./teacher/ExamDetail.vue"; |
94 |
+import ExamInsert from "./teacher/ExamInsert.vue"; |
|
95 |
+import RoadMap from "./teacher/RoadMap.vue"; |
|
79 | 96 |
|
80 | 97 |
const routes = [ |
81 | 98 |
{ path: '/login.page', name: 'login', component: login }, |
... | ... | @@ -130,6 +147,7 @@ |
130 | 147 |
{ path: '/Chapter3_1.page', name: 'Chapter3_1', component: Chapter3_1 }, |
131 | 148 |
{ path: '/Chapter3_2.page', name: 'Chapter3_2', component: Chapter3_2 }, |
132 | 149 |
{ path: '/Chapter3_3.page', name: 'Chapter3_3', component: Chapter3_3 }, |
150 |
+ { path: '/Chapter3_3_1.page', name: 'Chapter3_3_1', component: Chapter3_3_1 }, |
|
133 | 151 |
{ path: '/Chapter3_4.page', name: 'Chapter3_4', component: Chapter3_4 }, |
134 | 152 |
{ path: '/Chapter3_5.page', name: 'Chapter3_5', component: Chapter3_5 }, |
135 | 153 |
{ path: '/Chapter3_6.page', name: 'Chapter3_6', component: Chapter3_6 }, |
... | ... | @@ -167,15 +185,34 @@ |
167 | 185 |
{ path: '/ClassDetail.page', name: 'ClassDetail', component: ClassDetail }, |
168 | 186 |
{ path: '/StudentList.page', name: 'StudentList', component: StudentList }, |
169 | 187 |
{ path: '/StudentDetail.page', name: 'StudentDetail', component: StudentDetail }, |
188 |
+ { path: '/C_Textbook.page', name: 'C_Textbook', component: C_Textbook }, |
|
170 | 189 |
{ path: '/textbook.page', name: 'textbook', component: textbook }, |
171 | 190 |
{ path: '/TextBookDetail.page', name: 'TextBookDetail', component: TextBookDetail }, |
191 |
+ { path: '/C_TextBookDetail.page', name: 'C_TextBookDetail', component: C_TextBookDetail }, |
|
172 | 192 |
{ path: '/TextList.page', name: 'TextList', component: TextList }, |
173 | 193 |
{ path: '/TextInsert.page', name: 'TextInsert', component: TextInsert }, |
194 |
+ { path: '/TextDetail.page', name: 'TextDetail', component: TextDetail }, |
|
174 | 195 |
{ path: '/QuestionList.page', name: 'QuestionList', component: QuestionList }, |
175 | 196 |
{ path: '/QuestionInsert.page', name: 'QuestionInsert', component: QuestionInsert }, |
197 |
+ { path: '/QuestionDetail.page', name: 'QuestionDetail', component: QuestionDetail }, |
|
176 | 198 |
{ path: '/VocaList.page', name: 'VocaList', component: VocaList }, |
199 |
+ { path: '/VocaInsert.page', name: 'VocaInsert', component: VocaInsert }, |
|
200 |
+ { path: '/VocaDetail.page', name: 'VocaDetail', component: VocaDetail }, |
|
177 | 201 |
{ path: '/ExamList.page', name: 'ExamList', component: ExamList }, |
178 | 202 |
{ path: '/ExamDetail.page', name: 'ExamDetail', component: ExamDetail }, |
203 |
+ { path: '/ExamInsert.page', name: 'ExamInsert', component: ExamInsert }, |
|
204 |
+ { path: '/C_TextList.page', name: 'C_TextList', component: C_TextList }, |
|
205 |
+ { path: '/C_TextInsert.page', name: 'C_TextInsert', component: C_TextInsert }, |
|
206 |
+ { path: '/C_QuestionList.page', name: 'C_QuestionList', component: C_QuestionList }, |
|
207 |
+ { path: '/C_QuestionInsert.page', name: 'C_QuestionInsert', component: C_QuestionInsert }, |
|
208 |
+ { path: '/C_Voca_List.page', name: 'C_Voca_List', component: C_Voca_List }, |
|
209 |
+ { path: '/C_ExamList.page', name: 'C_ExamList', component: C_ExamList }, |
|
210 |
+ { path: '/C_ExamDetail.page', name: 'C_ExamDetail', component: C_ExamDetail }, |
|
211 |
+ { path: '/C_ExamInsert.page', name: 'C_ExamInsert', component: C_ExamInsert }, |
|
212 |
+ |
|
213 |
+ { path: '/RoadMap.page', name: 'RoadMap', component: RoadMap }, |
|
214 |
+ |
|
215 |
+ { path: '/TextDetail.page', name: 'TextDetail', component: TextDetail }, |
|
179 | 216 |
], |
180 | 217 |
}, |
181 | 218 |
]; |
--- client/views/pages/main/Chapter/Chapter3_1.vue
+++ client/views/pages/main/Chapter/Chapter3_1.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="flex align-center justify-center" style="gap: 113px;"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
23 | 26 |
</div> |
24 | 27 |
</div> |
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="pickGroup "> |
27 | 30 |
<div class="flex" style="gap: 250px;"> |
28 | 31 |
<article class="text-ct"> |
... | ... | @@ -108,7 +111,6 @@ |
108 | 111 |
|
109 | 112 |
.pickGroup button { |
110 | 113 |
position: relative; |
111 |
- margin-right: 30px; |
|
112 | 114 |
} |
113 | 115 |
|
114 | 116 |
.pickGroup button p { |
--- client/views/pages/main/Chapter/Chapter3_10.vue
+++ client/views/pages/main/Chapter/Chapter3_10.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup mt20"> |
27 | 30 |
<img src="../../../../resources/img/img116_59s.png" alt=""> |
28 | 31 |
<p class="title1 mt10" style="width: auto;"><strong>진수가 거절한 제안</strong>은 무엇인지 우리말로 쓰세요.</p> |
--- client/views/pages/main/Chapter/Chapter3_11.vue
+++ client/views/pages/main/Chapter/Chapter3_11.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup mt20"> |
27 | 30 |
<img src="../../../../resources/img/img115_58s.png" alt=""> |
28 | 31 |
<!-- <p class="title1 mt10"><strong>진수가 거절한 제안</strong>은 무엇인지 우리말로 쓰세요.</p> --> |
--- client/views/pages/main/Chapter/Chapter3_12.vue
+++ client/views/pages/main/Chapter/Chapter3_12.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class=" text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="dragGroup mt40"> |
27 | 30 |
<div class="flex justify-center" style="gap: 20px;"> |
28 | 31 |
<button><img src="../../../../resources/img/img63_37s.png" alt=""> |
--- client/views/pages/main/Chapter/Chapter3_13.vue
+++ client/views/pages/main/Chapter/Chapter3_13.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="flex justify-center "> |
27 | 30 |
<div class=" flex justify-between align-center" style="width: 50%;"> |
28 | 31 |
<div class="pickGroup left"> |
--- client/views/pages/main/Chapter/Chapter3_14.vue
+++ client/views/pages/main/Chapter/Chapter3_14.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup"><img src="../../../../resources/img/img124_63s.png" alt=""></div> |
27 | 30 |
|
28 | 31 |
<div class="dropGroup flex align-center justify-center mt30"> |
--- client/views/pages/main/Chapter/Chapter3_15.vue
+++ client/views/pages/main/Chapter/Chapter3_15.vue
... | ... | @@ -9,39 +9,33 @@ |
9 | 9 |
<div class="content title-box"> |
10 | 10 |
<p class="title mt25 title-bg">step3</p> |
11 | 11 |
<div class="flex align-center mb30"> |
12 |
- <p class="subtitle2 mr20">그림에 알맞는 낱말을 쓰세요.</p> |
|
13 |
- <!-- <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
|
14 |
- </button> --> |
|
12 |
+ <p class="subtitle2 mr20">듣고 올바른 대답을 말해보세요!</p> |
|
13 |
+ <button><img src="../../../../resources/img/btn10_s.png" alt=""> |
|
14 |
+ </button> |
|
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup"><img src="../../../../resources/img/img125_64s.png" alt=""></div> |
27 | 30 |
|
28 | 31 |
<div class="dropGroup flex align-center justify-center mt30"> |
29 |
- <div class="flex" style="gap: 20px;"> |
|
30 |
- <div class="bd-bt textbox" @click="showButton(1)"> |
|
31 |
- <p v-if="showButton1">A</p></div> |
|
32 |
- <div class="bd-bt textbox" @click="showButton(2)"> |
|
33 |
- <p v-if="showButton2">A</p></div> |
|
34 |
- <div class="bd-bt textbox" @click="showButton(3)"> |
|
35 |
- <p v-if="showButton3">A</p></div> |
|
36 |
- <div class="bd-bt textbox" @click="showButton(4)"> |
|
37 |
- <p v-if="showButton4">A</p></div> |
|
38 |
- </div> |
|
32 |
+ <img src="../../../../resources/img/btn18_64s_normal.png" alt=""> |
|
39 | 33 |
|
40 | 34 |
</div> |
41 | 35 |
|
42 | 36 |
</div> |
43 | 37 |
</div> |
44 |
- <div class="next-btn" @click="goToPage('Chapter3_16')"><img src="../../../../resources/img/right.png" alt=""></div> |
|
38 |
+ <div class="next-btn" @click="goToPage('Chapter4')"><img src="../../../../resources/img/right.png" alt=""></div> |
|
45 | 39 |
</div> |
46 | 40 |
</div> |
47 | 41 |
</template> |
--- client/views/pages/main/Chapter/Chapter3_16.vue
+++ client/views/pages/main/Chapter/Chapter3_16.vue
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 |
<span class="subtitle">my name is dd</span> |
6 | 6 |
</div> |
7 | 7 |
<div class="flex justify-between align-center"> |
8 |
- <div class="pre-btn" @click="goToPage('Chapter3_15')"><img src="../../../../resources/img/left.png" alt=""></div> |
|
8 |
+ <div class="pre-btn" @click="goToPage('Chapter4')"><img src="../../../../resources/img/left.png" alt=""></div> |
|
9 | 9 |
<div class="content title-box"> |
10 | 10 |
<p class="title mt25 title-bg">중간 평가 설문 조사</p> |
11 | 11 |
<div class="flex align-center mb30"> |
--- client/views/pages/main/Chapter/Chapter3_2.vue
+++ client/views/pages/main/Chapter/Chapter3_2.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup "> |
27 | 30 |
<img src="../../../../resources/img/img109_51s.png" alt=""> |
28 | 31 |
</div> |
--- client/views/pages/main/Chapter/Chapter3_3.vue
+++ client/views/pages/main/Chapter/Chapter3_3.vue
... | ... | @@ -13,14 +13,17 @@ |
13 | 13 |
</div> |
14 | 14 |
|
15 | 15 |
<div class="text-ct"> |
16 |
- <div class="time-bg"> |
|
17 |
- <div> |
|
18 |
- <div class="time"> |
|
19 |
- <p class="second">{{ timer }}</p> |
|
20 |
- <p class="text">sec</p> |
|
16 |
+ <div class="time-hint"> |
|
17 |
+ <button class="hint-btn">HINT</button> |
|
18 |
+ <div class="time-bg mt20"> |
|
19 |
+ <div> |
|
20 |
+ <div class="time"> |
|
21 |
+ <p class="second">{{ timer }}</p> |
|
22 |
+ <p class="text">sec</p> |
|
23 |
+ </div> |
|
24 |
+ </div> |
|
21 | 25 |
</div> |
22 |
- </div> |
|
23 |
- </div> |
|
26 |
+ </div> |
|
24 | 27 |
<div class="pickGroup mt60 flex align-center justify-center" style="gap: 100px; margin-top: 7%;"> |
25 | 28 |
<article style="gap: 60px; bottom: 159px; |
26 | 29 |
left: 242px;"> |
... | ... | @@ -43,7 +46,7 @@ |
43 | 46 |
</div> |
44 | 47 |
</div> |
45 | 48 |
</div> |
46 |
- <div class="next-btn" @click="goToPage('Chapter3_4')"><img src="../../../../resources/img/right.png" alt=""></div> |
|
49 |
+ <div class="next-btn" @click="goToPage('Chapter3_3_1')"><img src="../../../../resources/img/right.png" alt=""></div> |
|
47 | 50 |
</div> |
48 | 51 |
</div> |
49 | 52 |
</template> |
+++ client/views/pages/main/Chapter/Chapter3_3_1.vue
... | ... | @@ -0,0 +1,150 @@ |
1 | +<template> | |
2 | + <div id="Chapter1_1" class="content-wrap"> | |
3 | + <div class="title-box mb25 flex align-center mt40"> | |
4 | + <span class="title mr40">1. Hello WORLD</span> | |
5 | + <span class="subtitle">my name is dd</span> | |
6 | + </div> | |
7 | + <div class="flex justify-between align-center"> | |
8 | + <div class="pre-btn" @click="goToPage('Chapter3_3')"><img src="../../../../resources/img/left.png" alt=""></div> | |
9 | + <div class="content title-box"> | |
10 | + <p class="title mt25 title-bg">step3.</p> | |
11 | + <div class="flex align-center mb30"> | |
12 | + <p class="subtitle2 mr20">1. see the picture</p> | |
13 | + <button><img src="../../../../resources/img/btn10_s.png" alt=""> | |
14 | + </button> | |
15 | + </div> | |
16 | + | |
17 | + <div class="text-ct"> | |
18 | + <div class="time-hint"> | |
19 | + <button class="hint-btn">HINT</button> | |
20 | + <div class="time-bg mt20"> | |
21 | + <div> | |
22 | + <div class="time"> | |
23 | + <p class="second">{{ timer }}</p> | |
24 | + <p class="text">sec</p> | |
25 | + </div> | |
26 | + </div> | |
27 | + </div> | |
28 | + </div> | |
29 | + <div class="imgGroup "> | |
30 | + <img src="../../../../resources/img/img109_51s.png" alt=""> | |
31 | + </div> | |
32 | + | |
33 | + <div class="pickGroup mt60 flex align-center justify-center" style="gap: 100px; margin-top: 7%;"> | |
34 | + <article style="gap: 60px; bottom: 159px; | |
35 | + left: 242px;"> | |
36 | + <div class="flex align-center"> | |
37 | + <button><img src="../../../../resources/img/img136_71s.png" alt=""> | |
38 | + <p>1</p> | |
39 | + </button> | |
40 | + <img src="../../../../resources/img/img122_62s.png" alt=""> | |
41 | + </div> | |
42 | + </article> | |
43 | + <article style="gap: 60px; bottom: 159px; | |
44 | + right: 559px;"> | |
45 | + <div class="flex align-center"> | |
46 | + <button><img src="../../../../resources/img/img136_71s.png" alt=""> | |
47 | + <p>2</p> | |
48 | + </button> | |
49 | + <img src="../../../../resources/img/img123_62s.png" alt=""> | |
50 | + </div> | |
51 | + </article> | |
52 | + <article style="gap: 60px; bottom: 159px; | |
53 | + right: 559px;"> | |
54 | + <div class="flex align-center"> | |
55 | + <button><img src="../../../../resources/img/img136_71s.png" alt=""> | |
56 | + <p>3</p> | |
57 | + </button> | |
58 | + <img src="../../../../resources/img/img121_62s.png" alt=""> | |
59 | + </div> | |
60 | + </article> | |
61 | + </div> | |
62 | + </div> | |
63 | + </div> | |
64 | + <div class="next-btn" @click="goToPage('Chapter3_4')"><img src="../../../../resources/img/right.png" alt=""></div> | |
65 | + </div> | |
66 | + </div> | |
67 | +</template> | |
68 | + | |
69 | +<script> | |
70 | +export default { | |
71 | + data() { | |
72 | + return { | |
73 | + timer: '00' | |
74 | + } | |
75 | + }, | |
76 | + methods: { | |
77 | + goToPage(page) { | |
78 | + this.$router.push({ name: page }); | |
79 | + }, | |
80 | + startTimer() { | |
81 | + if (this.intervalId) { | |
82 | + clearInterval(this.intervalId); | |
83 | + } | |
84 | + this.timer = 5; | |
85 | + this.intervalId = setInterval(() => { | |
86 | + if (this.timer > 0) { | |
87 | + this.timer--; | |
88 | + } else { | |
89 | + clearInterval(this.intervalId); | |
90 | + } | |
91 | + }, 1000); | |
92 | + } | |
93 | + }, | |
94 | + watch: { | |
95 | + | |
96 | + }, | |
97 | + computed: { | |
98 | + | |
99 | + }, | |
100 | + components: { | |
101 | + }, | |
102 | + mounted() { | |
103 | + | |
104 | + } | |
105 | +} | |
106 | +</script> | |
107 | +<style scoped> | |
108 | +.inputbox { | |
109 | + font-size: 38px; | |
110 | + font-family: 'Pretendard-ExtraBold'; | |
111 | +} | |
112 | + | |
113 | +.imgGroup button { | |
114 | + position: relative; | |
115 | +} | |
116 | + | |
117 | +.imgGroup button p, | |
118 | +.textbox p { | |
119 | + position: absolute; | |
120 | + top: 50%; | |
121 | + left: 50%; | |
122 | + transform: translate(-50%, -50%); | |
123 | + width: fit-content; | |
124 | + height: fit-content; | |
125 | + background: #ffffffb8; | |
126 | + border-radius: 5px; | |
127 | + padding: 10px; | |
128 | + font-size: 48px; | |
129 | + font-family: 'ONEMobilePOP'; | |
130 | +} | |
131 | + | |
132 | +.pickGroup p { | |
133 | + font-size: 34px; | |
134 | + font-weight: bold; | |
135 | +} | |
136 | + | |
137 | +.pickGroup button { | |
138 | + position: relative; | |
139 | + margin-right: 30px; | |
140 | +} | |
141 | + | |
142 | +.pickGroup button p { | |
143 | + font-size: 34px; | |
144 | + color: #c6c6c6; | |
145 | + position: absolute; | |
146 | + top: 50%; | |
147 | + left: 50%; | |
148 | + transform: translate(-50%, -50%); | |
149 | +} | |
150 | +</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/main/Chapter/Chapter3_4.vue
+++ client/views/pages/main/Chapter/Chapter3_4.vue
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 |
<span class="subtitle">my name is dd</span> |
6 | 6 |
</div> |
7 | 7 |
<div class="flex justify-between align-center"> |
8 |
- <div class="pre-btn" @click="goToPage('Chapter3_3')"><img src="../../../../resources/img/left.png" alt=""></div> |
|
8 |
+ <div class="pre-btn" @click="goToPage('Chapter3_3_1')"><img src="../../../../resources/img/left.png" alt=""></div> |
|
9 | 9 |
<div class="content title-box"> |
10 | 10 |
<p class="title mt25 title-bg">step3.</p> |
11 | 11 |
<div class="flex align-center mb30"> |
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="pickGroup flex align-center justify-center" style="gap: 100px; margin-top: 7%;"> |
27 | 30 |
<article style="gap: 60px; bottom: 159px; |
28 | 31 |
left: 242px;"> |
--- client/views/pages/main/Chapter/Chapter3_5.vue
+++ client/views/pages/main/Chapter/Chapter3_5.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class=" text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup "> |
27 | 30 |
<img src="../../../../resources/img/img125_64s.png" alt=""> |
28 | 31 |
</div> |
--- client/views/pages/main/Chapter/Chapter3_6.vue
+++ client/views/pages/main/Chapter/Chapter3_6.vue
... | ... | @@ -14,14 +14,17 @@ |
14 | 14 |
<button><img src="../../../../resources/img/btn10_s.png" alt=""> |
15 | 15 |
</button> |
16 | 16 |
</div> |
17 |
- <div class="time-bg"> |
|
18 |
- <div> |
|
17 |
+ <div class="time-hint"> |
|
18 |
+ <button class="hint-btn">HINT</button> |
|
19 |
+ <div class="time-bg mt20"> |
|
20 |
+ <div> |
|
19 | 21 |
<div class="time"> |
20 |
- <p class="second">{{ timer }}</p> |
|
21 |
- <p class="text">sec</p> |
|
22 |
+ <p class="second">{{ timer }}</p> |
|
23 |
+ <p class="text">sec</p> |
|
22 | 24 |
</div> |
23 |
- </div> |
|
24 |
- </div> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
27 |
+ </div> |
|
25 | 28 |
|
26 | 29 |
<div class="imgGroup"> |
27 | 30 |
<img src="../../../../resources/img/img114_57s.png" alt=""> |
--- client/views/pages/main/Chapter/Chapter3_7.vue
+++ client/views/pages/main/Chapter/Chapter3_7.vue
... | ... | @@ -15,16 +15,19 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
|
27 |
- <div class="pickGroup flex align-center justify-between" style="gap: 100px;"> |
|
30 |
+ <div class="pickGroup flex align-center justify-between mt80" style="gap: 100px;"> |
|
28 | 31 |
<p>1. 문제</p> |
29 | 32 |
<div class="flex justify-center" style="gap: 60px;"> |
30 | 33 |
<article > |
--- client/views/pages/main/Chapter/Chapter3_8.vue
+++ client/views/pages/main/Chapter/Chapter3_8.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup flex align-center justify-center mt50"> |
27 | 30 |
<img src="../../../../resources/img/img114_57s.png" alt=""> |
28 | 31 |
<input class="yellow-bd ml50" style="width: 30%;" type="text" name="" id="" placeholder="답을 입력하세요."> |
--- client/views/pages/main/Chapter/Chapter3_9.vue
+++ client/views/pages/main/Chapter/Chapter3_9.vue
... | ... | @@ -15,14 +15,17 @@ |
15 | 15 |
</div> |
16 | 16 |
|
17 | 17 |
<div class="mt50 text-ct"> |
18 |
- <div class="time-bg"> |
|
19 |
- <div> |
|
20 |
- <div class="time"> |
|
21 |
- <p class="second">{{ timer }}</p> |
|
22 |
- <p class="text">sec</p> |
|
18 |
+ <div class="time-hint"> |
|
19 |
+ <button class="hint-btn">HINT</button> |
|
20 |
+ <div class="time-bg mt20"> |
|
21 |
+ <div> |
|
22 |
+ <div class="time"> |
|
23 |
+ <p class="second">{{ timer }}</p> |
|
24 |
+ <p class="text">sec</p> |
|
25 |
+ </div> |
|
26 |
+ </div> |
|
23 | 27 |
</div> |
24 |
- </div> |
|
25 |
- </div> |
|
28 |
+ </div> |
|
26 | 29 |
<div class="imgGroup mt50"> |
27 | 30 |
<img src="../../../../resources/img/img115_58s.png" alt=""> |
28 | 31 |
<div class=" mt50"> |
--- client/views/pages/main/Chapter/Chapter4.vue
+++ client/views/pages/main/Chapter/Chapter4.vue
... | ... | @@ -102,7 +102,7 @@ |
102 | 102 |
|
103 | 103 |
</div> |
104 | 104 |
</div> |
105 |
- <div class="next-btn" @click="goToPage('Dashboard')"><img src="../../../../resources/img/right.png" alt=""> |
|
105 |
+ <div class="next-btn" @click="goToPage('Chapter3_16')"><img src="../../../../resources/img/right.png" alt=""> |
|
106 | 106 |
</div> |
107 | 107 |
</div> |
108 | 108 |
</div> |
--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 |
<p class="subtitle">hi my name is dd!</p> |
7 | 7 |
</div> |
8 | 8 |
<div class="race-box"> |
9 |
- <div class="rabbit"><img src="../../../resources/img/img09_s.png" alt=""></div> |
|
9 |
+ <div class="rabbit-start"><img src="../../../resources/img/img09_s.png" alt=""></div> |
|
10 | 10 |
<div class="rcon flex justify-end mb5"> |
11 | 11 |
<div class="race-btn" @click="goToPage('Chapter1')"> |
12 | 12 |
<button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" |
... | ... | @@ -262,6 +262,7 @@ |
262 | 262 |
<h2 class="mb40">이 단원을 끝낸 친구들</h2> |
263 | 263 |
<article class=" flex-column" style="gap: 5px;"> |
264 | 264 |
<div class="flex" style="gap: 5px;"> |
265 |
+ <div @click="buttonSearch2" class="photo" ><img src="../../../resources/img/img143_75s.png" alt=""></div> |
|
265 | 266 |
<div @click="buttonSearch" class="photo"><img src="../../../resources/img/img143_75s.png" alt=""></div> |
266 | 267 |
</div> |
267 | 268 |
</article> |
... | ... | @@ -270,7 +271,7 @@ |
270 | 271 |
<div class="popup-box "> |
271 | 272 |
<div class="flex mb10 justify-between"> |
272 | 273 |
<p class="popup-title">알림</p> |
273 |
- <button type="button" class="popup-close-btn" @click="closeBtn"> |
|
274 |
+ <button type="button" class="popup-close-btn" @click="closeBtn2"> |
|
274 | 275 |
<svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
275 | 276 |
</button> |
276 | 277 |
</div> |
... | ... | @@ -436,6 +437,9 @@ |
436 | 437 |
buttonSearch() { |
437 | 438 |
this.searchOpen = true; |
438 | 439 |
}, |
440 |
+ buttonSearch2() { |
|
441 |
+ this.searchOpen2 = true; |
|
442 |
+ }, |
|
439 | 443 |
closeBtn() { |
440 | 444 |
this.searchOpen = false; |
441 | 445 |
}, |
--- client/views/pages/main/MyPage.vue
+++ client/views/pages/main/MyPage.vue
... | ... | @@ -74,7 +74,7 @@ |
74 | 74 |
</div> |
75 | 75 |
<div class=" mb30"> |
76 | 76 |
<div class=" flex " style="gap: 50px;"> |
77 |
- <div class="textbook"> |
|
77 |
+ <div class="textbook book-red"> |
|
78 | 78 |
<div class="text "> |
79 | 79 |
<p class="title1" style="color: #fff;">포토북 랭킹</p> |
80 | 80 |
</div> |
... | ... | @@ -83,7 +83,7 @@ |
83 | 83 |
<P class="title2 mt10">현재 30명 중 <em class="red">2등</em>입니다.</P> |
84 | 84 |
</div> |
85 | 85 |
</div> |
86 |
- <div class="textbook"> |
|
86 |
+ <div class="textbook "> |
|
87 | 87 |
<div class="text "> |
88 | 88 |
<p class="title1" style="color: #fff;">포토북 랭킹</p> |
89 | 89 |
</div> |
... | ... | @@ -92,7 +92,7 @@ |
92 | 92 |
<P class="title2 mt10">현재 30명 중 <em class="yellow">2등</em>입니다.</P> |
93 | 93 |
</div> |
94 | 94 |
</div> |
95 |
- <div class="textbook"> |
|
95 |
+ <div class="textbook book-blue"> |
|
96 | 96 |
<div class="text "> |
97 | 97 |
<p class="title1" style="color: #fff;">포토북 랭킹</p> |
98 | 98 |
</div> |
... | ... | @@ -101,7 +101,7 @@ |
101 | 101 |
<P class="title2 mt10">현재 30명 중 <em class="blue">2등</em>입니다.</P> |
102 | 102 |
</div> |
103 | 103 |
</div> |
104 |
- <div class="textbook"> |
|
104 |
+ <div class="textbook book-navy"> |
|
105 | 105 |
<div class="text "> |
106 | 106 |
<p class="title1" style="color: #fff;">포토북 랭킹</p> |
107 | 107 |
</div> |
... | ... | @@ -172,4 +172,7 @@ |
172 | 172 |
} |
173 | 173 |
</script> |
174 | 174 |
<style scoped> |
175 |
+.mypage .textbook { |
|
176 |
+ width: 22%; |
|
177 |
+} |
|
175 | 178 |
</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/Board.vue
+++ client/views/pages/teacher/Board.vue
... | ... | @@ -1,8 +1,14 @@ |
1 | 1 |
<template> |
2 | 2 |
<div class="title-box flex justify-between mb40"> |
3 | 3 |
<p class="title">게시판</p> |
4 |
- <select name="" id=""> |
|
5 |
- <option value="">A반</option> |
|
4 |
+ <select v-model="sclsId" @change="handleClassId()"> |
|
5 |
+ <option |
|
6 |
+ v-for="(item, index) in classList" |
|
7 |
+ :key="index" |
|
8 |
+ :value="item.sclsId" |
|
9 |
+ > |
|
10 |
+ {{ item.sclsNm }} |
|
11 |
+ </option> |
|
6 | 12 |
</select> |
7 | 13 |
</div> |
8 | 14 |
<div class="search-wrap flex justify-end mb20"> |
... | ... | @@ -38,11 +44,11 @@ |
38 | 44 |
:class="{ 'selected-row': selectedRow == item.dataList }" |
39 | 45 |
@click="[goToPage('noticeDetail'), selectBoardList(item)]" |
40 | 46 |
> |
41 |
- <td>{{ totalBoard - index }}</td> |
|
47 |
+ <td>{{ createNo(index) }}</td> |
|
42 | 48 |
<td>{{ item.bbsTtl }}</td> |
43 | 49 |
<td>{{ item.bbsCls }}</td> |
44 | 50 |
<td>{{ userNm }}</td> |
45 |
- <td>{{ item.bbsTm }}</td> |
|
51 |
+ <td>{{ item.bbsTm.substr(0, 16) }}</td> |
|
46 | 52 |
</tr> |
47 | 53 |
</tbody> |
48 | 54 |
</table> |
... | ... | @@ -50,22 +56,19 @@ |
50 | 56 |
class="table-pagination flex justify-center align-center mb20 mt30" |
51 | 57 |
style="gap: 10px" |
52 | 58 |
> |
53 |
- <button> |
|
54 |
- <img |
|
55 |
- src="../../../resources/img/btn27_90t_normal.png" |
|
56 |
- alt="" |
|
57 |
- @click="previousPage" |
|
58 |
- :disabled="page === 1" |
|
59 |
- /> |
|
59 |
+ <button @click="goToPagination(currentPage - 1)"> |
|
60 |
+ <img src="../../../resources/img/btn27_90t_normal.png" alt="" /> |
|
60 | 61 |
</button> |
61 |
- <button class="selected-btn">{{ page }}</button> |
|
62 |
- <button> |
|
63 |
- <img |
|
64 |
- src="../../../resources/img/btn28_90t_normal.png" |
|
65 |
- alt="" |
|
66 |
- @click="nextPage" |
|
67 |
- :disabled="page === totalPages" |
|
68 |
- /> |
|
62 |
+ <button |
|
63 |
+ v-for="page in paginationButtons" |
|
64 |
+ :key="page" |
|
65 |
+ @click="goToPagination(page - 1)" |
|
66 |
+ :class="{ 'selected-btn': currentPage === page - 1 }" |
|
67 |
+ > |
|
68 |
+ {{ page }} |
|
69 |
+ </button> |
|
70 |
+ <button @click="goToPagination(currentPage + 1)"> |
|
71 |
+ <img src="../../../resources/img/btn28_90t_normal.png" alt="" /> |
|
69 | 72 |
</button> |
70 | 73 |
</article> |
71 | 74 |
<div class="flex justify-end"> |
... | ... | @@ -93,20 +96,24 @@ |
93 | 96 |
|
94 | 97 |
// 게시글 정보 |
95 | 98 |
dataList: [], |
96 |
- totalBoard: null, |
|
99 |
+ totalPosts: 0, |
|
97 | 100 |
selectedRow: "", |
101 |
+ bbsTm: "", |
|
98 | 102 |
|
99 | 103 |
// 페이징 |
100 |
- page: 1, |
|
101 |
- pageSize: 8, |
|
102 |
- totalPages: null, |
|
104 |
+ currentPage: 0, |
|
105 |
+ itemsPerPage: 8, |
|
103 | 106 |
|
104 | 107 |
// 반 아이디 (추후 세션에서 받는걸로 수정) |
105 |
- sclsId: "1", |
|
108 |
+ sclsId: "", |
|
109 |
+ classList: [], |
|
106 | 110 |
|
111 |
+ userId: "", |
|
107 | 112 |
// 검색어 |
108 | 113 |
searchKeyword: "", |
109 | 114 |
selectedSearchOption: "bbsTtl", |
115 |
+ |
|
116 |
+ selected: null, |
|
110 | 117 |
}; |
111 | 118 |
}, |
112 | 119 |
methods: { |
... | ... | @@ -131,39 +138,44 @@ |
131 | 138 |
// 게시글 전체 조회 |
132 | 139 |
boardList() { |
133 | 140 |
const vm = this; |
141 |
+ vm.sclsId = JSON.parse(sessionStorage.getItem("sclsId")); |
|
134 | 142 |
axios({ |
135 | 143 |
url: "/board/findAll.json", |
136 | 144 |
method: "post", |
137 | 145 |
headers: { |
138 | 146 |
"Content-Type": "application/json; charset=UTF-8", |
139 | 147 |
}, |
140 |
- data: { page: vm.page, pageSize: vm.pageSize, sclsId: vm.sclsId }, |
|
148 |
+ data: { |
|
149 |
+ page: vm.currentPage + 1, |
|
150 |
+ pageSize: vm.itemsPerPage, |
|
151 |
+ sclsId: vm.sclsId, |
|
152 |
+ }, |
|
141 | 153 |
}) |
142 | 154 |
.then(function (res) { |
143 | 155 |
console.log("dataList - response : ", res.data); |
144 |
- console.log(res.data.result[0].boardClass[0].board); |
|
145 |
- |
|
146 |
- vm.dataList = res.data.result[0].boardClass[0].board; |
|
147 |
- vm.userNm = res.data.result[0].userNm; |
|
148 |
- vm.userId = res.data.result[0].userId; |
|
149 |
- vm.totalBoard = res.data.totalBoard; |
|
150 |
- vm.totalPages = Math.ceil(vm.totalBoard / vm.pageSize); |
|
156 |
+ if (res.data.result.length !== 0) { |
|
157 |
+ vm.dataList = res.data.result[0].boardClass[0].board; |
|
158 |
+ vm.userNm = res.data.result[0].userNm; |
|
159 |
+ vm.userId = res.data.result[0].userId; |
|
160 |
+ vm.totalPosts = res.data.totalBoard; |
|
161 |
+ vm.selectClass(); |
|
162 |
+ sessionStorage.removeItem("bbsId"); |
|
163 |
+ sessionStorage.removeItem("file"); |
|
164 |
+ } else { |
|
165 |
+ vm.selectClass(); |
|
166 |
+ } |
|
151 | 167 |
}) |
152 | 168 |
.catch(function (error) { |
153 |
- console.log("result - error : ", error); |
|
154 |
- alert("비상 비상!"); |
|
169 |
+ console.log("boardListError - error : ", error); |
|
155 | 170 |
}); |
156 | 171 |
}, |
157 | 172 |
|
158 | 173 |
// 게시글 정보 세션에 저장 |
159 | 174 |
selectBoardList(item) { |
160 |
- sessionStorage.setItem("selectedBoardList", JSON.stringify(item)); |
|
175 |
+ sessionStorage.setItem("bbsId", JSON.stringify(item.bbsId)); |
|
161 | 176 |
}, |
162 | 177 |
|
163 | 178 |
// 반 아이디 세션에 저장 |
164 |
- setClassId() { |
|
165 |
- sessionStorage.setItem("sclsId", JSON.stringify(this.sclsId)); |
|
166 |
- }, |
|
167 | 179 |
|
168 | 180 |
// 게시글 검색 |
169 | 181 |
boardDataSearch() { |
... | ... | @@ -171,8 +183,8 @@ |
171 | 183 |
let searchPayload = { |
172 | 184 |
keyword: vm.searchKeyword, |
173 | 185 |
option: vm.selectedSearchOption, |
174 |
- page: vm.page, |
|
175 |
- pageSize: vm.pageSize, |
|
186 |
+ page: vm.currentPage, |
|
187 |
+ pageSize: vm.itemsPerPage, |
|
176 | 188 |
sclsId: vm.sclsId, |
177 | 189 |
}; |
178 | 190 |
axios({ |
... | ... | @@ -188,7 +200,7 @@ |
188 | 200 |
vm.dataList = res.data.result[0].boardClass[0].board; |
189 | 201 |
vm.userNm = res.data.result[0].userNm; |
190 | 202 |
vm.userId = res.data.result[0].userId; |
191 |
- vm.totalBoard = res.data.totalBoard; |
|
203 |
+ vm.totalPosts = res.data.totalBoard; |
|
192 | 204 |
}) |
193 | 205 |
.catch(function (error) { |
194 | 206 |
console.log("dataSearch - error : ", error); |
... | ... | @@ -196,29 +208,70 @@ |
196 | 208 |
}); |
197 | 209 |
}, |
198 | 210 |
|
199 |
- previousPage() { |
|
200 |
- if (this.page > 1) { |
|
201 |
- this.page -= 1; |
|
202 |
- this.boardList(); |
|
203 |
- } |
|
211 |
+ // 반 조회 |
|
212 |
+ selectClass() { |
|
213 |
+ const vm = this; |
|
214 |
+ axios({ |
|
215 |
+ url: "/classes/selectClass.json", |
|
216 |
+ method: "post", |
|
217 |
+ headers: { |
|
218 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
219 |
+ }, |
|
220 |
+ data: { |
|
221 |
+ userId: vm.userId, |
|
222 |
+ }, |
|
223 |
+ }) |
|
224 |
+ .then(function (res) { |
|
225 |
+ console.log("classData - response : ", res.data); |
|
226 |
+ vm.classList = res.data.data; |
|
227 |
+ vm.selected = res.data.data.sclsId; |
|
228 |
+ }) |
|
229 |
+ .catch(function (error) { |
|
230 |
+ console.log("classData - error : ", error); |
|
231 |
+ }); |
|
232 |
+ }, |
|
233 |
+ handleClassId() { |
|
234 |
+ sessionStorage.setItem("sclsId", JSON.stringify(this.sclsId)); |
|
235 |
+ this.boardList(); |
|
204 | 236 |
}, |
205 | 237 |
|
206 |
- nextPage() { |
|
207 |
- if (this.page < this.totalPages) { |
|
208 |
- this.page += 1; |
|
209 |
- this.boardList(); |
|
238 |
+ createNo(index) { |
|
239 |
+ return this.totalPosts - (this.currentPage * this.itemsPerPage + index); |
|
240 |
+ }, |
|
241 |
+ |
|
242 |
+ goToPagination(page) { |
|
243 |
+ if (page < 0 || page >= this.totalPages) { |
|
244 |
+ return; |
|
210 | 245 |
} |
246 |
+ this.currentPage = page; |
|
247 |
+ this.boardList(); |
|
211 | 248 |
}, |
212 | 249 |
}, |
213 | 250 |
watch: {}, |
214 |
- computed: {}, |
|
251 |
+ computed: { |
|
252 |
+ totalPages() { |
|
253 |
+ return Math.ceil(this.totalPosts / this.itemsPerPage); |
|
254 |
+ }, |
|
255 |
+ paginationButtons() { |
|
256 |
+ let start = Math.max(0, this.currentPage - 2); |
|
257 |
+ let end = Math.min(start + 5, this.totalPages); |
|
258 |
+ |
|
259 |
+ if (end - start < 5) { |
|
260 |
+ start = Math.max(0, end - 5); |
|
261 |
+ } |
|
262 |
+ |
|
263 |
+ return Array.from({ length: end - start }, (_, i) => start + i + 1); |
|
264 |
+ }, |
|
265 |
+ startIndex() { |
|
266 |
+ return this.currentPage * this.itemsPerPage; |
|
267 |
+ }, |
|
268 |
+ }, |
|
215 | 269 |
components: { |
216 | 270 |
SvgIcon, |
217 | 271 |
}, |
218 | 272 |
mounted() { |
219 | 273 |
console.log("Main2 mounted"); |
220 | 274 |
this.boardList(); |
221 |
- this.setClassId(); |
|
222 | 275 |
}, |
223 | 276 |
}; |
224 | 277 |
</script> |
+++ client/views/pages/teacher/C_ExamDetail.vue
... | ... | @@ -0,0 +1,93 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">문제 상세 페이지</p> | |
4 | + </div> | |
5 | + <label for="" class="title1">문제 리스트</label> | |
6 | + <table class="mt20 mb100"> | |
7 | + <colgroup> | |
8 | + <col style="width: 10%;"> | |
9 | + <col style="width: 70%;"> | |
10 | + <col style="width: 20%;"> | |
11 | + </colgroup> | |
12 | + <thead> | |
13 | + <td>No.</td> | |
14 | + <td>문제</td> | |
15 | + <td>보기</td> | |
16 | + </thead> | |
17 | + <tbody> | |
18 | + <tr> | |
19 | + <td>1</td> | |
20 | + <td>1</td> | |
21 | + <td><button type="button" title="수정" class="new-btn"> | |
22 | + 수정 | |
23 | + </button></td> | |
24 | + </tr> | |
25 | + </tbody> | |
26 | + </table> | |
27 | + <label for="" class="title1">상세 내용</label> | |
28 | + <div class="board-wrap mt20"> | |
29 | + <div class="flex align-center mb20"> | |
30 | + <label for="" class="title2">문제</label> | |
31 | + <input type="text" class="data-wrap"> | |
32 | + </div> | |
33 | + | |
34 | + <hr> | |
35 | + <div class="flex align-center"> | |
36 | + <label for="" class="title2">내용</label> | |
37 | + <textarea name="" id="" class="data-wrap"></textarea> | |
38 | + </div> | |
39 | + <hr> | |
40 | + <div class="flex align-center mb20"> | |
41 | + <label for="" class="title2">첨부파일</label> | |
42 | + <input type="file" ref="fileInput" @change="handleFileUpload" /> | |
43 | + </div> | |
44 | + <div class="flex align-center"> | |
45 | + <label for="" class="title2">답</label> | |
46 | + <input type="text" class="data-wrap"> | |
47 | + </div> | |
48 | + </div> | |
49 | + <div class="flex justify-between mt50"> | |
50 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('ExamList')"> | |
51 | + 목록 | |
52 | + </button> | |
53 | + <div class="flex"> | |
54 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
55 | + 수정 | |
56 | + </button> | |
57 | + <button type="button" title="글쓰기" class="new-btn"> | |
58 | + 삭제 | |
59 | + </button> | |
60 | + </div> | |
61 | + </div> | |
62 | +</template> | |
63 | + | |
64 | +<script> | |
65 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
66 | +import { mdiMagnify } from '@mdi/js'; | |
67 | + | |
68 | + | |
69 | +export default { | |
70 | + data() { | |
71 | + return { | |
72 | + mdiMagnify: mdiMagnify, | |
73 | + } | |
74 | + }, | |
75 | + methods: { | |
76 | + goToPage(page) { | |
77 | + this.$router.push({ name: page }); | |
78 | + }, | |
79 | + }, | |
80 | + watch: { | |
81 | + | |
82 | + }, | |
83 | + computed: { | |
84 | + | |
85 | + }, | |
86 | + components: { | |
87 | + SvgIcon | |
88 | + }, | |
89 | + mounted() { | |
90 | + console.log('Main2 mounted'); | |
91 | + } | |
92 | +} | |
93 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_ExamInsert.vue
... | ... | @@ -0,0 +1,93 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">문제 등록 페이지</p> | |
4 | + </div> | |
5 | + <!-- <label for="" class="title1">문제 리스트</label> | |
6 | + <table class="mt20 mb100"> | |
7 | + <colgroup> | |
8 | + <col style="width: 10%;"> | |
9 | + <col style="width: 70%;"> | |
10 | + <col style="width: 20%;"> | |
11 | + </colgroup> | |
12 | + <thead> | |
13 | + <td>No.</td> | |
14 | + <td>문제</td> | |
15 | + <td>보기</td> | |
16 | + </thead> | |
17 | + <tbody> | |
18 | + <tr> | |
19 | + <td>1</td> | |
20 | + <td>1</td> | |
21 | + <td><button type="button" title="수정" class="new-btn"> | |
22 | + 수정 | |
23 | + </button></td> | |
24 | + </tr> | |
25 | + </tbody> | |
26 | + </table> --> | |
27 | + <label for="" class="title1">상세 내용</label> | |
28 | + <div class="board-wrap mt20"> | |
29 | + <div class="flex align-center mb20"> | |
30 | + <label for="" class="title2">문제</label> | |
31 | + <input type="text" class="data-wrap"> | |
32 | + </div> | |
33 | + | |
34 | + <hr> | |
35 | + <div class="flex align-center"> | |
36 | + <label for="" class="title2">내용</label> | |
37 | + <textarea name="" id="" class="data-wrap"></textarea> | |
38 | + </div> | |
39 | + <hr> | |
40 | + <div class="flex align-center mb20"> | |
41 | + <label for="" class="title2">첨부파일</label> | |
42 | + <input type="file" ref="fileInput" @change="handleFileUpload" /> | |
43 | + </div> | |
44 | + <div class="flex align-center"> | |
45 | + <label for="" class="title2">답</label> | |
46 | + <input type="text" class="data-wrap"> | |
47 | + </div> | |
48 | + </div> | |
49 | + <div class="flex justify-between mt50"> | |
50 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('C_ExamList')"> | |
51 | + 목록 | |
52 | + </button> | |
53 | + <div class="flex"> | |
54 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
55 | + 취소 | |
56 | + </button> | |
57 | + <button type="button" title="글쓰기" class="new-btn"> | |
58 | + 등록 | |
59 | + </button> | |
60 | + </div> | |
61 | + </div> | |
62 | +</template> | |
63 | + | |
64 | +<script> | |
65 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
66 | +import { mdiMagnify } from '@mdi/js'; | |
67 | + | |
68 | + | |
69 | +export default { | |
70 | + data() { | |
71 | + return { | |
72 | + mdiMagnify: mdiMagnify, | |
73 | + } | |
74 | + }, | |
75 | + methods: { | |
76 | + goToPage(page) { | |
77 | + this.$router.push({ name: page }); | |
78 | + }, | |
79 | + }, | |
80 | + watch: { | |
81 | + | |
82 | + }, | |
83 | + computed: { | |
84 | + | |
85 | + }, | |
86 | + components: { | |
87 | + SvgIcon | |
88 | + }, | |
89 | + mounted() { | |
90 | + console.log('Main2 mounted'); | |
91 | + } | |
92 | +} | |
93 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_ExamList.vue
... | ... | @@ -0,0 +1,150 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">평가</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="">1단원</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="search-wrap flex justify-end mb20"> | |
9 | + <select name="" id="" class="mr10 data-wrap"> | |
10 | + <option value="">중간</option> | |
11 | + <option value="">최종</option> | |
12 | + </select> | |
13 | + <select name="" id="" class="mr10 data-wrap"> | |
14 | + <option value="">전체</option> | |
15 | + </select> | |
16 | + <input type="text" placeholder="검색하세요."> | |
17 | + <button type="button" title="위원회 검색"> | |
18 | + <img src="../../../resources/img/look_t.png" alt=""> | |
19 | + </button> | |
20 | + </div> | |
21 | + <div class="table-wrap"> | |
22 | + <table> | |
23 | + <thead> | |
24 | + <td>No.</td> | |
25 | + <td>제목</td> | |
26 | + <td>중간/최종</td> | |
27 | + <td>작성자</td> | |
28 | + <td>문항</td> | |
29 | + <td>보기</td> | |
30 | + <td>등록일</td> | |
31 | + </thead> | |
32 | + <tbody> | |
33 | + <tr> | |
34 | + <td></td> | |
35 | + <td></td> | |
36 | + <td></td> | |
37 | + <td></td> | |
38 | + <td></td> | |
39 | + <td><button type="button" title="보기" class="new-btn" @click="goToPage('C_ExamDetail')"> | |
40 | + 보기 | |
41 | + </button></td> | |
42 | + <td></td> | |
43 | + </tr> | |
44 | + <!-- <tr :class="{ 'hidden-tr': !isRowVisible }" class="show-tr"> | |
45 | + <td colspan="7"> | |
46 | + <div> | |
47 | + <table> | |
48 | + <colgroup> | |
49 | + <col style="width: 10%;"> | |
50 | + <col style="width: 70%;"> | |
51 | + <col style="width: 20%;"> | |
52 | + </colgroup> | |
53 | + <thead> | |
54 | + <td>No.</td> | |
55 | + <td>문제</td> | |
56 | + <td></td> | |
57 | + </thead> | |
58 | + <tbody> | |
59 | + <tr> | |
60 | + <td>1</td> | |
61 | + <td>1</td> | |
62 | + <td><button type="button" title="수정" class="new-btn" @click="goToPage('ExamDetail')"> | |
63 | + 수정 | |
64 | + </button></td> | |
65 | + </tr> | |
66 | + </tbody> | |
67 | + </table> | |
68 | + </div> | |
69 | + </td> | |
70 | + </tr> --> | |
71 | + </tbody> | |
72 | + </table> | |
73 | + <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> | |
74 | + <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button> | |
75 | + <button class="selected-btn">1</button> | |
76 | + <button>2</button> | |
77 | + <button>3</button> | |
78 | + <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> | |
79 | + </article> | |
80 | + <div class="flex justify-end "> | |
81 | + <button type="button" title="등록" class="new-btn" @click="goToPage('C_ExamInsert')"> | |
82 | + 등록 | |
83 | + </button> | |
84 | + </div> | |
85 | + </div> | |
86 | +</template> | |
87 | + | |
88 | +<script> | |
89 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
90 | +import { mdiMagnify, mdiWindowClose} from '@mdi/js'; | |
91 | + | |
92 | + | |
93 | +export default { | |
94 | + data () { | |
95 | + return { | |
96 | + mdiMagnify: mdiMagnify, | |
97 | + mdiWindowClose: mdiWindowClose, | |
98 | + showModal: false, | |
99 | + searchOpen: false, | |
100 | + isRowVisible: false | |
101 | + } | |
102 | + }, | |
103 | + methods: { | |
104 | + toggleRow() { | |
105 | + this.isRowVisible = !this.isRowVisible; | |
106 | + }, | |
107 | + goToPage(page) { | |
108 | + this.$router.push({ name: page }); | |
109 | + }, | |
110 | + showConfirm(type) { | |
111 | + let message = ''; | |
112 | + if (type === 'cancel') { | |
113 | + message = '삭제하시겠습니까?'; | |
114 | + } else if (type === 'reset') { | |
115 | + message = '초기화하시겠습니까?'; | |
116 | + } else if (type === 'save') { | |
117 | + message = '등록하시겠습니까?'; | |
118 | + } | |
119 | + | |
120 | + if (confirm(message)) { | |
121 | + this.goBack(); | |
122 | + } | |
123 | + }, | |
124 | + | |
125 | + closeModal() { | |
126 | + this.showModal = false; | |
127 | + }, | |
128 | + buttonSearch() { | |
129 | + this.searchOpen = true; | |
130 | + }, | |
131 | + closeBtn() { | |
132 | + this.searchOpen = false; | |
133 | + | |
134 | + }, | |
135 | + | |
136 | + }, | |
137 | + watch: { | |
138 | + | |
139 | + }, | |
140 | + computed: { | |
141 | + | |
142 | + }, | |
143 | + components:{ | |
144 | + SvgIcon | |
145 | + }, | |
146 | + mounted() { | |
147 | + console.log('Main2 mounted'); | |
148 | + } | |
149 | +} | |
150 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_QuestionInsert.vue
... | ... | @@ -0,0 +1,99 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">문제 등록</p> | |
4 | + </div> | |
5 | + <div class="board-wrap"> | |
6 | + <div class="flex align-center mb20"> | |
7 | + <label for="" class="title2">제목</label> | |
8 | + <input type="text" class="data-wrap"> | |
9 | + </div> | |
10 | + <hr> | |
11 | + <div class="flex align-center"> | |
12 | + <label for="" class="title2">내용</label> | |
13 | + <textarea name="" id="" class="data-wrap"></textarea> | |
14 | + </div> | |
15 | + <hr> | |
16 | + <div class="flex align-center mb20"> | |
17 | + <label for="" class="title2">첨부파일</label> | |
18 | + <input type="file" ref="fileInput" @change="handleFileUpload" /> | |
19 | + </div> | |
20 | + <div class="flex align-center mb20"> | |
21 | + <label for="" class="title2">답</label> | |
22 | + <input type="text" class="data-wrap"> | |
23 | + </div> | |
24 | + <div> | |
25 | + <label for="" class="title2">오답 학생</label> | |
26 | + <div class="table-wrap mt20"> | |
27 | + <table> | |
28 | + <thead> | |
29 | + <td>No.</td> | |
30 | + <td>이름</td> | |
31 | + <td>학년</td> | |
32 | + <td>반</td> | |
33 | + <td>오답</td> | |
34 | + </thead> | |
35 | + <tbody> | |
36 | + <tr @click="goToPage('noticeDetail')"> | |
37 | + <td></td> | |
38 | + <td></td> | |
39 | + <td></td> | |
40 | + <td></td> | |
41 | + <td></td> | |
42 | + </tr> | |
43 | + </tbody> | |
44 | + </table> | |
45 | + <!-- <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> | |
46 | + <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button> | |
47 | + <button class="selected-btn">1</button> | |
48 | + <button>2</button> | |
49 | + <button>3</button> | |
50 | + <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> | |
51 | + </article> --> | |
52 | + </div> | |
53 | + </div> | |
54 | + </div> | |
55 | + <div class="flex justify-between mt50"> | |
56 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('C_QuestionList')"> | |
57 | + 목록 | |
58 | + </button> | |
59 | + <div class="flex"> | |
60 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
61 | + 수정 | |
62 | + </button> | |
63 | + <button type="button" title="글쓰기" class="new-btn"> | |
64 | + 삭제 | |
65 | + </button> | |
66 | + </div> | |
67 | + </div> | |
68 | +</template> | |
69 | + | |
70 | +<script> | |
71 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
72 | +import { mdiMagnify } from '@mdi/js'; | |
73 | + | |
74 | + | |
75 | +export default { | |
76 | + data() { | |
77 | + return { | |
78 | + mdiMagnify: mdiMagnify, | |
79 | + } | |
80 | + }, | |
81 | + methods: { | |
82 | + goToPage(page) { | |
83 | + this.$router.push({ name: page }); | |
84 | + }, | |
85 | + }, | |
86 | + watch: { | |
87 | + | |
88 | + }, | |
89 | + computed: { | |
90 | + | |
91 | + }, | |
92 | + components: { | |
93 | + SvgIcon | |
94 | + }, | |
95 | + mounted() { | |
96 | + console.log('Main2 mounted'); | |
97 | + } | |
98 | +} | |
99 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_QuestionList.vue
... | ... | @@ -0,0 +1,97 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">문제</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="">1단원</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="search-wrap flex justify-end mb20"> | |
9 | + <select name="" id="" class="mr10 data-wrap"> | |
10 | + <option value="">전체</option> | |
11 | + </select> | |
12 | + <input type="text" placeholder="검색하세요."> | |
13 | + <button type="button" title="위원회 검색"> | |
14 | + <img src="../../../resources/img/look_t.png" alt=""> | |
15 | + </button> | |
16 | + </div> | |
17 | + <div class="table-wrap"> | |
18 | + <table> | |
19 | + <thead> | |
20 | + <td>No.</td> | |
21 | + <td>제목</td> | |
22 | + <td>문제</td> | |
23 | + <td>작성자</td> | |
24 | + <td>오답률</td> | |
25 | + <td>등록일</td> | |
26 | + </thead> | |
27 | + <tbody> | |
28 | + <tr @click="goToPage('C_QuestionInsert')"> | |
29 | + <td></td> | |
30 | + <td></td> | |
31 | + <td></td> | |
32 | + <td></td> | |
33 | + <td></td> | |
34 | + <td></td> | |
35 | + </tr> | |
36 | + </tbody> | |
37 | + </table> | |
38 | + <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> | |
39 | + <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button> | |
40 | + <button class="selected-btn">1</button> | |
41 | + <button>2</button> | |
42 | + <button>3</button> | |
43 | + <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> | |
44 | + </article> | |
45 | + <div class="flex justify-end "> | |
46 | + <button type="button" title="등록" class="new-btn" @click="goToPage('C_QuestionInsert')"> | |
47 | + 등록 | |
48 | + </button> | |
49 | + </div> | |
50 | + </div> | |
51 | +</template> | |
52 | + | |
53 | +<script> | |
54 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
55 | +import { mdiMagnify} from '@mdi/js'; | |
56 | + | |
57 | + | |
58 | +export default { | |
59 | + data () { | |
60 | + return { | |
61 | + mdiMagnify: mdiMagnify, | |
62 | + } | |
63 | + }, | |
64 | + methods: { | |
65 | + goToPage(page) { | |
66 | + this.$router.push({ name: page }); | |
67 | + }, | |
68 | + showConfirm(type) { | |
69 | + let message = ''; | |
70 | + if (type === 'cancel') { | |
71 | + message = '삭제하시겠습니까?'; | |
72 | + } else if (type === 'reset') { | |
73 | + message = '초기화하시겠습니까?'; | |
74 | + } else if (type === 'save') { | |
75 | + message = '등록하시겠습니까?'; | |
76 | + } | |
77 | + | |
78 | + if (confirm(message)) { | |
79 | + this.goBack(); | |
80 | + } | |
81 | + }, | |
82 | + | |
83 | + }, | |
84 | + watch: { | |
85 | + | |
86 | + }, | |
87 | + computed: { | |
88 | + | |
89 | + }, | |
90 | + components:{ | |
91 | + SvgIcon | |
92 | + }, | |
93 | + mounted() { | |
94 | + console.log('Main2 mounted'); | |
95 | + } | |
96 | +} | |
97 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_TextBookDetail.vue
... | ... | @@ -0,0 +1,121 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">A교재</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="">A 반</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="board-wrap"> | |
9 | + <label for="" class="title1">단원</label> | |
10 | + <div class="unit-pagination flex mt10" style="gap: 10px;"> | |
11 | + <button class="selected-btn">1</button> | |
12 | + <button>2</button> | |
13 | + <button>3</button> | |
14 | + </div> | |
15 | + <hr> | |
16 | + <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('C_TextList')"> | |
17 | + <label for="" class="title1">지문</label> | |
18 | + <div class="flex align-center " style="gap: 10px;"> | |
19 | + <p>00개</p> | |
20 | + <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> | |
21 | + </div> | |
22 | + </div> | |
23 | + <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('C_QuestionList')"> | |
24 | + <label for="" class="title1">문제</label> | |
25 | + <div class="flex align-center " style="gap: 10px;"> | |
26 | + <p>00개</p> | |
27 | + <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> | |
28 | + </div> | |
29 | + </div> | |
30 | + <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('C_Voca_List')"> | |
31 | + <label for="" class="title1">단어</label> | |
32 | + <div class="flex align-center " style="gap: 10px;"> | |
33 | + <p>00개</p> | |
34 | + <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> | |
35 | + </div> | |
36 | + </div> | |
37 | + <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('C_ExamList')"> | |
38 | + <label for="" class="title1">중간 평가</label> | |
39 | + <div class="flex align-center " style="gap: 10px;"> | |
40 | + <p>00개</p> | |
41 | + <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> | |
42 | + </div> | |
43 | + </div> | |
44 | + <div class="bookmanage-btn flex justify-between align-center" @click="goToPage('C_ExamList')"> | |
45 | + <label for="" class="title1">최종 평가</label> | |
46 | + <div class="flex align-center " style="gap: 10px;"> | |
47 | + <p>00개</p> | |
48 | + <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> | |
49 | + </div> | |
50 | + </div> | |
51 | + </div> | |
52 | + <div class="flex justify-end mt30" style="gap: 10px;"> | |
53 | + <!-- <button type="button" title="" class="new-btn" @click="showConfirm('delete')"> | |
54 | + 추가 | |
55 | + </button> --> | |
56 | + <button type="button" title="" class="new-btn" @click="goToPage('RoadMap')"> | |
57 | + 로드맵 | |
58 | + </button> | |
59 | + <button type="button" title="" class="new-btn" @click="showConfirm('delete')"> | |
60 | + 삭제 | |
61 | + </button> | |
62 | + </div> | |
63 | +</template> | |
64 | + | |
65 | +<script> | |
66 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
67 | +import { mdiMagnify, mdilArrowRight } from '@mdi/js'; | |
68 | +import ProgressBar from '../../component/ProgressBar.vue'; | |
69 | + | |
70 | + | |
71 | +export default { | |
72 | + data() { | |
73 | + return { | |
74 | + mdiMagnify: mdiMagnify, | |
75 | + mdilArrowRight: mdilArrowRight, | |
76 | + timer: "00:00", | |
77 | + progress: 20 | |
78 | + } | |
79 | + }, | |
80 | + methods: { | |
81 | + goToPage(page) { | |
82 | + this.$router.push({ name: page }); | |
83 | + }, | |
84 | + increaseProgress() { | |
85 | + if (this.progress < 100) { | |
86 | + this.progress += 10; | |
87 | + } | |
88 | + }, | |
89 | + showConfirm(type) { | |
90 | + let message = ''; | |
91 | + if (type === 'delete') { | |
92 | + message = '삭제하시겠습니까?'; | |
93 | + } else if (type === 'reset') { | |
94 | + message = '초기화하시겠습니까?'; | |
95 | + } else if (type === 'save') { | |
96 | + message = '등록하시겠습니까?'; | |
97 | + } | |
98 | + | |
99 | + if (confirm(message)) { | |
100 | + this.goBack(); | |
101 | + } | |
102 | + }, | |
103 | + }, | |
104 | + watch: { | |
105 | + | |
106 | + }, | |
107 | + computed: { | |
108 | + | |
109 | + }, | |
110 | + components: { | |
111 | + SvgIcon, | |
112 | + ProgressBar | |
113 | + }, | |
114 | + mounted() { | |
115 | + console.log('Main2 mounted'); | |
116 | + } | |
117 | +} | |
118 | +</script> | |
119 | +<style scoped> | |
120 | +.bookmanage-btn:hover{background-color: #FFF3D7;} | |
121 | +</style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_TextInsert.vue
... | ... | @@ -0,0 +1,64 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">지문 등록</p> | |
4 | + </div> | |
5 | + <div class="board-wrap"> | |
6 | + <div class="flex align-center mb20"> | |
7 | + <label for="" class="title2">제목</label> | |
8 | + <input type="text" class="data-wrap"> | |
9 | + </div> | |
10 | + <div class="flex align-center"> | |
11 | + <label for="" class="title2">URL</label> | |
12 | + <input type="text" class="data-wrap"> | |
13 | + </div> | |
14 | + <hr> | |
15 | + <div class="flex align-center"> | |
16 | + <label for="" class="title2">스크립트</label> | |
17 | + <textarea name="" id="" class="data-wrap"></textarea> | |
18 | + </div> | |
19 | + </div> | |
20 | + <div class="flex justify-between mt50"> | |
21 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('C_TextList')"> | |
22 | + 목록 | |
23 | + </button> | |
24 | + <div class="flex"> | |
25 | + <button type="button" title="글쓰기" class="new-btn mr10" > | |
26 | + 수정 | |
27 | + </button> | |
28 | + <button type="button" title="글쓰기" class="new-btn" > | |
29 | + 삭제 | |
30 | + </button> | |
31 | + </div> | |
32 | + </div> | |
33 | +</template> | |
34 | + | |
35 | +<script> | |
36 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
37 | +import { mdiMagnify} from '@mdi/js'; | |
38 | + | |
39 | + | |
40 | +export default { | |
41 | + data () { | |
42 | + return { | |
43 | + mdiMagnify: mdiMagnify, | |
44 | + } | |
45 | + }, | |
46 | + methods: { | |
47 | + goToPage(page) { | |
48 | + this.$router.push({ name: page }); | |
49 | + }, | |
50 | + }, | |
51 | + watch: { | |
52 | + | |
53 | + }, | |
54 | + computed: { | |
55 | + | |
56 | + }, | |
57 | + components:{ | |
58 | + SvgIcon | |
59 | + }, | |
60 | + mounted() { | |
61 | + console.log('Main2 mounted'); | |
62 | + } | |
63 | +} | |
64 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_TextList .vue
... | ... | @@ -0,0 +1,95 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">지문</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="">1단원</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="search-wrap flex justify-end mb20"> | |
9 | + <select name="" id="" class="mr10 data-wrap"> | |
10 | + <option value="">전체</option> | |
11 | + </select> | |
12 | + <input type="text" placeholder="검색하세요."> | |
13 | + <button type="button" title="위원회 검색"> | |
14 | + <img src="../../../resources/img/look_t.png" alt=""> | |
15 | + </button> | |
16 | + </div> | |
17 | + <div class="table-wrap"> | |
18 | + <table> | |
19 | + <thead> | |
20 | + <td>No.</td> | |
21 | + <td>제목</td> | |
22 | + <td>내용</td> | |
23 | + <td>작성자</td> | |
24 | + <td>등록일</td> | |
25 | + </thead> | |
26 | + <tbody> | |
27 | + <tr @click="goToPage('C_TextInsert')"> | |
28 | + <td></td> | |
29 | + <td></td> | |
30 | + <td></td> | |
31 | + <td></td> | |
32 | + <td></td> | |
33 | + </tr> | |
34 | + </tbody> | |
35 | + </table> | |
36 | + <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> | |
37 | + <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button> | |
38 | + <button class="selected-btn">1</button> | |
39 | + <button>2</button> | |
40 | + <button>3</button> | |
41 | + <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> | |
42 | + </article> | |
43 | + <div class="flex justify-end "> | |
44 | + <button type="button" title="등록" class="new-btn" @click="goToPage('C_TextInsert')"> | |
45 | + 등록 | |
46 | + </button> | |
47 | + </div> | |
48 | + </div> | |
49 | +</template> | |
50 | + | |
51 | +<script> | |
52 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
53 | +import { mdiMagnify} from '@mdi/js'; | |
54 | + | |
55 | + | |
56 | +export default { | |
57 | + data () { | |
58 | + return { | |
59 | + mdiMagnify: mdiMagnify, | |
60 | + } | |
61 | + }, | |
62 | + methods: { | |
63 | + goToPage(page) { | |
64 | + this.$router.push({ name: page }); | |
65 | + }, | |
66 | + showConfirm(type) { | |
67 | + let message = ''; | |
68 | + if (type === 'cancel') { | |
69 | + message = '삭제하시겠습니까?'; | |
70 | + } else if (type === 'reset') { | |
71 | + message = '초기화하시겠습니까?'; | |
72 | + } else if (type === 'save') { | |
73 | + message = '등록하시겠습니까?'; | |
74 | + } | |
75 | + | |
76 | + if (confirm(message)) { | |
77 | + this.goBack(); | |
78 | + } | |
79 | + }, | |
80 | + | |
81 | + }, | |
82 | + watch: { | |
83 | + | |
84 | + }, | |
85 | + computed: { | |
86 | + | |
87 | + }, | |
88 | + components:{ | |
89 | + SvgIcon | |
90 | + }, | |
91 | + mounted() { | |
92 | + console.log('Main2 mounted'); | |
93 | + } | |
94 | +} | |
95 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_Textbook.vue
... | ... | @@ -0,0 +1,115 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">교재</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="">A반</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="content-t"> | |
9 | + <div class=" flex " style="gap: 50px;"> | |
10 | + <div class="textbook"> | |
11 | + <div class="box " style="gap: 10px;" @click="goToPage('C_TextBookDetail')"> | |
12 | + </div> | |
13 | + <div class="text "> | |
14 | + <p class="title1" style="color: #fff;">A 교재</p> | |
15 | + <div class="btnGroup mt15 flex align-center justify-end" style="gap: 10px;"> | |
16 | + <button>수정</button><p>|</p> | |
17 | + <button @click="showConfirm('delete')">삭제</button> | |
18 | + </div> | |
19 | + </div> | |
20 | + </div> | |
21 | + | |
22 | + <div class="textbook-add"> | |
23 | + <button @click="buttonSearch"><img src="../../../resources/img/btn32_98t_normal.png" alt=""></button> | |
24 | + | |
25 | + </div> | |
26 | + </div> | |
27 | + </div> | |
28 | + <div v-show="searchOpen" class="popup-wrap"> | |
29 | + <div class="popup-box "> | |
30 | + <div class="flex justify-between mb30"> | |
31 | + <p class="popup-title">교재 이름</p> | |
32 | + <button type="button" class="popup-close-btn" @click="closeBtn"> | |
33 | + <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> | |
34 | + | |
35 | + </button> | |
36 | + </div> | |
37 | + <div class="search-wrap mb30"> | |
38 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
39 | + <option value="bbsTtl">제목</option> | |
40 | + <option value="bbsCnt">내용</option> | |
41 | + <option value="userNm">작성자</option> | |
42 | + <option value="bbsCls">카테고리</option> | |
43 | + </select> | |
44 | + </div> | |
45 | + <div class="flex justify-center "> | |
46 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
47 | + 취소 | |
48 | + </button> | |
49 | + <button type="button" title="글쓰기" class="new-btn"> | |
50 | + 등록 | |
51 | + </button> | |
52 | + </div> | |
53 | + </div> | |
54 | + </div> | |
55 | +</template> | |
56 | + | |
57 | +<script> | |
58 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
59 | +import { mdiMagnify, mdiWindowClose } from '@mdi/js'; | |
60 | + | |
61 | +export default { | |
62 | + data () { | |
63 | + return { | |
64 | + mdiWindowClose: mdiWindowClose, | |
65 | + showModal: false, | |
66 | + searchOpen: false, | |
67 | + } | |
68 | + }, | |
69 | + methods: { | |
70 | + goToPage(page) { | |
71 | + this.$router.push({ name: page }); | |
72 | + }, | |
73 | + closeModal() { | |
74 | + this.showModal = false; | |
75 | + }, | |
76 | + buttonSearch() { | |
77 | + this.searchOpen = true; | |
78 | + }, | |
79 | + closeBtn() { | |
80 | + this.searchOpen = false; | |
81 | + | |
82 | + }, | |
83 | + showConfirm(type) { | |
84 | + let message = ''; | |
85 | + if (type === 'delete') { | |
86 | + message = '삭제하시겠습니까?'; | |
87 | + } else if (type === 'reset') { | |
88 | + message = '초기화하시겠습니까?'; | |
89 | + } else if (type === 'save') { | |
90 | + message = '등록하시겠습니까?'; | |
91 | + } | |
92 | + | |
93 | + if (confirm(message)) { | |
94 | + this.goBack(); | |
95 | + } | |
96 | + }, | |
97 | + | |
98 | + }, | |
99 | + watch: { | |
100 | + | |
101 | + }, | |
102 | + computed: { | |
103 | + | |
104 | + }, | |
105 | + components: { | |
106 | + SvgIcon | |
107 | + }, | |
108 | + mounted() { | |
109 | + console.log('Main2 mounted'); | |
110 | + } | |
111 | +} | |
112 | +</script> | |
113 | +<style scoped> | |
114 | +.textbook{width: 300px;} | |
115 | +</style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/C_Voca_List.vue
... | ... | @@ -0,0 +1,184 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">단어장</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="UNIT_000000000000001">1단원</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="search-wrap flex justify-between mb20 align-center"> | |
9 | + <div class="title2 gray">?단원 전체 목록</div> | |
10 | + <div> | |
11 | + <select name="" id="" class="mr10 data-wrap"> | |
12 | + <option value="">지문</option> | |
13 | + <option value="">단어</option> | |
14 | + </select> | |
15 | + <input type="text" placeholder="검색하세요."> | |
16 | + <button type="button" title="단어장 검색"> | |
17 | + <img src="../../../resources/img/look_t.png" alt=""> | |
18 | + </button> | |
19 | + </div> | |
20 | + </div> | |
21 | + <div class="table-wrap"> | |
22 | + <table> | |
23 | + <thead> | |
24 | + <td>No.</td> | |
25 | + <td>지문</td> | |
26 | + <td>단어 목록</td> | |
27 | + <td>작성자</td> | |
28 | + <td>등록일</td> | |
29 | + </thead> | |
30 | + <tbody> | |
31 | + <tr v-for="(wordBook, index) in dataList" :key="wordBook.wdBookId" @click="goToViewPage('noticeDetail')"> | |
32 | + <td>{{ createNo(index) }}</td> | |
33 | + <td>{{ wordBook.textTtl }}</td> | |
34 | + <td>{{ wordBook.wordsPreview }}</td> | |
35 | + <td>{{ wordBook.userId }}</td> | |
36 | + <td>{{ '' }}</td> | |
37 | + </tr> | |
38 | + </tbody> | |
39 | + </table> | |
40 | + <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> | |
41 | + <button @click="goToPage(currentPage - 1)"> | |
42 | + <img src="../../../resources/img/btn27_90t_normal.png" alt=""> | |
43 | + </button> | |
44 | + <button v-for="page in paginationButtons" :key="page" @click="goToPage(page - 1)" :class="{ 'selected-btn': currentPage === page - 1 }"> | |
45 | + {{ page }} | |
46 | + </button> | |
47 | + <button @click="goToPage(currentPage + 1)"> | |
48 | + <img src="../../../resources/img/btn28_90t_normal.png" alt=""> | |
49 | + </button> | |
50 | + </article> | |
51 | + <div class="flex justify-end "> | |
52 | + <button type="button" title="등록" class="new-btn" @click="goToPage('noticeInsert')"> | |
53 | + 등록 | |
54 | + </button> | |
55 | + </div> | |
56 | + </div> | |
57 | +</template> | |
58 | + | |
59 | +<script> | |
60 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
61 | +import { mdiMagnify } from '@mdi/js'; | |
62 | +import axios from "axios"; | |
63 | + | |
64 | + | |
65 | +export default { | |
66 | + data () { | |
67 | + return { | |
68 | + mdiMagnify: mdiMagnify, | |
69 | + dataList: [], | |
70 | + currentPage: 0, | |
71 | + itemsPerPage: 2, | |
72 | + totalPosts: 0, | |
73 | + unitId: "UNIT_000000000000001" | |
74 | + } | |
75 | + }, | |
76 | + methods: { | |
77 | + | |
78 | + dataSelectList() { | |
79 | + const vm = this; | |
80 | + axios({ | |
81 | + url: "/wordbook/findByUnitId.json", | |
82 | + method: "post", | |
83 | + headers: { | |
84 | + "Content-Type": "application/json; charset=UTF-8", | |
85 | + }, | |
86 | + data: { | |
87 | + unitId: vm.unitId, | |
88 | + page: vm.currentPage + 1, | |
89 | + pageSize: vm.itemsPerPage | |
90 | + }, | |
91 | + }) | |
92 | + .then(function (response) { | |
93 | + console.log("dataList - response: ", response.data); | |
94 | + const wordBooks = response.data.wordBooks; | |
95 | + vm.totalPosts = response.data.totalWordBooks; | |
96 | + | |
97 | + // 지문 제목 및 단어 목록 가져오기 | |
98 | + const fetchDataPromises = wordBooks.map(wordBook => { | |
99 | + const textTitlePromise = axios.post("/text/selectOneText.json", { | |
100 | + textId: wordBook.textId | |
101 | + }).then(textResponse => { | |
102 | + wordBook.textTtl = textResponse.data[0].text_ttl; | |
103 | + }).catch(error => { | |
104 | + console.error(`${wordBook.textId}으로 지문 제목 가져오기 실패: `, error); | |
105 | + wordBook.textTtl = '제목값없음'; // 오류 시 기본값 설정 | |
106 | + }); | |
107 | + | |
108 | + const wordsPromise = axios.post("/word/getWordsByBookId.json", { | |
109 | + wdBookId: wordBook.wdBookId | |
110 | + }).then(wordsResponse => { | |
111 | + const words = wordsResponse.data.map(word => word.wdNm); | |
112 | + wordBook.wordsPreview = vm.generateWordsPreview(words); | |
113 | + }).catch(error => { | |
114 | + console.error(`${wordBook.wdBookId}으로 단어 목록 가져오기 실패: `, error); | |
115 | + wordBook.wordsPreview = '단어값없음'; // 오류 시 기본값 설정 | |
116 | + }); | |
117 | + | |
118 | + return Promise.all([textTitlePromise, wordsPromise]); | |
119 | + }); | |
120 | + | |
121 | + // 모든 데이터 가져오기 작업이 완료되면 dataList에 데이터 설정 | |
122 | + Promise.all(fetchDataPromises).then(() => { | |
123 | + vm.dataList = wordBooks; | |
124 | + }); | |
125 | + }) | |
126 | + .catch(function (error) { | |
127 | + console.log("dataList - error: ", error); | |
128 | + alert("단어장 목록 조회에 오류가 발생했습니다."); | |
129 | + }); | |
130 | + }, | |
131 | + generateWordsPreview(words) { | |
132 | + const maxLength = 20; // 최대 표시 길이 설정 | |
133 | + const wordString = words.join(', '); | |
134 | + | |
135 | + if (wordString.length > maxLength) { | |
136 | + return wordString.substring(0, maxLength) + '...'; | |
137 | + } else { | |
138 | + return wordString; | |
139 | + } | |
140 | + }, | |
141 | + createNo(index) { | |
142 | + return this.totalPosts - (this.currentPage * this.itemsPerPage + index); | |
143 | + }, | |
144 | + goToPage(page) { | |
145 | + if (page < 0 || page >= this.totalPages) { | |
146 | + return; | |
147 | + } | |
148 | + this.currentPage = page; | |
149 | + this.dataSelectList(); | |
150 | + }, | |
151 | + goToViewPage(page) { | |
152 | + this.$router.push({ name: page }); | |
153 | + }, | |
154 | + }, | |
155 | + watch: { | |
156 | + | |
157 | + }, | |
158 | + computed: { | |
159 | + totalPages() { | |
160 | + return Math.ceil(this.totalPosts / this.itemsPerPage); | |
161 | + }, | |
162 | + paginationButtons() { | |
163 | + let start = Math.max(0, this.currentPage - 2); | |
164 | + let end = Math.min(start + 5, this.totalPages); | |
165 | + | |
166 | + if (end - start < 5) { | |
167 | + start = Math.max(0, end - 5); | |
168 | + } | |
169 | + | |
170 | + return Array.from({ length: end - start }, (_, i) => start + i + 1); | |
171 | + }, | |
172 | + startIndex() { | |
173 | + return this.currentPage * this.itemsPerPage; | |
174 | + } | |
175 | + }, | |
176 | + components:{ | |
177 | + SvgIcon | |
178 | + }, | |
179 | + mounted() { | |
180 | + console.log('Voca Book List Component mounted'); | |
181 | + this.dataSelectList(); | |
182 | + } | |
183 | +} | |
184 | +</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/ClassDetail.vue
+++ client/views/pages/teacher/ClassDetail.vue
... | ... | @@ -1,149 +1,218 @@ |
1 | 1 |
<template> |
2 |
- <div class="title-box flex justify-between mb40"> |
|
3 |
- <p class="title">반 관리</p> |
|
2 |
+ <div class="title-box flex justify-between mb40"> |
|
3 |
+ <p class="title">반 관리</p> |
|
4 |
+ </div> |
|
5 |
+ <div class="wrap mb30"> |
|
6 |
+ <div class="flex justify-between mb30 align-center"> |
|
7 |
+ <label for="" class="title1">게시판</label> |
|
8 |
+ <div class="look-btn flex align-center" @click="goToPage('Board')"> |
|
9 |
+ <p>자세히 보기</p> |
|
10 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class="ml10"></svg-icon> |
|
11 |
+ </div> |
|
12 |
+ </div> |
|
13 |
+ <div class="table-wrap"> |
|
14 |
+ <table> |
|
15 |
+ <thead> |
|
16 |
+ <td>No.</td> |
|
17 |
+ <td>제목</td> |
|
18 |
+ <td>내용</td> |
|
19 |
+ <td>작성자</td> |
|
20 |
+ <td>등록일</td> |
|
21 |
+ </thead> |
|
22 |
+ <tbody> |
|
23 |
+ <tr |
|
24 |
+ v-for="(item, index) in dataList" |
|
25 |
+ :key="item.id" |
|
26 |
+ :class="{ 'selected-row': selectedRow == item.dataList }" |
|
27 |
+ @click="[goToPage('noticeDetail'), selectBoardList(item)]" |
|
28 |
+ > |
|
29 |
+ <td>{{ totalPosts - index }}</td> |
|
30 |
+ <td>{{ item.bbsTtl }}</td> |
|
31 |
+ <td>{{ item.bbsCls }}</td> |
|
32 |
+ <td>{{ userNm }}</td> |
|
33 |
+ <td>{{ item.bbsTm.substr(0, 16) }}</td> |
|
34 |
+ </tr> |
|
35 |
+ </tbody> |
|
36 |
+ </table> |
|
37 |
+ </div> |
|
38 |
+ </div> |
|
39 |
+ <div class="flex justify-between" style="gap: 30px"> |
|
40 |
+ <div class="wrap mb30"> |
|
41 |
+ <div class="flex justify-between mb30 align-center"> |
|
42 |
+ <label for="" class="title1">학생 목록</label> |
|
43 |
+ <div class="look-btn align-center flex"> |
|
44 |
+ <p>자세히 보기</p> |
|
45 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class="ml10"></svg-icon> |
|
46 |
+ </div> |
|
47 |
+ </div> |
|
48 |
+ <div class="table-wrap"> |
|
49 |
+ <table> |
|
50 |
+ <thead> |
|
51 |
+ <td>No.</td> |
|
52 |
+ <td>이름</td> |
|
53 |
+ <td>학년</td> |
|
54 |
+ <td>반</td> |
|
55 |
+ </thead> |
|
56 |
+ <tbody> |
|
57 |
+ <tr> |
|
58 |
+ <td></td> |
|
59 |
+ <td></td> |
|
60 |
+ <td></td> |
|
61 |
+ <td></td> |
|
62 |
+ </tr> |
|
63 |
+ </tbody> |
|
64 |
+ </table> |
|
65 |
+ </div> |
|
4 | 66 |
</div> |
5 | 67 |
<div class="wrap mb30"> |
6 |
- <div class="flex justify-between mb30 align-center"> |
|
7 |
- <label for="" class="title1">학습 현황</label> |
|
8 |
- <div class="look-btn flex align-center"> |
|
9 |
- <p>자세히 보기 </p> |
|
10 |
- <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
68 |
+ <div class="flex justify-between mb30 align-center"> |
|
69 |
+ <label for="" class="title1">책 </label> |
|
70 |
+ <div class="align-center flex look-btn"> |
|
71 |
+ <p>자세히 보기</p> |
|
72 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class="ml10"></svg-icon> |
|
73 |
+ </div> |
|
74 |
+ </div> |
|
75 |
+ <div class="flex" style="gap: 50px"> |
|
76 |
+ <div class="textbook"> |
|
77 |
+ <div class="box" style="gap: 10px"></div> |
|
78 |
+ <div class="text"> |
|
79 |
+ <p class="title1" style="color: #fff">A 교재</p> |
|
80 |
+ <div |
|
81 |
+ class="btnGroup mt15 flex align-center justify-end" |
|
82 |
+ style="gap: 10px" |
|
83 |
+ > |
|
84 |
+ <button>수정</button> |
|
85 |
+ <p>|</p> |
|
86 |
+ <button @click="showConfirm('delete')">삭제</button> |
|
11 | 87 |
</div> |
88 |
+ </div> |
|
12 | 89 |
</div> |
13 |
- <div class="table-wrap"> |
|
14 |
- <table> |
|
15 |
- <thead> |
|
16 |
- <td>No.</td> |
|
17 |
- <td>제목</td> |
|
18 |
- <td>내용</td> |
|
19 |
- <td>작성자</td> |
|
20 |
- <td>등록일</td> |
|
21 |
- </thead> |
|
22 |
- <tbody> |
|
23 |
- <tr> |
|
24 |
- <td></td> |
|
25 |
- <td></td> |
|
26 |
- <td></td> |
|
27 |
- <td></td> |
|
28 |
- <td></td> |
|
29 |
- </tr> |
|
30 |
- </tbody> |
|
31 |
- </table> |
|
90 |
+ <div class="textbook"> |
|
91 |
+ <div class="box" style="gap: 10px"></div> |
|
92 |
+ <div class="text"> |
|
93 |
+ <p class="title1" style="color: #fff">A 교재</p> |
|
94 |
+ <div |
|
95 |
+ class="btnGroup mt15 flex align-center justify-end" |
|
96 |
+ style="gap: 10px" |
|
97 |
+ > |
|
98 |
+ <button>수정</button> |
|
99 |
+ <p>|</p> |
|
100 |
+ <button @click="showConfirm('delete')">삭제</button> |
|
101 |
+ </div> |
|
102 |
+ </div> |
|
32 | 103 |
</div> |
104 |
+ </div> |
|
33 | 105 |
</div> |
34 |
- <div class="flex justify-between" style="gap: 30px;"> |
|
35 |
- <div class="wrap mb30"> |
|
36 |
- <div class="flex justify-between mb30 align-center"> |
|
37 |
- <label for="" class="title1">학생 목록</label> |
|
38 |
- <div class="look-btn align-center flex"> |
|
39 |
- <p>자세히 보기 </p> |
|
40 |
- <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
41 |
- </div> |
|
42 |
- </div> |
|
43 |
- <div class="table-wrap"> |
|
44 |
- <table> |
|
45 |
- <thead> |
|
46 |
- <td>No.</td> |
|
47 |
- <td>이름</td> |
|
48 |
- <td>학년</td> |
|
49 |
- <td>반</td> |
|
50 |
- </thead> |
|
51 |
- <tbody> |
|
52 |
- <tr> |
|
53 |
- <td></td> |
|
54 |
- <td></td> |
|
55 |
- <td></td> |
|
56 |
- <td></td> |
|
57 |
- </tr> |
|
58 |
- </tbody> |
|
59 |
- </table> |
|
60 |
- </div> |
|
61 |
- </div> |
|
62 |
- <div class="wrap mb30"> |
|
63 |
- <div class="flex justify-between mb30 align-center"> |
|
64 |
- <label for="" class="title1">책 </label> |
|
65 |
- <div class="align-center flex look-btn"><p>자세히 보기 </p><svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon></div> |
|
66 |
- </div> |
|
67 |
- <div class=" flex " style="gap: 50px;"> |
|
68 |
- <div class="textbook"> |
|
69 |
- <div class="box " style="gap: 10px;"> |
|
70 |
- </div> |
|
71 |
- <div class="text "> |
|
72 |
- <p class="title1" style="color: #fff;">A 교재</p> |
|
73 |
- <div class="btnGroup mt15 flex align-center justify-end" style="gap: 10px;"> |
|
74 |
- <button>수정</button><p>|</p> |
|
75 |
- <button @click="showConfirm('delete')">삭제</button> |
|
76 |
- </div> |
|
77 |
- </div> |
|
78 |
- </div> |
|
79 |
- <div class="textbook"> |
|
80 |
- <div class="box " style="gap: 10px;"> |
|
81 |
- </div> |
|
82 |
- <div class="text "> |
|
83 |
- <p class="title1" style="color: #fff;">A 교재</p> |
|
84 |
- <div class="btnGroup mt15 flex align-center justify-end" style="gap: 10px;"> |
|
85 |
- <button>수정</button><p>|</p> |
|
86 |
- <button @click="showConfirm('delete')">삭제</button> |
|
87 |
- </div> |
|
88 |
- </div> |
|
89 |
- </div> |
|
90 |
- </div> |
|
91 |
- </div> |
|
92 |
- </div> |
|
106 |
+ </div> |
|
93 | 107 |
</template> |
94 | 108 |
|
95 | 109 |
<script> |
96 |
-import SvgIcon from '@jamescoyle/vue-icon'; |
|
97 |
-import { mdiMagnify, } from '@mdi/js'; |
|
98 |
-import { mdilArrowRight } from '@mdi/light-js'; |
|
99 |
-import ProgressBar from '../../component/ProgressBar.vue'; |
|
100 |
- |
|
110 |
+import SvgIcon from "@jamescoyle/vue-icon"; |
|
111 |
+import { mdiMagnify } from "@mdi/js"; |
|
112 |
+import { mdilArrowRight } from "@mdi/light-js"; |
|
113 |
+import ProgressBar from "../../component/ProgressBar.vue"; |
|
114 |
+import axios from "axios"; |
|
101 | 115 |
|
102 | 116 |
export default { |
103 |
- data() { |
|
104 |
- return { |
|
105 |
- mdiMagnify: mdiMagnify, |
|
106 |
- mdilArrowRight: mdilArrowRight, |
|
107 |
- timer: "00:00", |
|
108 |
- progress: 20 |
|
109 |
- } |
|
110 |
- }, |
|
111 |
- methods: { |
|
112 |
- goToPage(page) { |
|
113 |
- this.$router.push({ name: page }); |
|
114 |
- }, |
|
115 |
- increaseProgress() { |
|
116 |
- if (this.progress < 100) { |
|
117 |
- this.progress += 10; |
|
118 |
- } |
|
119 |
- }, |
|
120 |
- showConfirm(type) { |
|
121 |
- let message = ''; |
|
122 |
- if (type === 'cancel') { |
|
123 |
- message = '삭제하시겠습니까?'; |
|
124 |
- } else if (type === 'reset') { |
|
125 |
- message = '초기화하시겠습니까?'; |
|
126 |
- } else if (type === 'save') { |
|
127 |
- message = '등록하시겠습니까?'; |
|
128 |
- } |
|
117 |
+ data() { |
|
118 |
+ return { |
|
119 |
+ mdiMagnify: mdiMagnify, |
|
120 |
+ mdilArrowRight: mdilArrowRight, |
|
121 |
+ timer: "00:00", |
|
122 |
+ progress: 20, |
|
129 | 123 |
|
130 |
- if (confirm(message)) { |
|
131 |
- this.goBack(); |
|
132 |
- } |
|
124 |
+ // 교사 홈페이지에서 쿼리 파라미터로부터 전달받은 선택된 반의 아이디 |
|
125 |
+ selectedClassId: this.$route.query.sclsId, |
|
126 |
+ |
|
127 |
+ // 게시글 정보 |
|
128 |
+ dataList: [], |
|
129 |
+ totalPosts: 0, |
|
130 |
+ selectedRow: "", |
|
131 |
+ bbsTm: "", |
|
132 |
+ |
|
133 |
+ // 페이징 |
|
134 |
+ currentPage: 0, |
|
135 |
+ itemsPerPage: 5, |
|
136 |
+ |
|
137 |
+ // 반 아이디 |
|
138 |
+ sclsId: "", |
|
139 |
+ }; |
|
140 |
+ }, |
|
141 |
+ methods: { |
|
142 |
+ goToPage(page) { |
|
143 |
+ this.$router.push({ name: page }); |
|
144 |
+ }, |
|
145 |
+ increaseProgress() { |
|
146 |
+ if (this.progress < 100) { |
|
147 |
+ this.progress += 10; |
|
148 |
+ } |
|
149 |
+ }, |
|
150 |
+ showConfirm(type) { |
|
151 |
+ let message = ""; |
|
152 |
+ if (type === "cancel") { |
|
153 |
+ message = "삭제하시겠습니까?"; |
|
154 |
+ } else if (type === "reset") { |
|
155 |
+ message = "초기화하시겠습니까?"; |
|
156 |
+ } else if (type === "save") { |
|
157 |
+ message = "등록하시겠습니까?"; |
|
158 |
+ } |
|
159 |
+ |
|
160 |
+ if (confirm(message)) { |
|
161 |
+ this.goBack(); |
|
162 |
+ } |
|
163 |
+ }, |
|
164 |
+ |
|
165 |
+ // 게시글 조회 |
|
166 |
+ boardList() { |
|
167 |
+ const vm = this; |
|
168 |
+ axios({ |
|
169 |
+ url: "/board/findAll.json", |
|
170 |
+ method: "post", |
|
171 |
+ headers: { |
|
172 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
133 | 173 |
}, |
134 |
- }, |
|
135 |
- watch: { |
|
174 |
+ data: { |
|
175 |
+ page: vm.currentPage + 1, |
|
176 |
+ pageSize: vm.itemsPerPage, |
|
177 |
+ sclsId: vm.selectedClassId, |
|
178 |
+ }, |
|
179 |
+ }) |
|
180 |
+ .then(function (res) { |
|
181 |
+ console.log("dataList - response : ", res.data); |
|
136 | 182 |
|
137 |
- }, |
|
138 |
- computed: { |
|
183 |
+ vm.dataList = res.data.result[0].boardClass[0].board; |
|
184 |
+ vm.userNm = res.data.result[0].userNm; |
|
185 |
+ vm.userId = res.data.result[0].userId; |
|
186 |
+ vm.totalPosts = res.data.totalBoard; |
|
139 | 187 |
|
188 |
+ console.log(vm.userId); |
|
189 |
+ }) |
|
190 |
+ .catch(function (error) { |
|
191 |
+ console.log("result - error : ", error); |
|
192 |
+ }); |
|
140 | 193 |
}, |
141 |
- components: { |
|
142 |
- SvgIcon, |
|
143 |
- ProgressBar |
|
194 |
+ setClassId() { |
|
195 |
+ sessionStorage.setItem("sclsId", JSON.stringify(this.selectedClassId)); |
|
196 |
+ sessionStorage.removeItem("selectedBoardList"); |
|
197 |
+ sessionStorage.removeItem("file"); |
|
198 |
+ this.boardList(); |
|
144 | 199 |
}, |
145 |
- mounted() { |
|
146 |
- console.log('Main2 mounted'); |
|
147 |
- } |
|
148 |
-} |
|
149 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
200 |
+ |
|
201 |
+ // 게시글 정보 세션에 저장 |
|
202 |
+ selectBoardList(item) { |
|
203 |
+ sessionStorage.setItem("selectedBoardList", JSON.stringify(item)); |
|
204 |
+ }, |
|
205 |
+ }, |
|
206 |
+ watch: {}, |
|
207 |
+ computed: {}, |
|
208 |
+ components: { |
|
209 |
+ SvgIcon, |
|
210 |
+ ProgressBar, |
|
211 |
+ }, |
|
212 |
+ mounted() { |
|
213 |
+ console.log("Main2 mounted"); |
|
214 |
+ //console.log(`반 페이지 sclsId(반 아이디) 확인 : ${this.selectedClassId}`); |
|
215 |
+ this.setClassId(); |
|
216 |
+ }, |
|
217 |
+}; |
|
218 |
+</script> |
--- client/views/pages/teacher/ExamDetail.vue
+++ client/views/pages/teacher/ExamDetail.vue
... | ... | @@ -18,8 +18,8 @@ |
18 | 18 |
<tr> |
19 | 19 |
<td>1</td> |
20 | 20 |
<td>1</td> |
21 |
- <td><button type="button" title="보기" class="new-btn"> |
|
22 |
- 보기 |
|
21 |
+ <td><button type="button" title="수정" class="new-btn"> |
|
22 |
+ 수정 |
|
23 | 23 |
</button></td> |
24 | 24 |
</tr> |
25 | 25 |
</tbody> |
+++ client/views/pages/teacher/ExamInsert.vue
... | ... | @@ -0,0 +1,131 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">평가 등록</p> | |
4 | + </div> | |
5 | + <!-- <label for="" class="title1">문제 리스트</label> | |
6 | + <table class="mt20 mb100"> | |
7 | + <colgroup> | |
8 | + <col style="width: 10%;"> | |
9 | + <col style="width: 70%;"> | |
10 | + <col style="width: 20%;"> | |
11 | + </colgroup> | |
12 | + <thead> | |
13 | + <td>No.</td> | |
14 | + <td>문제</td> | |
15 | + <td>보기</td> | |
16 | + </thead> | |
17 | + <tbody> | |
18 | + <tr> | |
19 | + <td>1</td> | |
20 | + <td>1</td> | |
21 | + <td><button type="button" title="수정" class="new-btn"> | |
22 | + 수정 | |
23 | + </button></td> | |
24 | + </tr> | |
25 | + </tbody> | |
26 | + </table> --> | |
27 | + <label for="" class="title1">상세 내용</label> | |
28 | + <div class="board-wrap mt20"> | |
29 | + <div class="flex align-center mb20"> | |
30 | + <label for="" class="title2">단원</label> | |
31 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
32 | + <option value="bbsTtl">제목</option> | |
33 | + <option value="bbsCnt">내용</option> | |
34 | + <option value="userNm">작성자</option> | |
35 | + <option value="bbsCls">카테고리</option> | |
36 | + </select> | |
37 | + </div> | |
38 | + <div class="flex align-center mb20"> | |
39 | + <label for="" class="title2">평가 유형</label> | |
40 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
41 | + <option value="bbsTtl">제목</option> | |
42 | + <option value="bbsCnt">내용</option> | |
43 | + <option value="userNm">작성자</option> | |
44 | + <option value="bbsCls">카테고리</option> | |
45 | + </select> | |
46 | + </div> | |
47 | + | |
48 | + <hr> | |
49 | + <div class="flex align-center mb20"> | |
50 | + <label for="" class="title2">문제 1</label> | |
51 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
52 | + <option value="bbsTtl">제목</option> | |
53 | + <option value="bbsCnt">내용</option> | |
54 | + <option value="userNm">작성자</option> | |
55 | + <option value="bbsCls">카테고리</option> | |
56 | + </select> | |
57 | + </div> | |
58 | + <div class="flex align-center mb20"> | |
59 | + <label for="" class="title2">문제 2</label> | |
60 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
61 | + <option value="bbsTtl">제목</option> | |
62 | + <option value="bbsCnt">내용</option> | |
63 | + <option value="userNm">작성자</option> | |
64 | + <option value="bbsCls">카테고리</option> | |
65 | + </select> | |
66 | + </div> | |
67 | + <div class="flex align-center mb20"> | |
68 | + <label for="" class="title2">문제 3</label> | |
69 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
70 | + <option value="bbsTtl">제목</option> | |
71 | + <option value="bbsCnt">내용</option> | |
72 | + <option value="userNm">작성자</option> | |
73 | + <option value="bbsCls">카테고리</option> | |
74 | + </select> | |
75 | + </div> | |
76 | + <div class="flex align-center mb20"> | |
77 | + <label for="" class="title2">문제 4</label> | |
78 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
79 | + <option value="bbsTtl">제목</option> | |
80 | + <option value="bbsCnt">내용</option> | |
81 | + <option value="userNm">작성자</option> | |
82 | + <option value="bbsCls">카테고리</option> | |
83 | + </select> | |
84 | + </div> | |
85 | + | |
86 | + </div> | |
87 | + <div class="flex justify-between mt50"> | |
88 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('C_ExamList')"> | |
89 | + 목록 | |
90 | + </button> | |
91 | + <div class="flex"> | |
92 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
93 | + 취소 | |
94 | + </button> | |
95 | + <button type="button" title="글쓰기" class="new-btn"> | |
96 | + 등록 | |
97 | + </button> | |
98 | + </div> | |
99 | + </div> | |
100 | +</template> | |
101 | + | |
102 | +<script> | |
103 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
104 | +import { mdiMagnify } from '@mdi/js'; | |
105 | + | |
106 | + | |
107 | +export default { | |
108 | + data() { | |
109 | + return { | |
110 | + mdiMagnify: mdiMagnify, | |
111 | + } | |
112 | + }, | |
113 | + methods: { | |
114 | + goToPage(page) { | |
115 | + this.$router.push({ name: page }); | |
116 | + }, | |
117 | + }, | |
118 | + watch: { | |
119 | + | |
120 | + }, | |
121 | + computed: { | |
122 | + | |
123 | + }, | |
124 | + components: { | |
125 | + SvgIcon | |
126 | + }, | |
127 | + mounted() { | |
128 | + console.log('Main2 mounted'); | |
129 | + } | |
130 | +} | |
131 | +</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/ExamList.vue
+++ client/views/pages/teacher/ExamList.vue
... | ... | @@ -5,6 +5,12 @@ |
5 | 5 |
<option value="">1단원</option> |
6 | 6 |
</select> |
7 | 7 |
</div> |
8 |
+ <label for="" class="title2">단원</label> |
|
9 |
+ <div class="unit-pagination flex mt10 mb20" style="gap: 10px;"> |
|
10 |
+ <button class="selected-btn">1</button> |
|
11 |
+ <button>2</button> |
|
12 |
+ <button>3</button> |
|
13 |
+ </div> |
|
8 | 14 |
<div class="search-wrap flex justify-end mb20"> |
9 | 15 |
<select name="" id="" class="mr10 data-wrap"> |
10 | 16 |
<option value="">중간</option> |
... | ... | @@ -36,12 +42,12 @@ |
36 | 42 |
<td></td> |
37 | 43 |
<td></td> |
38 | 44 |
<td></td> |
39 |
- <td><button type="button" title="보기" class="new-btn" @click="toggleRow"> |
|
45 |
+ <td><button type="button" title="보기" class="new-btn" @click="goToPage('ExamDetail')"> |
|
40 | 46 |
보기 |
41 | 47 |
</button></td> |
42 | 48 |
<td></td> |
43 | 49 |
</tr> |
44 |
- <tr :class="{ 'hidden-tr': !isRowVisible }" class="show-tr"> |
|
50 |
+ <!-- <tr :class="{ 'hidden-tr': !isRowVisible }" class="show-tr"> |
|
45 | 51 |
<td colspan="7"> |
46 | 52 |
<div> |
47 | 53 |
<table> |
... | ... | @@ -67,7 +73,7 @@ |
67 | 73 |
</table> |
68 | 74 |
</div> |
69 | 75 |
</td> |
70 |
- </tr> |
|
76 |
+ </tr> --> |
|
71 | 77 |
</tbody> |
72 | 78 |
</table> |
73 | 79 |
<article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> |
... | ... | @@ -78,7 +84,7 @@ |
78 | 84 |
<button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> |
79 | 85 |
</article> |
80 | 86 |
<div class="flex justify-end "> |
81 |
- <button type="button" title="등록" class="new-btn" @click="goToPage('ExamDetail')"> |
|
87 |
+ <button type="button" title="등록" class="new-btn" @click="goToPage('ExamInsert')"> |
|
82 | 88 |
등록 |
83 | 89 |
</button> |
84 | 90 |
</div> |
--- client/views/pages/teacher/Home.vue
+++ client/views/pages/teacher/Home.vue
... | ... | @@ -1,114 +1,289 @@ |
1 | 1 |
<template> |
2 |
- <div class="title-box flex justify-between mb40"> |
|
3 |
- <p class="title">홈</p> |
|
4 |
- <select name="" id=""> |
|
5 |
- <option value="">A반</option> |
|
6 |
- </select> |
|
7 |
- </div> |
|
8 |
- <div class="content-t"> |
|
9 |
- <div class=" flex " style="gap: 50px;"> |
|
10 |
- <div class="class"> |
|
11 |
- <div class="box gd-col2" style="gap: 10px;" @click="goToPage('ClassDetail')"> |
|
12 |
- <div><img src="../../../resources/img/img176_82t.png" alt=""></div> |
|
13 |
- <div><img src="../../../resources/img/img176_82t.png" alt=""></div> |
|
14 |
- <div><img src="../../../resources/img/img176_82t.png" alt=""></div> |
|
15 |
- <div><img src="../../../resources/img/img176_82t.png" alt=""></div> |
|
16 |
- </div> |
|
17 |
- <div class="text flex justify-between mt20"> |
|
18 |
- <p class="title1">A반</p> |
|
19 |
- <span class="member">20명</span> |
|
20 |
- </div> |
|
21 |
- <div class="btnGroup mt15 flex align-center justify-end" style="gap: 10px;"> |
|
22 |
- <button @click="showConfirm('edit')">수정</button> |
|
23 |
- <p>|</p> |
|
24 |
- <button @click="showConfirm('delete')">삭제</button> |
|
25 |
- </div> |
|
26 |
- </div> |
|
27 |
- <div class="textbook-add"> |
|
28 |
- <button @click="buttonSearch"><img src="../../../resources/img/btn32_98t_normal.png" alt=""></button> |
|
29 |
- |
|
30 |
- </div> |
|
31 |
- <div v-show="searchOpen" class="popup-wrap"> |
|
32 |
- <div class="popup-box "> |
|
33 |
- <div class="flex justify-between mb30"> |
|
34 |
- <p class="popup-title">반 이름</p> |
|
35 |
- <button type="button" class="popup-close-btn" @click="closeBtn"> |
|
36 |
- <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
|
37 |
- |
|
38 |
- </button> |
|
39 |
- </div> |
|
40 |
- <div class="search-wrap mb30"> |
|
41 |
- <input type="text" class="data-wrap" placeholder=""> |
|
42 |
- <!-- <button type="button" > |
|
2 |
+ <div class="title-box flex justify-between mb40"> |
|
3 |
+ <p class="title">홈</p> |
|
4 |
+ </div> |
|
5 |
+ <div class="content-t"> |
|
6 |
+ <div class="flex" style="gap: 50px" :style="{ flexWrap: 'wrap' }"> |
|
7 |
+ <div |
|
8 |
+ class="class" |
|
9 |
+ v-for="classItem in classesList" |
|
10 |
+ :key="classItem.sclsId" |
|
11 |
+ > |
|
12 |
+ <div |
|
13 |
+ class="box gd-col2" |
|
14 |
+ style="gap: 10px" |
|
15 |
+ @click="goToPage('ClassDetail', classItem.sclsId)" |
|
16 |
+ > |
|
17 |
+ <div><img src="../../../resources/img/img176_82t.png" alt="" /></div> |
|
18 |
+ <div><img src="../../../resources/img/img176_82t.png" alt="" /></div> |
|
19 |
+ <div><img src="../../../resources/img/img176_82t.png" alt="" /></div> |
|
20 |
+ <div><img src="../../../resources/img/img176_82t.png" alt="" /></div> |
|
21 |
+ </div> |
|
22 |
+ <div class="text flex justify-between mt20"> |
|
23 |
+ <p class="title1">{{ classItem.sclsNm }}</p> |
|
24 |
+ <span class="member">{{ classItem.studentCount }}</span> |
|
25 |
+ </div> |
|
26 |
+ <div |
|
27 |
+ class="btnGroup mt15 flex align-center justify-end" |
|
28 |
+ style="gap: 10px" |
|
29 |
+ > |
|
30 |
+ <button @click="editModeModal(classItem.sclsId)">수정</button> |
|
31 |
+ <p>|</p> |
|
32 |
+ <button @click="deleteClass(classItem.sclsId)">삭제</button> |
|
33 |
+ </div> |
|
34 |
+ </div> |
|
35 |
+ <div class="textbook-add"> |
|
36 |
+ <button @click="addModeModal"> |
|
37 |
+ <img src="../../../resources/img/btn32_98t_normal.png" alt="" /> |
|
38 |
+ </button> |
|
39 |
+ </div> |
|
40 |
+ <!-- 팝업창 --> |
|
41 |
+ <div v-show="searchOpen" class="popup-wrap"> |
|
42 |
+ <div class="popup-box"> |
|
43 |
+ <div class="flex justify-between mb30"> |
|
44 |
+ <p class="popup-title">반 이름</p> |
|
45 |
+ <button type="button" class="popup-close-btn" @click="closeBtn"> |
|
46 |
+ <svg-icon |
|
47 |
+ type="mdi" |
|
48 |
+ :path="mdiWindowClose" |
|
49 |
+ class="close-btn" |
|
50 |
+ ></svg-icon> |
|
51 |
+ </button> |
|
52 |
+ </div> |
|
53 |
+ <div class="search-wrap mb30"> |
|
54 |
+ <input |
|
55 |
+ type="text" |
|
56 |
+ v-model="createClassName" |
|
57 |
+ class="data-wrap" |
|
58 |
+ placeholder="" |
|
59 |
+ /> |
|
60 |
+ <!-- <button type="button" > |
|
43 | 61 |
<img src="../../../resources/img/look_t.png" alt=""> |
44 | 62 |
</button> --> |
45 |
- </div> |
|
46 |
- <div class="flex justify-center "> |
|
47 |
- <button type="button" title="글쓰기" class="new-btn mr10"> |
|
48 |
- 취소 |
|
49 |
- </button> |
|
50 |
- <button type="button" title="글쓰기" class="new-btn"> |
|
51 |
- 생성 |
|
52 |
- </button> |
|
53 |
- </div> |
|
54 |
- </div> |
|
55 |
- </div> |
|
63 |
+ </div> |
|
64 |
+ <div class="flex justify-center"> |
|
65 |
+ <button |
|
66 |
+ type="button" |
|
67 |
+ title="글쓰기" |
|
68 |
+ class="new-btn mr10" |
|
69 |
+ @click="closeBtn" |
|
70 |
+ > |
|
71 |
+ 취소 |
|
72 |
+ </button> |
|
73 |
+ <button |
|
74 |
+ type="button" |
|
75 |
+ title="등록" |
|
76 |
+ class="new-btn" |
|
77 |
+ @click="isEditMode ? updateClass() : insertClass()" |
|
78 |
+ > |
|
79 |
+ {{ isEditMode ? "수정" : "등록" }} |
|
80 |
+ </button> |
|
81 |
+ </div> |
|
56 | 82 |
</div> |
83 |
+ </div> |
|
57 | 84 |
</div> |
85 |
+ </div> |
|
58 | 86 |
</template> |
59 | 87 |
|
60 | 88 |
<script> |
61 |
-import SvgIcon from '@jamescoyle/vue-icon'; |
|
62 |
-import { mdiMagnify, mdiWindowClose } from '@mdi/js'; |
|
89 |
+import axios from "axios"; |
|
90 |
+import SvgIcon from "@jamescoyle/vue-icon"; |
|
91 |
+import { mdiMagnify, mdiWindowClose } from "@mdi/js"; |
|
63 | 92 |
export default { |
64 |
- data() { |
|
65 |
- return { |
|
66 |
- mdiWindowClose: mdiWindowClose, |
|
67 |
- showModal: false, |
|
68 |
- searchOpen: false, |
|
69 |
- } |
|
70 |
- }, |
|
71 |
- methods: { |
|
72 |
- goToPage(page) { |
|
73 |
- this.$router.push({ name: page }); |
|
74 |
- }, |
|
75 |
- closeModal() { |
|
76 |
- this.showModal = false; |
|
77 |
- }, |
|
78 |
- buttonSearch() { |
|
79 |
- this.searchOpen = true; |
|
80 |
- }, |
|
81 |
- closeBtn() { |
|
82 |
- this.searchOpen = false; |
|
93 |
+ data() { |
|
94 |
+ return { |
|
95 |
+ mdiWindowClose: mdiWindowClose, |
|
96 |
+ showModal: false, |
|
97 |
+ searchOpen: false, |
|
83 | 98 |
|
99 |
+ classesList: [], // 불러온 반 정보 |
|
100 |
+ user_id: "2", //유저 아이디 : 현재는 고정 |
|
101 |
+ createClassName: "", // 생성 또는 수정할 반 이름 |
|
102 |
+ |
|
103 |
+ isEditMode: false, // 추가 모드인지 수정 모드인지 구분하는 변수 |
|
104 |
+ current_editId: "", // 현재 수정할 반 id |
|
105 |
+ }; |
|
106 |
+ }, |
|
107 |
+ methods: { |
|
108 |
+ goToPage(page, sclsId) { |
|
109 |
+ //console.log(`sclsId : ${sclsId}`); // 쿼리 확인 |
|
110 |
+ this.$router.push({ name: page, query: { sclsId: sclsId } }); |
|
111 |
+ }, |
|
112 |
+ closeModal() { |
|
113 |
+ this.showModal = false; |
|
114 |
+ }, |
|
115 |
+ editModeModal(sclsId) { |
|
116 |
+ this.searchOpen = true; |
|
117 |
+ this.isEditMode = true; // 수정 모드로 설정 |
|
118 |
+ this.current_editId = sclsId; |
|
119 |
+ }, |
|
120 |
+ addModeModal() { |
|
121 |
+ this.searchOpen = true; |
|
122 |
+ this.isEditMode = false; // 추가 모드로 설정 |
|
123 |
+ }, |
|
124 |
+ closeBtn() { |
|
125 |
+ this.searchOpen = false; |
|
126 |
+ this.createClassName = ""; // 팝업 닫을 때 반 이름 초기화 |
|
127 |
+ }, |
|
128 |
+ showConfirm(type, callback) { |
|
129 |
+ let message = ""; |
|
130 |
+ if (type === "delete") { |
|
131 |
+ message = "삭제하시겠습니까?"; |
|
132 |
+ } else if (type === "reset") { |
|
133 |
+ message = "초기화하시겠습니까?"; |
|
134 |
+ } else if (type === "save") { |
|
135 |
+ message = "등록하시겠습니까?"; |
|
136 |
+ } else if (type === "edit") { |
|
137 |
+ message = "수정하시겠습니까?"; |
|
138 |
+ } |
|
139 |
+ |
|
140 |
+ if (confirm(message)) { |
|
141 |
+ if (callback) callback(); // 콜백 함수 호출 |
|
142 |
+ } |
|
143 |
+ }, |
|
144 |
+ // 조회 |
|
145 |
+ selectClass() { |
|
146 |
+ sessionStorage.removeItem("sclsId"); |
|
147 |
+ axios({ |
|
148 |
+ url: "/classes/selectClass.json", |
|
149 |
+ method: "post", |
|
150 |
+ headers: { |
|
151 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
84 | 152 |
}, |
85 |
- showConfirm(type) { |
|
86 |
- let message = ''; |
|
87 |
- if (type === 'delete') { |
|
88 |
- message = '삭제하시겠습니까?'; |
|
89 |
- } else if (type === 'reset') { |
|
90 |
- message = '초기화하시겠습니까?'; |
|
91 |
- } else if (type === 'save') { |
|
92 |
- message = '등록하시겠습니까?'; |
|
153 |
+ data: { |
|
154 |
+ userId: this.user_id, |
|
155 |
+ }, |
|
156 |
+ }) |
|
157 |
+ .then((res) => { |
|
158 |
+ if (res.data.status === "success") { |
|
159 |
+ console.log("classesList - response(조회) : ", res.data.data); |
|
160 |
+ this.classesList = res.data.data; |
|
161 |
+ } else { |
|
162 |
+ console.log("조회에 실패했습니다: ", res.data); |
|
163 |
+ alert("조회에 실패했습니다."); |
|
164 |
+ } |
|
165 |
+ }) |
|
166 |
+ .catch((err) => { |
|
167 |
+ console.log("classesList - error(조회) : ", err); |
|
168 |
+ alert("조회에 오류가 발생했습니다."); |
|
169 |
+ }); |
|
170 |
+ }, |
|
171 |
+ // 추가 |
|
172 |
+ insertClass() { |
|
173 |
+ if (this.createClassName.trim() === "") { |
|
174 |
+ alert("반 이름을 입력해주세요"); |
|
175 |
+ } else { |
|
176 |
+ this.showConfirm("save", () => { |
|
177 |
+ axios({ |
|
178 |
+ url: "/classes/insertClass.json", |
|
179 |
+ method: "post", |
|
180 |
+ headers: { |
|
181 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
182 |
+ }, |
|
183 |
+ data: { |
|
184 |
+ userId: this.user_id, |
|
185 |
+ sclsNm: this.createClassName, |
|
186 |
+ }, |
|
187 |
+ }) |
|
188 |
+ .then((res) => { |
|
189 |
+ if (res.data.status === "success") { |
|
190 |
+ console.log("classesList - response(추가) : ", res.data.data); |
|
191 |
+ this.selectClass(); |
|
192 |
+ this.createClassName = ""; // 반 이름 초기화 |
|
193 |
+ this.closeBtn(); // 생성 모달 닫기 |
|
194 |
+ } else { |
|
195 |
+ console.log("추가에 실패했습니다: ", res.data); |
|
196 |
+ alert("추가에 실패했습니다."); |
|
197 |
+ } |
|
198 |
+ }) |
|
199 |
+ .catch((err) => { |
|
200 |
+ console.log("classesList - error(추가) : ", err); |
|
201 |
+ alert("추가에 오류가 발생했습니다."); |
|
202 |
+ }); |
|
203 |
+ }); |
|
204 |
+ } |
|
205 |
+ }, |
|
206 |
+ // 삭제 |
|
207 |
+ deleteClass(sclsId) { |
|
208 |
+ this.showConfirm("delete", () => { |
|
209 |
+ axios({ |
|
210 |
+ url: "/classes/deleteClass.json", |
|
211 |
+ method: "post", |
|
212 |
+ headers: { |
|
213 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
214 |
+ }, |
|
215 |
+ data: { |
|
216 |
+ sclsId: sclsId, |
|
217 |
+ }, |
|
218 |
+ }) |
|
219 |
+ .then((res) => { |
|
220 |
+ if (res.data.status === "success") { |
|
221 |
+ console.log("classesList - response(삭제) : ", res.data.data); |
|
222 |
+ this.selectClass(); |
|
223 |
+ } else { |
|
224 |
+ console.log("삭제에 실패했습니다: ", res.data); |
|
225 |
+ alert("삭제에 실패했습니다."); |
|
93 | 226 |
} |
94 |
- |
|
95 |
- if (confirm(message)) { |
|
96 |
- this.goBack(); |
|
97 |
- } |
|
98 |
- }, |
|
99 |
- |
|
227 |
+ }) |
|
228 |
+ .catch((err) => { |
|
229 |
+ console.log("classesList - error(삭제) : ", err); |
|
230 |
+ alert("삭제에 오류가 발생했습니다."); |
|
231 |
+ }); |
|
232 |
+ }); |
|
100 | 233 |
}, |
101 |
- watch: { |
|
234 |
+ // 수정 |
|
235 |
+ updateClass() { |
|
236 |
+ if (this.createClassName.trim() === "") { |
|
237 |
+ alert("반 이름을 입력해주세요"); |
|
238 |
+ } else { |
|
239 |
+ this.showConfirm("edit", () => { |
|
240 |
+ axios({ |
|
241 |
+ url: "/classes/updateClass.json", |
|
242 |
+ method: "post", |
|
243 |
+ headers: { |
|
244 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
245 |
+ }, |
|
246 |
+ data: { |
|
247 |
+ sclsId: this.current_editId, |
|
248 |
+ sclsNm: this.createClassName, |
|
249 |
+ }, |
|
250 |
+ }) |
|
251 |
+ .then((res) => { |
|
252 |
+ if (res.data.status === "success") { |
|
253 |
+ console.log("classesList - response(수정) : ", res.data.data); |
|
254 |
+ this.selectClass(); |
|
255 |
+ this.createClassName = ""; // 반 이름 초기화 |
|
256 |
+ this.current_editId = ""; // 반 Id 초기화 |
|
257 |
+ this.closeBtn(); // 팝업 닫기 |
|
258 |
+ } else { |
|
259 |
+ console.log("수정에 실패했습니다: ", res.data); |
|
260 |
+ alert("수정에 실패했습니다."); |
|
261 |
+ } |
|
262 |
+ }) |
|
263 |
+ .catch((err) => { |
|
264 |
+ console.log("classesList - error(수정) : ", err); |
|
265 |
+ alert("수정에 오류가 발생했습니다."); |
|
266 |
+ }); |
|
267 |
+ }); |
|
268 |
+ } |
|
269 |
+ }, |
|
270 |
+ }, |
|
271 |
+ watch: {}, |
|
272 |
+ computed: {}, |
|
273 |
+ components: { |
|
274 |
+ SvgIcon, |
|
275 |
+ }, |
|
276 |
+ mounted() { |
|
277 |
+ console.log("Main2 mounted"); |
|
278 |
+ this.selectClass(); |
|
279 |
+ }, |
|
280 |
+}; |
|
281 |
+</script> |
|
102 | 282 |
|
103 |
- }, |
|
104 |
- computed: { |
|
105 |
- |
|
106 |
- }, |
|
107 |
- components: { |
|
108 |
- SvgIcon |
|
109 |
- }, |
|
110 |
- mounted() { |
|
111 |
- console.log('Main2 mounted'); |
|
112 |
- } |
|
283 |
+<style> |
|
284 |
+.content-t { |
|
285 |
+ flex-wrap: wrap; |
|
286 |
+ height: 90%; |
|
287 |
+ overflow-y: scroll; |
|
113 | 288 |
} |
114 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
289 |
+</style> |
--- client/views/pages/teacher/Main_t.vue
+++ client/views/pages/teacher/Main_t.vue
... | ... | @@ -1,7 +1,7 @@ |
1 | 1 |
<template> |
2 | 2 |
<div class="flex justify-between" style="height: 100%;"> |
3 | 3 |
<Side_t></Side_t> |
4 |
- <div style="padding: 15px 60px 90px 60px; "> |
|
4 |
+ <div style="padding: 15px 60px 120px 0px "> |
|
5 | 5 |
<Header></Header> |
6 | 6 |
<div class="main-wrap"> |
7 | 7 |
<router-view /> |
+++ client/views/pages/teacher/QuestionDetail.vue
... | ... | @@ -0,0 +1,232 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">문제 등록</p> | |
4 | + </div> | |
5 | + <div class="board-wrap"> | |
6 | + <div class="tab-box" > | |
7 | + <label class="mr20 title1"> | |
8 | + <input type="radio" v-model="selectedTab" value="tab1" /> | |
9 | + 문제 유형 (일반형) | |
10 | + </label> | |
11 | + <label class="mr20 title1"> | |
12 | + <input type="radio" v-model="selectedTab" value="tab2" /> | |
13 | + 문제 유형 (O,X형) | |
14 | + </label> | |
15 | + <label class="mr20 title1"> | |
16 | + <input type="radio" v-model="selectedTab" value="tab3" /> | |
17 | + 문제 유형 (연결형) | |
18 | + </label> | |
19 | + <label class="mr20 title1"> | |
20 | + <input type="radio" v-model="selectedTab" value="tab4" /> | |
21 | + 문제 유형 (다중 정답형) | |
22 | + </label> | |
23 | + </div> | |
24 | + <hr> | |
25 | + <div class="gd-col2 " > | |
26 | + <div class="flex align-center mb20"> | |
27 | + <label for="" class="title2">카테고리</label> | |
28 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
29 | + <option value="bbsTtl">제목</option> | |
30 | + <option value="bbsCnt">내용</option> | |
31 | + <option value="userNm">작성자</option> | |
32 | + <option value="bbsCls">카테고리</option> | |
33 | + </select> | |
34 | + </div> | |
35 | + <div class="flex align-center mb20"> | |
36 | + <label for="" class="title2">문제 유형</label> | |
37 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
38 | + <option value="bbsTtl">제목</option> | |
39 | + <option value="bbsCnt">내용</option> | |
40 | + <option value="userNm">작성자</option> | |
41 | + <option value="bbsCls">카테고리</option> | |
42 | + </select> | |
43 | + </div> | |
44 | + <div class="flex align-center"> | |
45 | + <label for="" class="title2">지문</label> | |
46 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
47 | + <option value="bbsTtl">제목</option> | |
48 | + <option value="bbsCnt">내용</option> | |
49 | + <option value="userNm">작성자</option> | |
50 | + <option value="bbsCls">카테고리</option> | |
51 | + </select> | |
52 | + </div> | |
53 | + <div class="flex align-center"> | |
54 | + <label for="" class="title2">문제 지표</label> | |
55 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
56 | + <option value="bbsTtl">제목</option> | |
57 | + <option value="bbsCnt">내용</option> | |
58 | + <option value="userNm">작성자</option> | |
59 | + <option value="bbsCls">카테고리</option> | |
60 | + </select> | |
61 | + </div> | |
62 | + </div> | |
63 | + <div class="flex align-center mb20 mt40"> | |
64 | + <label for="" class="title2">문제 배점</label> | |
65 | + <input type="text" class="data-wrap"> | |
66 | + </div> | |
67 | + | |
68 | + <div class="flex align-center mb20"> | |
69 | + <label for="" class="title2">내용</label> | |
70 | + <textarea name="" id="" class="data-wrap"></textarea> | |
71 | + </div> | |
72 | + <div class="flex align-center mb20"> | |
73 | + <label for="" class="title2">힌트</label> | |
74 | + <input type="text" class="data-wrap"> | |
75 | + </div> | |
76 | + <div class="flex align-center mb20"> | |
77 | + <label for="" class="title2">첨부파일</label> | |
78 | + <input type="file" ref="fileInput" @change="handleFileUpload" /> | |
79 | + </div> | |
80 | + <hr> | |
81 | + <div v-if="selectedTab === 'tab1'"> | |
82 | + <div class="flex align-center mb20"> | |
83 | + <label for="" class="title2">답1</label> | |
84 | + <input type="text" class="data-wrap"> | |
85 | + </div> | |
86 | + <div class="flex align-center mb20"> | |
87 | + <label for="" class="title2">답2</label> | |
88 | + <input type="text" class="data-wrap"> | |
89 | + </div> | |
90 | + <div class="flex align-center mb20"> | |
91 | + <label for="" class="title2">답3</label> | |
92 | + <input type="text" class="data-wrap"> | |
93 | + </div> | |
94 | + <div class="flex align-center mb20"> | |
95 | + <label for="" class="title2">답4</label> | |
96 | + <input type="text" class="data-wrap"> | |
97 | + </div> | |
98 | + <div class="flex align-center mb20"> | |
99 | + <label for="" class="title2">해설</label> | |
100 | + <textarea name="" id="" class="data-wrap"></textarea> | |
101 | + </div> | |
102 | + </div> | |
103 | + <div v-else-if="selectedTab === 'tab2'"> | |
104 | + <div class="flex align-center mb20"> | |
105 | + <label for="" class="title2">답</label> | |
106 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
107 | + <option value="bbsTtl">O</option> | |
108 | + <option value="bbsCnt">X</option> | |
109 | + </select> | |
110 | + </div> | |
111 | + <div class="flex align-center mb20"> | |
112 | + <label for="" class="title2">해설</label> | |
113 | + <textarea name="" id="" class="data-wrap"></textarea> | |
114 | + </div> | |
115 | + </div> | |
116 | + <div v-else-if="selectedTab === 'tab3'"> | |
117 | + <div class="gd-col2 " > | |
118 | + <div class="flex align-center mb20 mr40" > | |
119 | + <label for="" class="title2">문제1</label> | |
120 | + <input type="text" class="data-wrap"> | |
121 | + </div> | |
122 | + <div class="flex align-center mb20"> | |
123 | + <label for="" class="title2">답1</label> | |
124 | + <input type="text" class="data-wrap"> | |
125 | + </div> | |
126 | + <div class="flex align-center mb20 mr40"> | |
127 | + <label for="" class="title2">문제2</label> | |
128 | + <input type="text" class="data-wrap"> | |
129 | + </div> | |
130 | + <div class="flex align-center mb20"> | |
131 | + <label for="" class="title2">답2</label> | |
132 | + <input type="text" class="data-wrap"> | |
133 | + </div> | |
134 | + <div class="flex align-center mb20 mr40"> | |
135 | + <label for="" class="title2">문제3</label> | |
136 | + <input type="text" class="data-wrap"> | |
137 | + </div> | |
138 | + <div class="flex align-center mb20 "> | |
139 | + <label for="" class="title2">답3</label> | |
140 | + <input type="text" class="data-wrap"> | |
141 | + </div> | |
142 | + <div class="flex align-center mb20 mr40"> | |
143 | + <label for="" class="title2">문제4</label> | |
144 | + <input type="text" class="data-wrap"> | |
145 | + </div> | |
146 | + <div class="flex align-center mb20"> | |
147 | + <label for="" class="title2">답4</label> | |
148 | + <input type="text" class="data-wrap"> | |
149 | + </div> | |
150 | + </div> | |
151 | + <div class="flex align-center mb20"> | |
152 | + <label for="" class="title2">해설</label> | |
153 | + <textarea name="" id="" class="data-wrap"></textarea> | |
154 | + </div> | |
155 | + </div> | |
156 | + <div v-else-if="selectedTab === 'tab4'"> | |
157 | + <div class="flex align-center mb20 mr40" > | |
158 | + <label for="" class="title2">문제1</label> | |
159 | + <input type="text" class="data-wrap"> | |
160 | + <input type="checkbox" class="ui-checkbox ml30"> | |
161 | + </div> | |
162 | + <div class="flex align-center mb20 mr40"> | |
163 | + <label for="" class="title2">문제2</label> | |
164 | + <input type="text" class="data-wrap"> | |
165 | + <input type="checkbox" class="ui-checkbox ml30"> | |
166 | + </div> | |
167 | + <div class="flex align-center mb20 mr40"> | |
168 | + <label for="" class="title2">문제3</label> | |
169 | + <input type="text" class="data-wrap"> | |
170 | + <input type="checkbox" class="ui-checkbox ml30"> | |
171 | + </div> | |
172 | + <div class="flex align-center mb20 mr40"> | |
173 | + <label for="" class="title2">문제4</label> | |
174 | + <input type="text" class="data-wrap"> | |
175 | + <input type="checkbox" class="ui-checkbox ml30"> | |
176 | + </div> | |
177 | + <div class="flex align-center mb20"> | |
178 | + <label for="" class="title2">해설</label> | |
179 | + <textarea name="" id="" class="data-wrap"></textarea> | |
180 | + </div> | |
181 | + </div> | |
182 | + | |
183 | + </div> | |
184 | + <div class="flex justify-between mt50"> | |
185 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('QuestionList')"> | |
186 | + 목록 | |
187 | + </button> | |
188 | + <div class="flex"> | |
189 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
190 | + 삭제 | |
191 | + </button> | |
192 | + <button type="button" title="글쓰기" class="new-btn"> | |
193 | + 수정 | |
194 | + </button> | |
195 | + </div> | |
196 | + </div> | |
197 | +</template> | |
198 | + | |
199 | +<script> | |
200 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
201 | +import { mdiMagnify } from '@mdi/js'; | |
202 | + | |
203 | + | |
204 | +export default { | |
205 | + data() { | |
206 | + return { | |
207 | + mdiMagnify: mdiMagnify, | |
208 | + selectedTab: 'tab1', | |
209 | + } | |
210 | + }, | |
211 | + methods: { | |
212 | + goToPage(page) { | |
213 | + this.$router.push({ name: page }); | |
214 | + }, | |
215 | + }, | |
216 | + watch: { | |
217 | + | |
218 | + }, | |
219 | + computed: { | |
220 | + | |
221 | + }, | |
222 | + components: { | |
223 | + SvgIcon | |
224 | + }, | |
225 | + mounted() { | |
226 | + console.log('Main2 mounted'); | |
227 | + } | |
228 | +} | |
229 | +</script> | |
230 | +<style scoped> | |
231 | +.ui-checkbox{width: 30px; height: 30px;} | |
232 | +</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/QuestionInsert.vue
+++ client/views/pages/teacher/QuestionInsert.vue
... | ... | @@ -3,54 +3,183 @@ |
3 | 3 |
<p class="title">문제 등록</p> |
4 | 4 |
</div> |
5 | 5 |
<div class="board-wrap"> |
6 |
- <div class="flex align-center mb20"> |
|
7 |
- <label for="" class="title2">제목</label> |
|
8 |
- <input type="text" class="data-wrap"> |
|
6 |
+ <div class="tab-box" > |
|
7 |
+ <label class="mr20 title1"> |
|
8 |
+ <input type="radio" v-model="selectedTab" value="tab1" /> |
|
9 |
+ 문제 유형 (일반형) |
|
10 |
+ </label> |
|
11 |
+ <label class="mr20 title1"> |
|
12 |
+ <input type="radio" v-model="selectedTab" value="tab2" /> |
|
13 |
+ 문제 유형 (O,X형) |
|
14 |
+ </label> |
|
15 |
+ <label class="mr20 title1"> |
|
16 |
+ <input type="radio" v-model="selectedTab" value="tab3" /> |
|
17 |
+ 문제 유형 (연결형) |
|
18 |
+ </label> |
|
19 |
+ <label class="mr20 title1"> |
|
20 |
+ <input type="radio" v-model="selectedTab" value="tab4" /> |
|
21 |
+ 문제 유형 (다중 정답형) |
|
22 |
+ </label> |
|
9 | 23 |
</div> |
10 | 24 |
<hr> |
11 |
- <div class="flex align-center"> |
|
25 |
+ <div class="gd-col2 " > |
|
26 |
+ <div class="flex align-center mb20"> |
|
27 |
+ <label for="" class="title2">카테고리</label> |
|
28 |
+ <select v-model="selectedSearchOption" class="mr10 data-wrap"> |
|
29 |
+ <option value="bbsTtl">제목</option> |
|
30 |
+ <option value="bbsCnt">내용</option> |
|
31 |
+ <option value="userNm">작성자</option> |
|
32 |
+ <option value="bbsCls">카테고리</option> |
|
33 |
+ </select> |
|
34 |
+ </div> |
|
35 |
+ <div class="flex align-center mb20"> |
|
36 |
+ <label for="" class="title2">문제 유형</label> |
|
37 |
+ <select v-model="selectedSearchOption" class="mr10 data-wrap"> |
|
38 |
+ <option value="bbsTtl">제목</option> |
|
39 |
+ <option value="bbsCnt">내용</option> |
|
40 |
+ <option value="userNm">작성자</option> |
|
41 |
+ <option value="bbsCls">카테고리</option> |
|
42 |
+ </select> |
|
43 |
+ </div> |
|
44 |
+ <div class="flex align-center"> |
|
45 |
+ <label for="" class="title2">지문</label> |
|
46 |
+ <select v-model="selectedSearchOption" class="mr10 data-wrap"> |
|
47 |
+ <option value="bbsTtl">제목</option> |
|
48 |
+ <option value="bbsCnt">내용</option> |
|
49 |
+ <option value="userNm">작성자</option> |
|
50 |
+ <option value="bbsCls">카테고리</option> |
|
51 |
+ </select> |
|
52 |
+ </div> |
|
53 |
+ <div class="flex align-center"> |
|
54 |
+ <label for="" class="title2">문제 지표</label> |
|
55 |
+ <select v-model="selectedSearchOption" class="mr10 data-wrap"> |
|
56 |
+ <option value="bbsTtl">제목</option> |
|
57 |
+ <option value="bbsCnt">내용</option> |
|
58 |
+ <option value="userNm">작성자</option> |
|
59 |
+ <option value="bbsCls">카테고리</option> |
|
60 |
+ </select> |
|
61 |
+ </div> |
|
62 |
+ </div> |
|
63 |
+ <div class="flex align-center mb20 mt40"> |
|
64 |
+ <label for="" class="title2">문제 배점</label> |
|
65 |
+ <input type="text" class="data-wrap"> |
|
66 |
+ </div> |
|
67 |
+ |
|
68 |
+ <div class="flex align-center mb20"> |
|
12 | 69 |
<label for="" class="title2">내용</label> |
13 | 70 |
<textarea name="" id="" class="data-wrap"></textarea> |
14 | 71 |
</div> |
15 |
- <hr> |
|
72 |
+ <div class="flex align-center mb20"> |
|
73 |
+ <label for="" class="title2">힌트</label> |
|
74 |
+ <input type="text" class="data-wrap"> |
|
75 |
+ </div> |
|
16 | 76 |
<div class="flex align-center mb20"> |
17 | 77 |
<label for="" class="title2">첨부파일</label> |
18 | 78 |
<input type="file" ref="fileInput" @change="handleFileUpload" /> |
19 | 79 |
</div> |
20 |
- <div class="flex align-center mb20"> |
|
21 |
- <label for="" class="title2">답</label> |
|
22 |
- <input type="text" class="data-wrap"> |
|
23 |
- </div> |
|
24 |
- <div> |
|
25 |
- <label for="" class="title2">오답 학생</label> |
|
26 |
- <div class="table-wrap mt20"> |
|
27 |
- <table> |
|
28 |
- <thead> |
|
29 |
- <td>No.</td> |
|
30 |
- <td>이름</td> |
|
31 |
- <td>학년</td> |
|
32 |
- <td>반</td> |
|
33 |
- <td>오답</td> |
|
34 |
- </thead> |
|
35 |
- <tbody> |
|
36 |
- <tr @click="goToPage('noticeDetail')"> |
|
37 |
- <td></td> |
|
38 |
- <td></td> |
|
39 |
- <td></td> |
|
40 |
- <td></td> |
|
41 |
- <td></td> |
|
42 |
- </tr> |
|
43 |
- </tbody> |
|
44 |
- </table> |
|
45 |
- <!-- <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> |
|
46 |
- <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button> |
|
47 |
- <button class="selected-btn">1</button> |
|
48 |
- <button>2</button> |
|
49 |
- <button>3</button> |
|
50 |
- <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> |
|
51 |
- </article> --> |
|
80 |
+ <hr> |
|
81 |
+ <div v-if="selectedTab === 'tab1'"> |
|
82 |
+ <div class="flex align-center mb20"> |
|
83 |
+ <label for="" class="title2">답1</label> |
|
84 |
+ <input type="text" class="data-wrap"> |
|
85 |
+ </div> |
|
86 |
+ <div class="flex align-center mb20"> |
|
87 |
+ <label for="" class="title2">답2</label> |
|
88 |
+ <input type="text" class="data-wrap"> |
|
89 |
+ </div> |
|
90 |
+ <div class="flex align-center mb20"> |
|
91 |
+ <label for="" class="title2">답3</label> |
|
92 |
+ <input type="text" class="data-wrap"> |
|
93 |
+ </div> |
|
94 |
+ <div class="flex align-center mb20"> |
|
95 |
+ <label for="" class="title2">답4</label> |
|
96 |
+ <input type="text" class="data-wrap"> |
|
97 |
+ </div> |
|
98 |
+ <div class="flex align-center mb20"> |
|
99 |
+ <label for="" class="title2">해설</label> |
|
100 |
+ <textarea name="" id="" class="data-wrap"></textarea> |
|
52 | 101 |
</div> |
53 | 102 |
</div> |
103 |
+ <div v-else-if="selectedTab === 'tab2'"> |
|
104 |
+ <div class="flex align-center mb20"> |
|
105 |
+ <label for="" class="title2">답</label> |
|
106 |
+ <select v-model="selectedSearchOption" class="mr10 data-wrap"> |
|
107 |
+ <option value="bbsTtl">O</option> |
|
108 |
+ <option value="bbsCnt">X</option> |
|
109 |
+ </select> |
|
110 |
+ </div> |
|
111 |
+ <div class="flex align-center mb20"> |
|
112 |
+ <label for="" class="title2">해설</label> |
|
113 |
+ <textarea name="" id="" class="data-wrap"></textarea> |
|
114 |
+ </div> |
|
115 |
+ </div> |
|
116 |
+ <div v-else-if="selectedTab === 'tab3'"> |
|
117 |
+ <div class="gd-col2 " > |
|
118 |
+ <div class="flex align-center mb20 mr40" > |
|
119 |
+ <label for="" class="title2">문제1</label> |
|
120 |
+ <input type="text" class="data-wrap"> |
|
121 |
+ </div> |
|
122 |
+ <div class="flex align-center mb20"> |
|
123 |
+ <label for="" class="title2">답1</label> |
|
124 |
+ <input type="text" class="data-wrap"> |
|
125 |
+ </div> |
|
126 |
+ <div class="flex align-center mb20 mr40"> |
|
127 |
+ <label for="" class="title2">문제2</label> |
|
128 |
+ <input type="text" class="data-wrap"> |
|
129 |
+ </div> |
|
130 |
+ <div class="flex align-center mb20"> |
|
131 |
+ <label for="" class="title2">답2</label> |
|
132 |
+ <input type="text" class="data-wrap"> |
|
133 |
+ </div> |
|
134 |
+ <div class="flex align-center mb20 mr40"> |
|
135 |
+ <label for="" class="title2">문제3</label> |
|
136 |
+ <input type="text" class="data-wrap"> |
|
137 |
+ </div> |
|
138 |
+ <div class="flex align-center mb20 "> |
|
139 |
+ <label for="" class="title2">답3</label> |
|
140 |
+ <input type="text" class="data-wrap"> |
|
141 |
+ </div> |
|
142 |
+ <div class="flex align-center mb20 mr40"> |
|
143 |
+ <label for="" class="title2">문제4</label> |
|
144 |
+ <input type="text" class="data-wrap"> |
|
145 |
+ </div> |
|
146 |
+ <div class="flex align-center mb20"> |
|
147 |
+ <label for="" class="title2">답4</label> |
|
148 |
+ <input type="text" class="data-wrap"> |
|
149 |
+ </div> |
|
150 |
+ </div> |
|
151 |
+ <div class="flex align-center mb20"> |
|
152 |
+ <label for="" class="title2">해설</label> |
|
153 |
+ <textarea name="" id="" class="data-wrap"></textarea> |
|
154 |
+ </div> |
|
155 |
+ </div> |
|
156 |
+ <div v-else-if="selectedTab === 'tab4'"> |
|
157 |
+ <div class="flex align-center mb20 mr40" > |
|
158 |
+ <label for="" class="title2">문제1</label> |
|
159 |
+ <input type="text" class="data-wrap"> |
|
160 |
+ <input type="checkbox" class="ui-checkbox ml30"> |
|
161 |
+ </div> |
|
162 |
+ <div class="flex align-center mb20 mr40"> |
|
163 |
+ <label for="" class="title2">문제2</label> |
|
164 |
+ <input type="text" class="data-wrap"> |
|
165 |
+ <input type="checkbox" class="ui-checkbox ml30"> |
|
166 |
+ </div> |
|
167 |
+ <div class="flex align-center mb20 mr40"> |
|
168 |
+ <label for="" class="title2">문제3</label> |
|
169 |
+ <input type="text" class="data-wrap"> |
|
170 |
+ <input type="checkbox" class="ui-checkbox ml30"> |
|
171 |
+ </div> |
|
172 |
+ <div class="flex align-center mb20 mr40"> |
|
173 |
+ <label for="" class="title2">문제4</label> |
|
174 |
+ <input type="text" class="data-wrap"> |
|
175 |
+ <input type="checkbox" class="ui-checkbox ml30"> |
|
176 |
+ </div> |
|
177 |
+ <div class="flex align-center mb20"> |
|
178 |
+ <label for="" class="title2">해설</label> |
|
179 |
+ <textarea name="" id="" class="data-wrap"></textarea> |
|
180 |
+ </div> |
|
181 |
+ </div> |
|
182 |
+ |
|
54 | 183 |
</div> |
55 | 184 |
<div class="flex justify-between mt50"> |
56 | 185 |
<button type="button" title="글쓰기" class="new-btn" @click="goToPage('QuestionList')"> |
... | ... | @@ -58,10 +187,10 @@ |
58 | 187 |
</button> |
59 | 188 |
<div class="flex"> |
60 | 189 |
<button type="button" title="글쓰기" class="new-btn mr10"> |
61 |
- 수정 |
|
190 |
+ 취소 |
|
62 | 191 |
</button> |
63 | 192 |
<button type="button" title="글쓰기" class="new-btn"> |
64 |
- 삭제 |
|
193 |
+ 등록 |
|
65 | 194 |
</button> |
66 | 195 |
</div> |
67 | 196 |
</div> |
... | ... | @@ -76,6 +205,7 @@ |
76 | 205 |
data() { |
77 | 206 |
return { |
78 | 207 |
mdiMagnify: mdiMagnify, |
208 |
+ selectedTab: 'tab1', |
|
79 | 209 |
} |
80 | 210 |
}, |
81 | 211 |
methods: { |
... | ... | @@ -96,4 +226,7 @@ |
96 | 226 |
console.log('Main2 mounted'); |
97 | 227 |
} |
98 | 228 |
} |
99 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
229 |
+</script> |
|
230 |
+<style scoped> |
|
231 |
+.ui-checkbox{width: 30px; height: 30px;} |
|
232 |
+</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/QuestionList.vue
+++ client/views/pages/teacher/QuestionList.vue
... | ... | @@ -2,9 +2,15 @@ |
2 | 2 |
<div class="title-box flex justify-between mb40"> |
3 | 3 |
<p class="title">문제</p> |
4 | 4 |
<select name="" id=""> |
5 |
- <option value="">1단원</option> |
|
5 |
+ <option value="">A교재</option> |
|
6 | 6 |
</select> |
7 | 7 |
</div> |
8 |
+ <label for="" class="title2">단원</label> |
|
9 |
+ <div class="unit-pagination flex mt10 mb20" style="gap: 10px;"> |
|
10 |
+ <button class="selected-btn">1</button> |
|
11 |
+ <button>2</button> |
|
12 |
+ <button>3</button> |
|
13 |
+ </div> |
|
8 | 14 |
<div class="search-wrap flex justify-end mb20"> |
9 | 15 |
<select name="" id="" class="mr10 data-wrap"> |
10 | 16 |
<option value="">전체</option> |
... | ... | @@ -19,13 +25,13 @@ |
19 | 25 |
<thead> |
20 | 26 |
<td>No.</td> |
21 | 27 |
<td>제목</td> |
22 |
- <td>문제</td> |
|
23 |
- <td>작성자</td> |
|
24 |
- <td>오답률</td> |
|
28 |
+ <td>내용</td> |
|
29 |
+ <td>유형</td> |
|
30 |
+ <td>지문</td> |
|
25 | 31 |
<td>등록일</td> |
26 | 32 |
</thead> |
27 | 33 |
<tbody> |
28 |
- <tr @click="goToPage('QuestionInsert')"> |
|
34 |
+ <tr @click="goToPage('QuestionDetail')"> |
|
29 | 35 |
<td></td> |
30 | 36 |
<td></td> |
31 | 37 |
<td></td> |
+++ client/views/pages/teacher/RoadMap.vue
... | ... | @@ -0,0 +1,166 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">A반</p> | |
4 | + <select name="" id=""> | |
5 | + <option value="">A 교재</option> | |
6 | + </select> | |
7 | + </div> | |
8 | + <div class="board-wrap" style=" height: calc(100% - 16rem);"> | |
9 | + <label for="" class="title2">단원</label> | |
10 | + <div class="table-pagination flex mt10"> | |
11 | + <button class="selected-btn">1</button> | |
12 | + <button>2</button> | |
13 | + <button>3</button> | |
14 | + </div> | |
15 | + <hr> | |
16 | + <label for="" class="title2 ">1단원 로드맵 등록</label> | |
17 | + <div class="search-wrap flex mb20 mt30"> | |
18 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
19 | + <option value="bbsTtl">제목</option> | |
20 | + <option value="bbsCnt">내용</option> | |
21 | + <option value="userNm">작성자</option> | |
22 | + <option value="bbsCls">카테고리</option> | |
23 | + </select> | |
24 | + <input v-model="searchKeyword" type="text" placeholder="검색하세요." @keyup.enter="boardDataSearch" /> | |
25 | + <button type="button" @click="boardDataSearch()" title="게시글 검색"> | |
26 | + <img src="../../../resources/img/look_t.png" alt="" /> | |
27 | + </button> | |
28 | + </div> | |
29 | + <div class="flex justify-between align-center mypage mt10" style="height: calc(100% - 23rem);"> | |
30 | + <div class="textbook big book-gray"> | |
31 | + <div class="text "> | |
32 | + <p class="title1">학습항목</p> | |
33 | + </div> | |
34 | + <div class="box flex-column" style="gap: 30px;"> | |
35 | + <!-- 지문 --> | |
36 | + <div class="textbook book-red"> | |
37 | + <div class="text "> | |
38 | + <p class="title1" style="color: #fff;">지문. 제목</p> | |
39 | + </div> | |
40 | + <div class="box"> | |
41 | + | |
42 | + <P class="title2 mt10">지문 내용</P> | |
43 | + </div> | |
44 | + </div> | |
45 | + <!-- 단어 --> | |
46 | + <div class="textbook "> | |
47 | + <div class="text "> | |
48 | + <p class="title1" style="color: #fff;">단어장1</p> | |
49 | + </div> | |
50 | + <div class="box"> | |
51 | + | |
52 | + <P class="title2 mt10">단어1</P> | |
53 | + </div> | |
54 | + </div> | |
55 | + <!-- 문제 --> | |
56 | + <div class="textbook book-blue"> | |
57 | + <div class="text "> | |
58 | + <p class="title1" style="color: #fff;">문제1</p> | |
59 | + </div> | |
60 | + <div class="box"> | |
61 | + | |
62 | + <P class="title2 mt10">문제유형</P> | |
63 | + <P class="title2 mt10">정답</P> | |
64 | + </div> | |
65 | + </div> | |
66 | + <!-- 평가 --> | |
67 | + <div class="textbook book-navy"> | |
68 | + <div class="text "> | |
69 | + <p class="title1" style="color: #fff;">평가1</p> | |
70 | + </div> | |
71 | + <div class="box"> | |
72 | + | |
73 | + <P class="title2 mt10">평가 내용</P> | |
74 | + </div> | |
75 | + </div> | |
76 | + </div> | |
77 | + </div> | |
78 | + <div class="textbook big book-gray"> | |
79 | + <div class="text "> | |
80 | + <p class="title1">로드맵</p> | |
81 | + </div> | |
82 | + <div class="box flex-column" style="gap: 10px;"> | |
83 | + <div class="dropbox"><P class="title2">여기로 드래그 하세요</P></div> | |
84 | + <div class="text-ct"><svg-icon type="mdi" :path="mdilArrowDown" style="width: 40px; height: 40px; color: #8C8E92;"></svg-icon></div> | |
85 | + <div class="dropbox"><P class="title2">여기로 드래그 하세요</P></div> | |
86 | + <div class="text-ct"><svg-icon type="mdi" :path="mdilArrowDown" style="width: 40px; height: 40px; color: #8C8E92;"></svg-icon></div> | |
87 | + <div class="dropbox"><P class="title2">여기로 드래그 하세요</P></div> | |
88 | + </div> | |
89 | + </div> | |
90 | + </div> | |
91 | + | |
92 | + </div> | |
93 | + <div class="flex justify-end mt30" style="gap: 10px;"> | |
94 | + <!-- <button type="button" title="" class="new-btn" @click="showConfirm('delete')"> | |
95 | + 추가 | |
96 | + </button> --> | |
97 | + <button type="button" title="" class="new-btn" @click="goToPage('TextBookDetail')"> | |
98 | + 취소 | |
99 | + </button> | |
100 | + <button type="button" title="" class="new-btn" @click="goToPage('TextBookDetail')"> | |
101 | + 등록 | |
102 | + </button> | |
103 | + </div> | |
104 | +</template> | |
105 | + | |
106 | +<script> | |
107 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
108 | +import { mdiMagnify, mdilArrowRight } from '@mdi/js'; | |
109 | +import { mdilArrowDown } from '@mdi/light-js'; | |
110 | +import ProgressBar from '../../component/ProgressBar.vue'; | |
111 | + | |
112 | + | |
113 | +export default { | |
114 | + data() { | |
115 | + return { | |
116 | + mdilArrowDown: mdilArrowDown, | |
117 | + mdiMagnify: mdiMagnify, | |
118 | + mdilArrowRight: mdilArrowRight, | |
119 | + timer: "00:00", | |
120 | + progress: 20 | |
121 | + } | |
122 | + }, | |
123 | + methods: { | |
124 | + goToPage(page) { | |
125 | + this.$router.push({ name: page }); | |
126 | + }, | |
127 | + increaseProgress() { | |
128 | + if (this.progress < 100) { | |
129 | + this.progress += 10; | |
130 | + } | |
131 | + }, | |
132 | + showConfirm(type) { | |
133 | + let message = ''; | |
134 | + if (type === 'delete') { | |
135 | + message = '삭제하시겠습니까?'; | |
136 | + } else if (type === 'reset') { | |
137 | + message = '초기화하시겠습니까?'; | |
138 | + } else if (type === 'save') { | |
139 | + message = '등록하시겠습니까?'; | |
140 | + } | |
141 | + | |
142 | + if (confirm(message)) { | |
143 | + this.goBack(); | |
144 | + } | |
145 | + }, | |
146 | + }, | |
147 | + watch: { | |
148 | + | |
149 | + }, | |
150 | + computed: { | |
151 | + | |
152 | + }, | |
153 | + components: { | |
154 | + SvgIcon, | |
155 | + ProgressBar | |
156 | + }, | |
157 | + mounted() { | |
158 | + console.log('Main2 mounted'); | |
159 | + } | |
160 | +} | |
161 | +</script> | |
162 | +<style scoped> | |
163 | +.search-wrap button { | |
164 | + right: 83rem; | |
165 | +} | |
166 | +</style>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/TextBookDetail.vue
+++ client/views/pages/teacher/TextBookDetail.vue
... | ... | @@ -1,70 +1,191 @@ |
1 | 1 |
<template> |
2 | 2 |
<div class="title-box flex justify-between mb40"> |
3 |
- <p class="title">교재 관리</p> |
|
4 |
- <select name="" id=""> |
|
5 |
- <option value="">A 교재</option> |
|
6 |
- </select> |
|
3 |
+ <p class="title">A교재</p> |
|
4 |
+ <!-- <select name="" id=""> |
|
5 |
+ <option value="">1단원</option> |
|
6 |
+ </select> --> |
|
7 | 7 |
</div> |
8 |
- <div class="board-wrap"> |
|
9 |
- <label for="" class="title2">단원</label> |
|
10 |
- <div class="table-pagination flex mt10"> |
|
8 |
+ <label for="" class="title1">단원</label> |
|
9 |
+ <div class="unit-pagination flex mt10" style="gap: 10px;"> |
|
11 | 10 |
<button class="selected-btn">1</button> |
12 | 11 |
<button>2</button> |
13 | 12 |
<button>3</button> |
13 |
+ <button ><svg-icon type="mdi" :path="mdiPlus" style=" padding-top: 6px; |
|
14 |
+ width: 30px; |
|
15 |
+ height: 30px;"></svg-icon></button> |
|
16 |
+ </div> |
|
17 |
+ <div class="board-wrap mt30"> |
|
18 |
+ <div class="mb20 "> |
|
19 |
+ <div class="flex justify-between mb30 align-center"> |
|
20 |
+ <label for="" class="title1">지문</label> |
|
21 |
+ <div class="look-btn flex align-center" @click="goToPage('TextList')"> |
|
22 |
+ <p>자세히 보기 </p> |
|
23 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
24 |
+ </div> |
|
25 |
+ </div> |
|
26 |
+ <div class="table-wrap"> |
|
27 |
+ <table> |
|
28 |
+ <thead> |
|
29 |
+ <td>No.</td> |
|
30 |
+ <td>제목</td> |
|
31 |
+ <td>내용</td> |
|
32 |
+ <td>작성자</td> |
|
33 |
+ <td>등록일</td> |
|
34 |
+ </thead> |
|
35 |
+ <tbody> |
|
36 |
+ <tr> |
|
37 |
+ <td></td> |
|
38 |
+ <td></td> |
|
39 |
+ <td></td> |
|
40 |
+ <td></td> |
|
41 |
+ <td></td> |
|
42 |
+ </tr> |
|
43 |
+ </tbody> |
|
44 |
+ </table> |
|
45 |
+ </div> |
|
14 | 46 |
</div> |
15 | 47 |
<hr> |
16 |
- <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('TextList')"> |
|
17 |
- <label for="" class="title1">지문</label> |
|
18 |
- <div class="flex align-center " style="gap: 10px;"> |
|
19 |
- <p>00개</p> |
|
20 |
- <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> |
|
48 |
+ <div class="mb20" > |
|
49 |
+ <div class="flex justify-between mb30 align-center"> |
|
50 |
+ <label for="" class="title1">문제</label> |
|
51 |
+ <div class="look-btn flex align-center" @click="goToPage('QuestionList')"> |
|
52 |
+ <p>자세히 보기 </p> |
|
53 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
54 |
+ </div> |
|
55 |
+ </div> |
|
56 |
+ <div class="table-wrap"> |
|
57 |
+ <table> |
|
58 |
+ <thead> |
|
59 |
+ <td>No.</td> |
|
60 |
+ <td>제목</td> |
|
61 |
+ <td>내용</td> |
|
62 |
+ <td>작성자</td> |
|
63 |
+ <td>등록일</td> |
|
64 |
+ </thead> |
|
65 |
+ <tbody> |
|
66 |
+ <tr> |
|
67 |
+ <td></td> |
|
68 |
+ <td></td> |
|
69 |
+ <td></td> |
|
70 |
+ <td></td> |
|
71 |
+ <td></td> |
|
72 |
+ </tr> |
|
73 |
+ </tbody> |
|
74 |
+ </table> |
|
21 | 75 |
</div> |
22 | 76 |
</div> |
23 |
- <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('QuestionList')"> |
|
24 |
- <label for="" class="title1">문제</label> |
|
25 |
- <div class="flex align-center " style="gap: 10px;"> |
|
26 |
- <p>00개</p> |
|
27 |
- <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> |
|
77 |
+ <hr> |
|
78 |
+ <div class="mb20" > |
|
79 |
+ <div class="flex justify-between mb30 align-center"> |
|
80 |
+ <label for="" class="title1">단어</label> |
|
81 |
+ <div class="look-btn flex align-center" @click="goToPage('VocaList')"> |
|
82 |
+ <p>자세히 보기 </p> |
|
83 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
84 |
+ </div> |
|
85 |
+ </div> |
|
86 |
+ <div class="table-wrap"> |
|
87 |
+ <table> |
|
88 |
+ <thead> |
|
89 |
+ <td>No.</td> |
|
90 |
+ <td>단어</td> |
|
91 |
+ <td>뜻</td> |
|
92 |
+ <td>작성자</td> |
|
93 |
+ <td>등록일</td> |
|
94 |
+ </thead> |
|
95 |
+ <tbody> |
|
96 |
+ <tr> |
|
97 |
+ <td></td> |
|
98 |
+ <td></td> |
|
99 |
+ <td></td> |
|
100 |
+ <td></td> |
|
101 |
+ <td></td> |
|
102 |
+ </tr> |
|
103 |
+ </tbody> |
|
104 |
+ </table> |
|
28 | 105 |
</div> |
29 | 106 |
</div> |
30 |
- <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('VocaList')"> |
|
31 |
- <label for="" class="title1">단어</label> |
|
32 |
- <div class="flex align-center " style="gap: 10px;"> |
|
33 |
- <p>00개</p> |
|
34 |
- <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> |
|
107 |
+ <hr> |
|
108 |
+ <div class="mb20" > |
|
109 |
+ <div class="flex justify-between mb30 align-center"> |
|
110 |
+ <label for="" class="title1">중간 평가</label> |
|
111 |
+ <div class="look-btn flex align-center" @click="goToPage('ExamList')"> |
|
112 |
+ <p>자세히 보기 </p> |
|
113 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
114 |
+ </div> |
|
115 |
+ </div> |
|
116 |
+ <div class="table-wrap"> |
|
117 |
+ <table> |
|
118 |
+ <thead> |
|
119 |
+ <td>No.</td> |
|
120 |
+ <td>제목</td> |
|
121 |
+ <td>내용</td> |
|
122 |
+ <td>작성자</td> |
|
123 |
+ <td>등록일</td> |
|
124 |
+ </thead> |
|
125 |
+ <tbody> |
|
126 |
+ <tr> |
|
127 |
+ <td></td> |
|
128 |
+ <td></td> |
|
129 |
+ <td></td> |
|
130 |
+ <td></td> |
|
131 |
+ <td></td> |
|
132 |
+ </tr> |
|
133 |
+ </tbody> |
|
134 |
+ </table> |
|
35 | 135 |
</div> |
36 | 136 |
</div> |
37 |
- <div class="bookmanage-btn mb20 flex justify-between align-center" @click="goToPage('ExamList')"> |
|
38 |
- <label for="" class="title1">중간 평가</label> |
|
39 |
- <div class="flex align-center " style="gap: 10px;"> |
|
40 |
- <p>00개</p> |
|
41 |
- <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> |
|
137 |
+ <hr> |
|
138 |
+ <div > |
|
139 |
+ <div class="flex justify-between mb30 align-center"> |
|
140 |
+ <label for="" class="title1">최종 평가</label> |
|
141 |
+ <div class="look-btn flex align-center" @click="goToPage('ExamList')"> |
|
142 |
+ <p>자세히 보기 </p> |
|
143 |
+ <svg-icon type="mdi" :path="mdilArrowRight" class=" ml10"></svg-icon> |
|
144 |
+ </div> |
|
42 | 145 |
</div> |
43 |
- </div> |
|
44 |
- <div class="bookmanage-btn flex justify-between align-center" @click="goToPage('ExamList')"> |
|
45 |
- <label for="" class="title1">최종 평가</label> |
|
46 |
- <div class="flex align-center " style="gap: 10px;"> |
|
47 |
- <p>00개</p> |
|
48 |
- <button><img src="../../../resources/img/btn33_101t_normal.png" alt=""></button> |
|
146 |
+ <div class="table-wrap"> |
|
147 |
+ <table> |
|
148 |
+ <thead> |
|
149 |
+ <td>No.</td> |
|
150 |
+ <td>제목</td> |
|
151 |
+ <td>내용</td> |
|
152 |
+ <td>작성자</td> |
|
153 |
+ <td>등록일</td> |
|
154 |
+ </thead> |
|
155 |
+ <tbody> |
|
156 |
+ <tr> |
|
157 |
+ <td></td> |
|
158 |
+ <td></td> |
|
159 |
+ <td></td> |
|
160 |
+ <td></td> |
|
161 |
+ <td></td> |
|
162 |
+ </tr> |
|
163 |
+ </tbody> |
|
164 |
+ </table> |
|
49 | 165 |
</div> |
50 | 166 |
</div> |
51 | 167 |
</div> |
52 |
- <div class="flex justify-end mt30"> |
|
168 |
+ <!-- <div class="flex justify-end mt30" style="gap: 10px;"> |
|
169 |
+ <button type="button" title="" class="new-btn" @click="goToPage('RoadMap')"> |
|
170 |
+ 로드맵 |
|
171 |
+ </button> |
|
53 | 172 |
<button type="button" title="" class="new-btn" @click="showConfirm('delete')"> |
54 | 173 |
삭제 |
55 | 174 |
</button> |
56 |
- </div> |
|
175 |
+ </div> --> |
|
57 | 176 |
</template> |
58 | 177 |
|
59 | 178 |
<script> |
60 | 179 |
import SvgIcon from '@jamescoyle/vue-icon'; |
61 |
-import { mdiMagnify, mdilArrowRight } from '@mdi/js'; |
|
180 |
+import { mdiMagnify,mdiPlus } from '@mdi/js'; |
|
181 |
+import { mdilArrowRight } from '@mdi/light-js'; |
|
62 | 182 |
import ProgressBar from '../../component/ProgressBar.vue'; |
63 | 183 |
|
64 | 184 |
|
65 | 185 |
export default { |
66 | 186 |
data() { |
67 | 187 |
return { |
188 |
+ mdiPlus :mdiPlus , |
|
68 | 189 |
mdiMagnify: mdiMagnify, |
69 | 190 |
mdilArrowRight: mdilArrowRight, |
70 | 191 |
timer: "00:00", |
... | ... | @@ -109,4 +230,5 @@ |
109 | 230 |
console.log('Main2 mounted'); |
110 | 231 |
} |
111 | 232 |
} |
112 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
233 |
+</script> |
|
234 |
+<style scoped></style>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/TextDetail.vue
... | ... | @@ -0,0 +1,229 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">지문 상세 보기</p> | |
4 | + </div> | |
5 | + <div class="board-wrap"> | |
6 | + <div class="flex align-center mb20"> | |
7 | + <label for="" class="title2">제목</label> | |
8 | + <input v-if="isEditing" type="text" v-model="post.textTtl" class=" data-wrap"> | |
9 | + <p class="data-wrap" v-else>{{ post.textTtl }}</p> | |
10 | + </div> | |
11 | + <div class="flex align-center mb20"> | |
12 | + <label for="" class="title2">URL</label> | |
13 | + <input v-if="isEditing" type="text" v-model="post.textUrl" class="data-wrap"> | |
14 | + <p v-else class="data-wrap">{{ post.textUrl }}</p> | |
15 | + </div> | |
16 | + <div class="flex align-center mb20" style="display: flex; flex-direction: row;"> | |
17 | + <label class="title2">형식</label> | |
18 | + <label class="title2"> | |
19 | + <input type="radio" v-model="post.textTypeId" value="1" class="data-wrap" :disabled="!isEditing"> 일반 | |
20 | + </label> | |
21 | + <label class="title2"> | |
22 | + <input type="radio" v-model="post.textTypeId" value="2" class="data-wrap" :disabled="!isEditing"> 대화 | |
23 | + </label> | |
24 | + <label class="title2"> | |
25 | + <input type="radio" v-model="post.textTypeId" value="3" class="data-wrap" :disabled="!isEditing"> 책 리스닝 | |
26 | + </label> | |
27 | + <select v-if="isEditing" id="" v-model="post.bookId" @change="fetchUnits" class="ml20"> | |
28 | + <option value="" disabled>교재를 선택하세요</option> | |
29 | + <option v-for="book in books" :key="book.book_id" :value="book.book_id"> | |
30 | + {{ book.book_nm }} | |
31 | + </option> | |
32 | + </select> | |
33 | + <label v-else for="" class="title2 flex align-center ml20" style="display: flex; width: 20rem;">교재: | |
34 | + <p class="title2">{{ post.bookName }}</p> | |
35 | + </label> | |
36 | + <select v-if="isEditing" name="" id="" v-model="post.unitId" class="ml20"> | |
37 | + <option value="" disabled>단원을 선택하세요</option> | |
38 | + <option v-for="unit in units" :key="unit.unitId" :value="unit.unitId"> | |
39 | + {{ unit.unitName }} | |
40 | + </option> | |
41 | + </select> | |
42 | + <label v-else for="" class="title2 flex align-center ml20" | |
43 | + style="display: flex; width: 20rem; text-align: right;">단원: | |
44 | + <p class="title2">{{ post.unitName }}</p> | |
45 | + </label> | |
46 | + </div> | |
47 | + <hr> | |
48 | + <div class="flex align-center"> | |
49 | + <label for="" class="title2">스크립트</label> | |
50 | + <textarea v-if="isEditing" v-model="post.textCnt" class="data-wrap"></textarea> | |
51 | + <p v-else class="data-wrap">{{ post.textCnt }}</p> | |
52 | + </div> | |
53 | + </div> | |
54 | + <div class="flex justify-between mt50"> | |
55 | + <button type="button" title="목록으로" class="new-btn" @click="goToPage('TextList')"> | |
56 | + 목록 | |
57 | + </button> | |
58 | + <div class="flex"> | |
59 | + <button type="button" title="수정" class="new-btn mr10" @click="toggleEdit"> | |
60 | + {{ isEditing ? '저장' : '수정' }} | |
61 | + </button> | |
62 | + <button type="button" title="삭제" class="new-btn" @click="deletePost"> | |
63 | + 삭제 | |
64 | + </button> | |
65 | + </div> | |
66 | + </div> | |
67 | +</template> | |
68 | + | |
69 | +<script> | |
70 | +import axios from "axios"; | |
71 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
72 | +import { mdiMagnify } from '@mdi/js'; | |
73 | + | |
74 | +export default { | |
75 | + data() { | |
76 | + return { | |
77 | + mdiMagnify: mdiMagnify, | |
78 | + post: { | |
79 | + textId: "", | |
80 | + textTtl: "", | |
81 | + textCnt: "", | |
82 | + textUrl: "", | |
83 | + textTypeId: "", | |
84 | + bookId: "", | |
85 | + unitId: "", | |
86 | + bookName: "", | |
87 | + unitName: "" | |
88 | + }, | |
89 | + books: [], | |
90 | + units: [], | |
91 | + isEditing: false | |
92 | + }; | |
93 | + }, | |
94 | + computed: { | |
95 | + textId() { | |
96 | + return this.$route.query.textId; | |
97 | + }, | |
98 | + selectedBookName() { | |
99 | + const book = this.books.find(book => book.book_id === this.post.bookId); | |
100 | + return book ? book.book_nm : ''; | |
101 | + }, | |
102 | + selectedUnitName() { | |
103 | + const unit = this.units.find(unit => unit.unit_id === this.post.unitId); | |
104 | + return unit ? unit.unit_nm : ''; | |
105 | + } | |
106 | + }, | |
107 | + methods: { | |
108 | + goToPage(page) { | |
109 | + this.$router.push({ name: page }); | |
110 | + }, | |
111 | + fetchPostDetail() { | |
112 | + const textId = this.$route.query.textId; | |
113 | + axios.post('/text/selectOneText.json', { textId }, { | |
114 | + headers: { | |
115 | + "Content-Type": "application/json; charset=UTF-8", | |
116 | + } | |
117 | + }) | |
118 | + .then(response => { | |
119 | + if (response.data && response.data[0]) { | |
120 | + this.post.textId = response.data[0].text_id; | |
121 | + this.post.textTtl = response.data[0].text_ttl; | |
122 | + this.post.textCnt = response.data[0].text_cnt; | |
123 | + this.post.textUrl = response.data[0].text_url; | |
124 | + this.post.textTypeId = response.data[0].text_type_id; | |
125 | + this.post.bookId = response.data[0].book_id; | |
126 | + this.post.unitId = response.data[0].unit_id; | |
127 | + this.post.bookName = response.data[0].book_name; | |
128 | + this.post.unitName = response.data[0].unit_name; | |
129 | + } else { | |
130 | + this.error = "Failed to fetch post details."; | |
131 | + } | |
132 | + }) | |
133 | + .catch(error => { | |
134 | + console.error("Error fetching post detail:", error); | |
135 | + this.error = "Failed to fetch post details."; | |
136 | + }); | |
137 | + }, | |
138 | + dataInsert() { | |
139 | + this.newPost = { | |
140 | + textId: this.post.textId, | |
141 | + textTtl: this.post.textTtl, | |
142 | + textCnt: this.post.textCnt, | |
143 | + textUrl: this.post.textUrl, | |
144 | + textTypeId: this.post.textTypeId, | |
145 | + bookId: this.post.bookId, | |
146 | + unitId: this.post.unitId | |
147 | + }; | |
148 | + console.log(this.newPost) | |
149 | + | |
150 | + axios.post("/text/textUpdate.json", this.newPost, { | |
151 | + headers: { | |
152 | + "Content-Type": "application/json; charset=UTF-8", | |
153 | + } | |
154 | + }) | |
155 | + .then(response => { | |
156 | + alert(response.data.message); | |
157 | + this.fetchPostDetail(); | |
158 | + }) | |
159 | + .catch(error => { | |
160 | + console.log("dataInsert - error:", error.response.data); | |
161 | + alert("게시글 등록에 오류가 발생했습니다."); | |
162 | + }); | |
163 | + }, | |
164 | + toggleEdit() { | |
165 | + if (this.isEditing) { | |
166 | + this.dataInsert(); | |
167 | + this.isEditing = false; | |
168 | + } else { | |
169 | + this.isEditing = true; | |
170 | + this.fetchBooks(); | |
171 | + } | |
172 | + }, | |
173 | + deletePost() { | |
174 | + axios.post("/text/textDelete.json", { textId: this.textId }, { | |
175 | + headers: { | |
176 | + "Content-Type": "application/json; charset=UTF-8", | |
177 | + } | |
178 | + }) | |
179 | + .then(response => { | |
180 | + alert(response.data.message); | |
181 | + this.goToPage('TextList'); | |
182 | + }) | |
183 | + .catch(error => { | |
184 | + console.error("Error deleting post:", error); | |
185 | + alert("게시글 삭제에 오류가 발생했습니다."); | |
186 | + }); | |
187 | + }, | |
188 | + fetchBooks() { | |
189 | + axios.post("/book/findAll.json", {}, { | |
190 | + headers: { | |
191 | + "Content-Type": "application/json; charset=UTF-8", | |
192 | + } | |
193 | + }) | |
194 | + .then(response => { | |
195 | + this.books = response.data; | |
196 | + }) | |
197 | + .catch(error => { | |
198 | + console.error("fetchBooks - error:", error); | |
199 | + alert("교재 목록을 불러오는 중 오류가 발생했습니다."); | |
200 | + }); | |
201 | + }, | |
202 | + fetchUnits() { | |
203 | + if (!this.post.bookId) return; | |
204 | + | |
205 | + axios.post("/unit/unitList.json", { bookId: this.post.bookId }, { | |
206 | + headers: { | |
207 | + "Content-Type": "application/json; charset=UTF-8", | |
208 | + } | |
209 | + }) | |
210 | + .then(response => { | |
211 | + this.units = response.data; | |
212 | + }) | |
213 | + .catch(error => { | |
214 | + console.error("fetchUnits - error:", error); | |
215 | + alert("단원 목록을 불러오는 중 오류가 발생했습니다."); | |
216 | + }); | |
217 | + } | |
218 | + }, | |
219 | + mounted() { | |
220 | + this.fetchPostDetail(); | |
221 | + }, | |
222 | + components: { | |
223 | + SvgIcon | |
224 | + } | |
225 | +}; | |
226 | +</script> | |
227 | + | |
228 | +<style scoped> | |
229 | +</style> |
--- client/views/pages/teacher/TextInsert.vue
+++ client/views/pages/teacher/TextInsert.vue
... | ... | @@ -1,63 +1,221 @@ |
1 |
+ |
|
1 | 2 |
<template> |
2 | 3 |
<div class="title-box flex justify-between mb40"> |
3 | 4 |
<p class="title">지문 등록</p> |
4 | 5 |
</div> |
5 |
- <div class="board-wrap"> |
|
6 |
- <div class="flex align-center mb20"> |
|
7 |
- <label for="" class="title2">제목</label> |
|
8 |
- <input type="text" class="data-wrap"> |
|
9 |
- </div> |
|
10 |
- <div class="flex align-center"> |
|
11 |
- <label for="" class="title2">URL</label> |
|
12 |
- <input type="text" class="data-wrap"> |
|
13 |
- </div> |
|
14 |
- <hr> |
|
15 |
- <div class="flex align-center"> |
|
16 |
- <label for="" class="title2">스크립트</label> |
|
17 |
- <textarea name="" id="" class="data-wrap"></textarea> |
|
18 |
- </div> |
|
6 |
+ <div class="board-wrap"> |
|
7 |
+ <div class="flex align-center mb20"> |
|
8 |
+ <label for="" class="title2">제목</label> |
|
9 |
+ <input type="text" class="data-wrap" v-model="newData.textTtl"> |
|
19 | 10 |
</div> |
20 |
- <div class="flex justify-between mt50"> |
|
21 |
- <button type="button" title="글쓰기" class="new-btn" @click="goToPage('TextList')"> |
|
22 |
- 목록 |
|
23 |
- </button> |
|
24 |
- <div class="flex"> |
|
25 |
- <button type="button" title="글쓰기" class="new-btn mr10" > |
|
26 |
- 수정 |
|
27 |
- </button> |
|
28 |
- <button type="button" title="글쓰기" class="new-btn" > |
|
29 |
- 삭제 |
|
30 |
- </button> |
|
31 |
- </div> |
|
11 |
+ <div class="flex align-center mb20"> |
|
12 |
+ <label for="" class="title2">URL</label> |
|
13 |
+ <input type="text" class="data-wrap" v-model="newData.textUrl"> |
|
32 | 14 |
</div> |
15 |
+ <div class="flex align-center"> |
|
16 |
+ <label class="title2">형식</label> |
|
17 |
+ <label class="title2"> |
|
18 |
+ <input type="radio" v-model="newData.textTypeId" value="1" class="data-wrap"> 일반 |
|
19 |
+ </label> |
|
20 |
+ <label class="title2"> |
|
21 |
+ <input type="radio" v-model="newData.textTypeId" value="2" class="data-wrap"> 대화 |
|
22 |
+ </label> |
|
23 |
+ <label class="title2"> |
|
24 |
+ <input type="radio" v-model="newData.textTypeId" value="3" class="data-wrap"> 책 리스닝 |
|
25 |
+ </label> |
|
26 |
+ <select name="" id="" v-model="newData.bookId" @change="fetchUnits" class="ml20"> |
|
27 |
+ <option value="" disabled>교재를 선택하세요</option> |
|
28 |
+ <option v-for="book in books" :key="book.book_id" :value="book.book_id"> |
|
29 |
+ {{ book.book_nm }} |
|
30 |
+ </option> |
|
31 |
+ </select> |
|
32 |
+ <select name="" id="" v-model="newData.unitId" class="ml20"> |
|
33 |
+ <option value="" disabled>단원을 선택하세요</option> |
|
34 |
+ <option v-for="unit in units" :key="unit.unitId" :value="unit.unitId"> |
|
35 |
+ {{ unit.unitName }} |
|
36 |
+ </option> |
|
37 |
+ </select> |
|
38 |
+ </div> |
|
39 |
+ <hr> |
|
40 |
+ <div class="flex align-center"> |
|
41 |
+ <label for="" class="title2">스크립트</label> |
|
42 |
+ <textarea name="" id="" class="data-wrap" v-model="newData.textCnt"></textarea> |
|
43 |
+ </div> |
|
44 |
+ </div> |
|
45 |
+ <div class="flex justify-between mt50"> |
|
46 |
+ <button type="button" title="글쓰기" class="new-btn" @click="goToPage('TextList')"> |
|
47 |
+ 목록 |
|
48 |
+ </button> |
|
49 |
+ <div class="flex"> |
|
50 |
+ <button type="button" title="글쓰기" class="new-btn mr10" @click="handleButtonAction"> |
|
51 |
+ 작성 |
|
52 |
+ </button> |
|
53 |
+ </div> |
|
54 |
+ </div> |
|
33 | 55 |
</template> |
34 | 56 |
|
35 | 57 |
<script> |
58 |
+import axios from "axios"; |
|
36 | 59 |
import SvgIcon from '@jamescoyle/vue-icon'; |
37 |
-import { mdiMagnify} from '@mdi/js'; |
|
60 |
+import { mdiMagnify } from '@mdi/js'; |
|
38 | 61 |
|
39 | 62 |
|
40 | 63 |
export default { |
41 |
- data () { |
|
64 |
+ computed: { |
|
65 |
+ textId() { |
|
66 |
+ return this.$route.query.textId; |
|
67 |
+ } |
|
68 |
+ }, |
|
69 |
+ data() { |
|
42 | 70 |
return { |
43 | 71 |
mdiMagnify: mdiMagnify, |
72 |
+ post: null, |
|
73 |
+ newData: { |
|
74 |
+ textId: "", |
|
75 |
+ textTtl: "", |
|
76 |
+ textCnt: "", |
|
77 |
+ textUrl: "", |
|
78 |
+ textTypeId: "", |
|
79 |
+ //fileMngId:"", |
|
80 |
+ // userId:"". |
|
81 |
+ bookId: "", |
|
82 |
+ unitId: "" |
|
83 |
+ }, |
|
84 |
+ books: [], |
|
85 |
+ units: [], |
|
44 | 86 |
} |
45 | 87 |
}, |
46 | 88 |
methods: { |
47 | 89 |
goToPage(page) { |
48 |
- this.$router.push({ name: page }); |
|
49 |
- }, |
|
90 |
+ this.$router.push({ name: page }); |
|
91 |
+ }, fetchPostDetail() { |
|
92 |
+ const textId = this.$route.query.textId |
|
93 |
+ axios({ |
|
94 |
+ url: `/text/selectOneText.json`, |
|
95 |
+ method: "post", |
|
96 |
+ headers: { |
|
97 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
98 |
+ }, |
|
99 |
+ data: { "textId": textId } |
|
100 |
+ }) |
|
101 |
+ .then(response => { |
|
102 |
+ if (response.data && response.data[0]) { |
|
103 |
+ this.post = response.data[0]; |
|
104 |
+ this.editTitle = this.post.title; |
|
105 |
+ this.editContent = this.post.content; |
|
106 |
+ console.log(this.post); |
|
107 |
+ } else { |
|
108 |
+ this.error = "Failed to fetch post details."; |
|
109 |
+ } |
|
110 |
+ }) |
|
111 |
+ .catch(error => { |
|
112 |
+ console.error("Error fetching post detail:", error); |
|
113 |
+ this.error = "Failed to fetch post details."; |
|
114 |
+ }); |
|
115 |
+ }, dataInsert() { |
|
116 |
+ const vm = this; |
|
117 |
+ axios({ |
|
118 |
+ url: "/text/insertText.json", |
|
119 |
+ method: "post", |
|
120 |
+ headers: { |
|
121 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
122 |
+ }, |
|
123 |
+ data: vm.newData, |
|
124 |
+ }) |
|
125 |
+ .then(response => { |
|
126 |
+ alert(response.data.message); |
|
127 |
+ this.goToPage('TextList') |
|
128 |
+ }) |
|
129 |
+ .catch(error => { |
|
130 |
+ console.log("dataInsert - error : ", error.response.data); |
|
131 |
+ alert("게시글 등록에 오류가 발생했습니다."); |
|
132 |
+ }); |
|
133 |
+ }, |
|
134 |
+ handleButtonAction() { |
|
135 |
+ if (!this.newData.textTtl) { |
|
136 |
+ alert("제목을 입력해 주세요."); |
|
137 |
+ return; |
|
138 |
+ } |
|
139 |
+ |
|
140 |
+ if (!this.newData.textUrl) { |
|
141 |
+ alert("url을 입력해 주세요."); |
|
142 |
+ return; |
|
143 |
+ } |
|
144 |
+ |
|
145 |
+ if (!this.newData.textTypeId) { |
|
146 |
+ alert("지문 형식을 입력해 주세요."); |
|
147 |
+ return; |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ if (!this.newData.bookId) { |
|
151 |
+ alert("교재를 선택해 주세요."); |
|
152 |
+ return; |
|
153 |
+ } |
|
154 |
+ |
|
155 |
+ if (!this.newData.unitId) { |
|
156 |
+ alert("단원을 선택해 주세요."); |
|
157 |
+ return; |
|
158 |
+ } |
|
159 |
+ |
|
160 |
+ if (!this.newData.textCnt) { |
|
161 |
+ alert("내용을 입력해 주세요."); |
|
162 |
+ return; |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ this.dataInsert(); |
|
166 |
+ }, |
|
167 |
+ fetchBooks() { |
|
168 |
+ axios({ |
|
169 |
+ url: "/book/findAll.json", |
|
170 |
+ method: "post", |
|
171 |
+ headers: { |
|
172 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
173 |
+ }, |
|
174 |
+ }) |
|
175 |
+ .then(response => { |
|
176 |
+ console.log(response.data) |
|
177 |
+ this.books = response.data; |
|
178 |
+ }) |
|
179 |
+ .catch(error => { |
|
180 |
+ console.error("fetchBooks - error: ", error); |
|
181 |
+ alert("교재 목록을 불러오는 중 오류가 발생했습니다."); |
|
182 |
+ }); |
|
183 |
+ }, |
|
184 |
+ fetchUnits() { |
|
185 |
+ if (!this.newData.bookId) return; |
|
186 |
+ |
|
187 |
+ axios({ |
|
188 |
+ url: "/unit/unitList.json", |
|
189 |
+ method: "post", |
|
190 |
+ headers: { |
|
191 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
192 |
+ }, |
|
193 |
+ data: { |
|
194 |
+ "bookId": this.newData.bookId |
|
195 |
+ }, |
|
196 |
+ }) |
|
197 |
+ .then(response => { |
|
198 |
+ console.log(response.data) |
|
199 |
+ this.units = response.data; |
|
200 |
+ }) |
|
201 |
+ .catch(error => { |
|
202 |
+ console.error("fetchUnits - error: ", error); |
|
203 |
+ alert("단원 목록을 불러오는 중 오류가 발생했습니다."); |
|
204 |
+ }); |
|
205 |
+ }, |
|
50 | 206 |
}, |
51 | 207 |
watch: { |
52 | 208 |
|
53 | 209 |
}, |
54 | 210 |
computed: { |
55 |
- |
|
211 |
+ |
|
56 | 212 |
}, |
57 |
- components:{ |
|
213 |
+ components: { |
|
58 | 214 |
SvgIcon |
59 | 215 |
}, |
60 | 216 |
mounted() { |
217 |
+ this.fetchPostDetail(); |
|
218 |
+ this.fetchBooks(); |
|
61 | 219 |
console.log('Main2 mounted'); |
62 | 220 |
} |
63 | 221 |
} |
--- client/views/pages/teacher/TextList.vue
+++ client/views/pages/teacher/TextList.vue
... | ... | @@ -1,69 +1,109 @@ |
1 | 1 |
<template> |
2 |
- <div class="title-box flex justify-between mb40"> |
|
2 |
+ <div class="title-box flex justify-between mb40 myplan"> |
|
3 | 3 |
<p class="title">지문</p> |
4 |
- <select name="" id=""> |
|
5 |
- <option value="">1단원</option> |
|
4 |
+ <select name="" id="" v-model="selectedBook" @change="fetchUnits"> |
|
5 |
+ <option value="" disabled>교재를 선택하세요</option> |
|
6 |
+ <option v-for="book in books" :key="book.book_id" :value="book.book_id"> |
|
7 |
+ {{ book.book_nm }} |
|
8 |
+ </option> |
|
6 | 9 |
</select> |
7 | 10 |
</div> |
11 |
+ <label for="" class="title2">단원</label> |
|
12 |
+ <div class="unit-pagination flex mt10 mb20" style="gap: 10px;"> |
|
13 |
+ <button |
|
14 |
+ v-for="(unit, index) in units" |
|
15 |
+ :key="index" |
|
16 |
+ :class="{ 'selected-btn': selectedUnit === unit.unitId }" |
|
17 |
+ @click="selectUnit(unit.unitId)"> |
|
18 |
+ {{ unit.unitName }} |
|
19 |
+ </button> |
|
20 |
+ </div> |
|
8 | 21 |
<div class="search-wrap flex justify-end mb20"> |
9 |
- <select name="" id="" class="mr10 data-wrap"> |
|
10 |
- <option value="">전체</option> |
|
11 |
- </select> |
|
12 |
- <input type="text" placeholder="검색하세요."> |
|
13 |
- <button type="button" title="위원회 검색"> |
|
14 |
- <img src="../../../resources/img/look_t.png" alt=""> |
|
15 |
- </button> |
|
16 |
- </div> |
|
17 |
- <div class="table-wrap"> |
|
18 |
- <table> |
|
19 |
- <thead> |
|
22 |
+ <select name="" id="" class="mr10 data-wrap" style="width: 15rem;" v-model="option"> |
|
23 |
+ <option value="" disabled>검색유형</option> |
|
24 |
+ <option v-for="g in optionList" :key="g.value" :value="g.value">{{ g.text }}</option> |
|
25 |
+ </select> |
|
26 |
+ <input type="text" placeholder="검색하세요." v-model="keyword"> |
|
27 |
+ <button type="button" title="위원회 검색" @click="search"> |
|
28 |
+ <img src="../../../resources/img/look_t.png" alt=""> |
|
29 |
+ </button> |
|
30 |
+ </div> |
|
31 |
+ <div class="table-wrap"> |
|
32 |
+ <table> |
|
33 |
+ <thead> |
|
34 |
+ <tr> |
|
20 | 35 |
<td>No.</td> |
21 | 36 |
<td>제목</td> |
22 | 37 |
<td>내용</td> |
23 | 38 |
<td>작성자</td> |
24 | 39 |
<td>등록일</td> |
25 |
- </thead> |
|
26 |
- <tbody> |
|
27 |
- <tr @click="goToPage('TextInsert')"> |
|
28 |
- <td></td> |
|
29 |
- <td></td> |
|
30 |
- <td></td> |
|
31 |
- <td></td> |
|
32 |
- <td></td> |
|
33 |
- </tr> |
|
34 |
- </tbody> |
|
35 |
- </table> |
|
36 |
- <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> |
|
37 |
- <button><img src="../../../resources/img/btn27_90t_normal.png" alt=""></button> |
|
38 |
- <button class="selected-btn">1</button> |
|
39 |
- <button>2</button> |
|
40 |
- <button>3</button> |
|
41 |
- <button><img src="../../../resources/img/btn28_90t_normal.png" alt=""></button> |
|
42 |
- </article> |
|
43 |
- <div class="flex justify-end "> |
|
44 |
- <button type="button" title="등록" class="new-btn" @click="goToPage('TextInsert')"> |
|
45 |
- 등록 |
|
46 |
- </button> |
|
40 |
+ </tr> |
|
41 |
+ </thead> |
|
42 |
+ <tbody> |
|
43 |
+ <tr v-for="(post, index) in posts" :key="index" class="post" |
|
44 |
+ @click="goToPage('TextDetail', post.textId)"> |
|
45 |
+ <td>{{ index + 1 + (currentPage - 1) * pageSize }}</td> |
|
46 |
+ <td>{{ post.textTtl.slice(0, 20) }}{{ post.textTtl.length > 20 ? '...' : '' }}</td> |
|
47 |
+ <td>{{ post.textCnt.slice(0, 20) }}{{ post.textCnt.length > 20 ? '...' : '' }}</td> |
|
48 |
+ <td>{{ post.userId }}</td> |
|
49 |
+ <td>{{ post.regDt }}</td> |
|
50 |
+ </tr> |
|
51 |
+ </tbody> |
|
52 |
+ </table> |
|
53 |
+ <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;"> |
|
54 |
+ <button @click="changePage(currentPage - 1)" :disabled="currentPage === 1"> |
|
55 |
+ <img src="../../../resources/img/btn27_90t_normal.png" alt="Previous"> |
|
56 |
+ </button> |
|
57 |
+ <button v-for="page in totalPages" :key="page" @click="changePage(page)" |
|
58 |
+ :class="{ 'selected-btn': currentPage === page }"> |
|
59 |
+ {{ page }} |
|
60 |
+ </button> |
|
61 |
+ <button @click="changePage(currentPage + 1)" :disabled="currentPage === totalPages"> |
|
62 |
+ <img src="../../../resources/img/btn28_90t_normal.png" alt="Next"> |
|
63 |
+ </button> |
|
64 |
+ </article> |
|
65 |
+ <div class="flex justify-end"> |
|
66 |
+ <button type="button" title="등록" class="new-btn" @click="goToPage('TextInsert')"> |
|
67 |
+ 등록 |
|
68 |
+ </button> |
|
47 | 69 |
</div> |
48 |
- </div> |
|
70 |
+ </div> |
|
49 | 71 |
</template> |
50 | 72 |
|
51 | 73 |
<script> |
74 |
+import axios from "axios"; |
|
52 | 75 |
import SvgIcon from '@jamescoyle/vue-icon'; |
53 |
-import { mdiMagnify} from '@mdi/js'; |
|
54 |
- |
|
76 |
+import { mdiMagnify } from '@mdi/js'; |
|
55 | 77 |
|
56 | 78 |
export default { |
57 |
- data () { |
|
79 |
+ data() { |
|
58 | 80 |
return { |
59 | 81 |
mdiMagnify: mdiMagnify, |
60 |
- } |
|
82 |
+ posts: [], |
|
83 |
+ currentPage: 1, |
|
84 |
+ pageSize: 10, |
|
85 |
+ totalPosts: 0, |
|
86 |
+ option: "", |
|
87 |
+ keyword: "", |
|
88 |
+ books: [], |
|
89 |
+ selectedBook: "", |
|
90 |
+ optionList: [ |
|
91 |
+ { text: "번호", value: "textId" }, |
|
92 |
+ { text: "제목", value: "textTtl" }, |
|
93 |
+ { text: "내용", value: "textCnt" }, |
|
94 |
+ { text: "작성자", value: "userId" }, |
|
95 |
+ { text: "등록일", value: "regDt" }, |
|
96 |
+ ], |
|
97 |
+ units: [], |
|
98 |
+ selectedUnit: null, |
|
99 |
+ searching: false, |
|
100 |
+ }; |
|
61 | 101 |
}, |
62 | 102 |
methods: { |
63 |
- goToPage(page) { |
|
64 |
- this.$router.push({ name: page }); |
|
65 |
- }, |
|
66 |
- showConfirm(type) { |
|
103 |
+ goToPage(page, textId) { |
|
104 |
+ this.$router.push({ name: page, query: { textId } }); |
|
105 |
+ }, |
|
106 |
+ showConfirm(type) { |
|
67 | 107 |
let message = ''; |
68 | 108 |
if (type === 'cancel') { |
69 | 109 |
message = '삭제하시겠습니까?'; |
... | ... | @@ -77,19 +117,110 @@ |
77 | 117 |
this.goBack(); |
78 | 118 |
} |
79 | 119 |
}, |
120 |
+ selectUnit(unitId) { |
|
121 |
+ this.selectedUnit = unitId; |
|
122 |
+ this.fetchData(); |
|
123 |
+ }, |
|
124 |
+ search() { |
|
125 |
+ if (!this.option) { |
|
126 |
+ alert("검색유형을 선택해 주세요") |
|
127 |
+ } else { |
|
128 |
+ this.currentPage = 1; |
|
129 |
+ this.searching = true; |
|
130 |
+ this.fetchData(); |
|
131 |
+ } |
|
132 |
+ }, |
|
133 |
+ fetchData() { |
|
134 |
+ const idx = (this.currentPage - 1) * this.pageSize; |
|
135 |
+ axios({ |
|
136 |
+ url: "/text/textSearch.json", |
|
137 |
+ method: "post", |
|
138 |
+ headers: { |
|
139 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
140 |
+ }, |
|
141 |
+ data: { |
|
142 |
+ "option": this.option, |
|
143 |
+ "keyword": this.keyword, |
|
144 |
+ "pageSize": this.pageSize, |
|
145 |
+ "startIndex": idx, |
|
146 |
+ "unitId": this.selectedUnit |
|
147 |
+ }, |
|
148 |
+ }) |
|
149 |
+ .then(response => { |
|
150 |
+ this.posts = response.data.list; |
|
151 |
+ if (!this.searching || this.keyword === "") { |
|
152 |
+ this.totalPosts = response.data.totalText; |
|
153 |
+ } else if (this.searching) { |
|
154 |
+ this.totalPosts = response.data.resultCount; |
|
155 |
+ } |
|
156 |
+ this.posts.forEach(post => { |
|
157 |
+ let regDt = post.regDt; |
|
158 |
+ let date = new Date(regDt); |
|
159 |
+ post.regDt = date.toISOString().split('T')[0]; |
|
160 |
+ }); |
|
161 |
+ }) |
|
162 |
+ .catch(error => { |
|
163 |
+ console.error("fetchData - error: ", error); |
|
164 |
+ alert("검색 중 오류가 발생했습니다."); |
|
165 |
+ }); |
|
166 |
+ }, |
|
167 |
+ changePage(page) { |
|
168 |
+ if (page > 0 && page <= this.totalPages) { |
|
169 |
+ this.currentPage = page; |
|
170 |
+ this.fetchData(); |
|
171 |
+ } |
|
172 |
+ }, |
|
173 |
+ fetchBooks() { |
|
174 |
+ axios({ |
|
175 |
+ url: "/book/findAll.json", |
|
176 |
+ method: "post", |
|
177 |
+ headers: { |
|
178 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
179 |
+ }, |
|
180 |
+ }) |
|
181 |
+ .then(response => { |
|
182 |
+ console.log(response.data) |
|
183 |
+ this.books = response.data; |
|
184 |
+ }) |
|
185 |
+ .catch(error => { |
|
186 |
+ console.error("fetchBooks - error: ", error); |
|
187 |
+ alert("교재 목록을 불러오는 중 오류가 발생했습니다."); |
|
188 |
+ }); |
|
189 |
+ }, |
|
190 |
+ fetchUnits() { |
|
191 |
+ if (!this.selectedBook) return; |
|
80 | 192 |
|
81 |
- }, |
|
82 |
- watch: { |
|
83 |
- |
|
193 |
+ axios({ |
|
194 |
+ url: "/unit/unitList.json", |
|
195 |
+ method: "post", |
|
196 |
+ headers: { |
|
197 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
198 |
+ }, |
|
199 |
+ data: { |
|
200 |
+ "bookId": this.selectedBook |
|
201 |
+ }, |
|
202 |
+ }) |
|
203 |
+ .then(response => { |
|
204 |
+ console.log(response.data) |
|
205 |
+ this.units = response.data; |
|
206 |
+ }) |
|
207 |
+ .catch(error => { |
|
208 |
+ console.error("fetchUnits - error: ", error); |
|
209 |
+ alert("단원 목록을 불러오는 중 오류가 발생했습니다."); |
|
210 |
+ }); |
|
211 |
+ }, |
|
84 | 212 |
}, |
85 | 213 |
computed: { |
86 |
- |
|
214 |
+ totalPages() { |
|
215 |
+ return Math.ceil(this.totalPosts / this.pageSize); |
|
216 |
+ } |
|
87 | 217 |
}, |
88 |
- components:{ |
|
218 |
+ components: { |
|
89 | 219 |
SvgIcon |
90 | 220 |
}, |
91 | 221 |
mounted() { |
92 |
- console.log('Main2 mounted'); |
|
222 |
+ this.fetchBooks(); // Fetch books when the component is mounted |
|
223 |
+ this.fetchData(); // Fetch data for the default view |
|
93 | 224 |
} |
94 |
-} |
|
95 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
225 |
+}; |
|
226 |
+</script> |
+++ client/views/pages/teacher/VocaDetail.vue
... | ... | @@ -0,0 +1,102 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">단어장 등록</p> | |
4 | + </div> | |
5 | + <div class="board-wrap"> | |
6 | + <div class="flex align-center mb20"> | |
7 | + <label for="" class="title2">지문</label> | |
8 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
9 | + <option value="bbsTtl">제목</option> | |
10 | + <option value="bbsCnt">내용</option> | |
11 | + <option value="userNm">작성자</option> | |
12 | + <option value="bbsCls">카테고리</option> | |
13 | + </select> | |
14 | + </div> | |
15 | + <div class="flex align-center"> | |
16 | + <label for="" class="title2">단어 목록</label> | |
17 | + <div class="flex-column" style="gap: 10px;"> | |
18 | + <div class="flex align-center" style="gap: 10px;"> | |
19 | + <input type="text" class="data-wrap" placeholder="영어"> | |
20 | + <input type="text" class="data-wrap" placeholder="한글"> | |
21 | + <button type="button" @click="addThesis"> | |
22 | + <img src="../../../resources/img/btn39_120t_normal.png" alt=""> | |
23 | + | |
24 | + </button> | |
25 | + </div> | |
26 | + <div class="flex align-center " style="gap: 10px;" v-for="(thesis, index) in thesised" :key="thesis.id"> | |
27 | + <input type="text" class="data-wrap" placeholder="영어"> | |
28 | + <input type="text" class="data-wrap" placeholder="한글"> | |
29 | + <button type="button" @click="removeThesis(thesis.id)"> | |
30 | + <img src="../../../resources/img/btn38_120t_normal.png" alt=""> | |
31 | + </button> | |
32 | + | |
33 | + </div> | |
34 | + </div> | |
35 | + | |
36 | + </div> | |
37 | + </div> | |
38 | + <div class="flex justify-between mt50"> | |
39 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('TextList')"> | |
40 | + 목록 | |
41 | + </button> | |
42 | + <div class="flex"> | |
43 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
44 | + 취소 | |
45 | + </button> | |
46 | + <button type="button" title="글쓰기" class="new-btn"> | |
47 | + 수정 | |
48 | + </button> | |
49 | + </div> | |
50 | + </div> | |
51 | +</template> | |
52 | + | |
53 | +<script> | |
54 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
55 | +import { mdiMagnify, mdiPlusCircleOutline, mdiWindowClose } from '@mdi/js'; | |
56 | + | |
57 | + | |
58 | +export default { | |
59 | + data() { | |
60 | + return { | |
61 | + thesised: [], | |
62 | + mdiPlusCircleOutline: mdiPlusCircleOutline, | |
63 | + mdiMagnify: mdiMagnify, | |
64 | + mdiWindowClose: mdiWindowClose, | |
65 | + } | |
66 | + }, | |
67 | + methods: { | |
68 | + // 논문실적 버튼 추가 | |
69 | + addThesis() { | |
70 | + // 고유 ID로 현재 시간의 타임스탬프를 사용 | |
71 | + const uniqueId = Date.now(); | |
72 | + this.thesised.push({ | |
73 | + id: uniqueId, // 고유 ID 추가 | |
74 | + | |
75 | + }); | |
76 | + }, | |
77 | + removeThesis(thesisId) { | |
78 | + // ID를 기준으로 교육 정보 객체를 찾아서 삭제 | |
79 | + const index = this.thesised.findIndex(thesis => thesis.id === thesisId); | |
80 | + if (index !== -1) { | |
81 | + this.thesised.splice(index, 1); | |
82 | + } | |
83 | + }, | |
84 | + // | |
85 | + goToPage(page) { | |
86 | + this.$router.push({ name: page }); | |
87 | + }, | |
88 | + }, | |
89 | + watch: { | |
90 | + | |
91 | + }, | |
92 | + computed: { | |
93 | + | |
94 | + }, | |
95 | + components: { | |
96 | + SvgIcon | |
97 | + }, | |
98 | + mounted() { | |
99 | + console.log('Main2 mounted'); | |
100 | + } | |
101 | +} | |
102 | +</script>(파일 끝에 줄바꿈 문자 없음) |
+++ client/views/pages/teacher/VocaInsert.vue
... | ... | @@ -0,0 +1,102 @@ |
1 | +<template> | |
2 | + <div class="title-box flex justify-between mb40"> | |
3 | + <p class="title">단어장 등록</p> | |
4 | + </div> | |
5 | + <div class="board-wrap"> | |
6 | + <div class="flex align-center mb20"> | |
7 | + <label for="" class="title2">지문</label> | |
8 | + <select v-model="selectedSearchOption" class="mr10 data-wrap"> | |
9 | + <option value="bbsTtl">제목</option> | |
10 | + <option value="bbsCnt">내용</option> | |
11 | + <option value="userNm">작성자</option> | |
12 | + <option value="bbsCls">카테고리</option> | |
13 | + </select> | |
14 | + </div> | |
15 | + <div class="flex align-center"> | |
16 | + <label for="" class="title2">단어 목록</label> | |
17 | + <div class="flex-column" style="gap: 10px;"> | |
18 | + <div class="flex align-center" style="gap: 10px;"> | |
19 | + <input type="text" class="data-wrap" placeholder="영어"> | |
20 | + <input type="text" class="data-wrap" placeholder="한글"> | |
21 | + <button type="button" @click="addThesis"> | |
22 | + <img src="../../../resources/img/btn39_120t_normal.png" alt=""> | |
23 | + | |
24 | + </button> | |
25 | + </div> | |
26 | + <div class="flex align-center " style="gap: 10px;" v-for="(thesis, index) in thesised" :key="thesis.id"> | |
27 | + <input type="text" class="data-wrap" placeholder="영어"> | |
28 | + <input type="text" class="data-wrap" placeholder="한글"> | |
29 | + <button type="button" @click="removeThesis(thesis.id)"> | |
30 | + <img src="../../../resources/img/btn38_120t_normal.png" alt=""> | |
31 | + </button> | |
32 | + | |
33 | + </div> | |
34 | + </div> | |
35 | + | |
36 | + </div> | |
37 | + </div> | |
38 | + <div class="flex justify-between mt50"> | |
39 | + <button type="button" title="글쓰기" class="new-btn" @click="goToPage('TextList')"> | |
40 | + 목록 | |
41 | + </button> | |
42 | + <div class="flex"> | |
43 | + <button type="button" title="글쓰기" class="new-btn mr10"> | |
44 | + 취소 | |
45 | + </button> | |
46 | + <button type="button" title="글쓰기" class="new-btn"> | |
47 | + 등록 | |
48 | + </button> | |
49 | + </div> | |
50 | + </div> | |
51 | +</template> | |
52 | + | |
53 | +<script> | |
54 | +import SvgIcon from '@jamescoyle/vue-icon'; | |
55 | +import { mdiMagnify, mdiPlusCircleOutline, mdiWindowClose } from '@mdi/js'; | |
56 | + | |
57 | + | |
58 | +export default { | |
59 | + data() { | |
60 | + return { | |
61 | + thesised: [], | |
62 | + mdiPlusCircleOutline: mdiPlusCircleOutline, | |
63 | + mdiMagnify: mdiMagnify, | |
64 | + mdiWindowClose: mdiWindowClose, | |
65 | + } | |
66 | + }, | |
67 | + methods: { | |
68 | + // 논문실적 버튼 추가 | |
69 | + addThesis() { | |
70 | + // 고유 ID로 현재 시간의 타임스탬프를 사용 | |
71 | + const uniqueId = Date.now(); | |
72 | + this.thesised.push({ | |
73 | + id: uniqueId, // 고유 ID 추가 | |
74 | + | |
75 | + }); | |
76 | + }, | |
77 | + removeThesis(thesisId) { | |
78 | + // ID를 기준으로 교육 정보 객체를 찾아서 삭제 | |
79 | + const index = this.thesised.findIndex(thesis => thesis.id === thesisId); | |
80 | + if (index !== -1) { | |
81 | + this.thesised.splice(index, 1); | |
82 | + } | |
83 | + }, | |
84 | + // | |
85 | + goToPage(page) { | |
86 | + this.$router.push({ name: page }); | |
87 | + }, | |
88 | + }, | |
89 | + watch: { | |
90 | + | |
91 | + }, | |
92 | + computed: { | |
93 | + | |
94 | + }, | |
95 | + components: { | |
96 | + SvgIcon | |
97 | + }, | |
98 | + mounted() { | |
99 | + console.log('Main2 mounted'); | |
100 | + } | |
101 | +} | |
102 | +</script>(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/teacher/VocaList.vue
+++ client/views/pages/teacher/VocaList.vue
... | ... | @@ -2,9 +2,15 @@ |
2 | 2 |
<div class="title-box flex justify-between mb40"> |
3 | 3 |
<p class="title">단어장</p> |
4 | 4 |
<select name="" id=""> |
5 |
- <option value="UNIT_000000000000001">1단원</option> |
|
5 |
+ <option value="UNIT_000000000000001">A교재</option> |
|
6 | 6 |
</select> |
7 | 7 |
</div> |
8 |
+ <label for="" class="title2">단원</label> |
|
9 |
+ <div class="unit-pagination flex mt10 mb20" style="gap: 10px;"> |
|
10 |
+ <button class="selected-btn">1</button> |
|
11 |
+ <button>2</button> |
|
12 |
+ <button>3</button> |
|
13 |
+ </div> |
|
8 | 14 |
<div class="search-wrap flex justify-between mb20 align-center"> |
9 | 15 |
<div class="title2 gray">?단원 전체 목록</div> |
10 | 16 |
<div> |
... | ... | @@ -28,7 +34,7 @@ |
28 | 34 |
<td>등록일</td> |
29 | 35 |
</thead> |
30 | 36 |
<tbody> |
31 |
- <tr v-for="(wordBook, index) in dataList" :key="wordBook.wdBookId" @click="goToViewPage('noticeDetail')"> |
|
37 |
+ <tr v-for="(wordBook, index) in dataList" :key="wordBook.wdBookId" @click="goToViewPage('VocaDetail')"> |
|
32 | 38 |
<td>{{ createNo(index) }}</td> |
33 | 39 |
<td>{{ wordBook.textTtl }}</td> |
34 | 40 |
<td>{{ wordBook.wordsPreview }}</td> |
... | ... | @@ -49,7 +55,7 @@ |
49 | 55 |
</button> |
50 | 56 |
</article> |
51 | 57 |
<div class="flex justify-end "> |
52 |
- <button type="button" title="등록" class="new-btn" @click="goToPage('noticeInsert')"> |
|
58 |
+ <button type="button" title="등록" class="new-btn" @click="goToPage('VocaInsert')"> |
|
53 | 59 |
등록 |
54 | 60 |
</button> |
55 | 61 |
</div> |
--- client/views/pages/teacher/noticeDetail.vue
+++ client/views/pages/teacher/noticeDetail.vue
... | ... | @@ -1,78 +1,224 @@ |
1 | 1 |
<template> |
2 |
- <div class="title-box flex justify-between mb40"> |
|
3 |
- <p class="title">공지 등록</p> |
|
2 |
+ <div class="title-box flex justify-between mb40"> |
|
3 |
+ <p class="title">{{ category }}</p> |
|
4 |
+ </div> |
|
5 |
+ <div class="board-wrap"> |
|
6 |
+ <div class="flex align-center"> |
|
7 |
+ <label for="" class="title2">{{ title }}</label> |
|
4 | 8 |
</div> |
5 |
- <div class="board-wrap"> |
|
6 |
- <div class="flex align-center"> |
|
7 |
- <label for="" class="title2">제목</label> |
|
8 |
- <input type="text" class="data-wrap"> |
|
9 |
- </div> |
|
10 |
- <hr> |
|
11 |
- <textarea name="" id=""></textarea> |
|
12 |
- <hr> |
|
13 |
- <div class="flex align-center"> |
|
14 |
- <label for="" class="title2">첨부파일</label> |
|
15 |
- <input type="file" ref="fileInput" @change="handleFileUpload" /> |
|
16 |
- </div> |
|
17 |
- <hr> |
|
18 |
- <div class="flex justify-between"> |
|
19 |
- <button type="button" class="flex align-center"> |
|
20 |
- <svg-icon type="mdi" :path="mdilChevronLeft" ></svg-icon> |
|
21 |
- <p> 이전글</p> |
|
22 |
- </button> |
|
23 |
- <button type="button" class="flex align-center"><p>다음글</p> |
|
24 |
- <svg-icon type="mdi" :path="mdilChevronRight" ></svg-icon> |
|
25 |
- |
|
26 |
- </button> |
|
27 |
- |
|
28 |
- |
|
29 |
- </div> |
|
30 |
- </div> |
|
31 |
- <div class="flex justify-between mt50"> |
|
32 |
- <button type="button" title="글쓰기" class="new-btn" @click="goToPage('Board')"> |
|
33 |
- 목록 |
|
34 |
- </button> |
|
35 |
- <div class="flex"> |
|
36 |
- <button type="button" title="글쓰기" class="new-btn mr10" > |
|
37 |
- 수정 |
|
38 |
- </button> |
|
39 |
- <button type="button" title="글쓰기" class="new-btn" > |
|
40 |
- 삭제 |
|
41 |
- </button> |
|
42 |
- </div> |
|
43 |
- </div> |
|
9 |
+ <hr /> |
|
10 |
+ <textarea readonly name="" id="">{{ content }}</textarea> |
|
11 |
+ <hr /> |
|
12 |
+ <div class="flex align-center"> |
|
13 |
+ <label for="" class="title2">첨부파일</label> |
|
14 |
+ <label for="" class="title2" v-if="file">{{ file.fileNm }}</label> |
|
15 |
+ </div> |
|
16 |
+ <hr /> |
|
17 |
+ <div class="flex justify-between"> |
|
18 |
+ <button type="button" class="flex align-center" @click="prevBoard()"> |
|
19 |
+ <svg-icon type="mdi" :path="mdilChevronLeft"></svg-icon> |
|
20 |
+ <p>이전글</p> |
|
21 |
+ </button> |
|
22 |
+ <button type="button" class="flex align-center" @click="nextBoard()"> |
|
23 |
+ <p>다음글</p> |
|
24 |
+ <svg-icon type="mdi" :path="mdilChevronRight"></svg-icon> |
|
25 |
+ </button> |
|
26 |
+ </div> |
|
27 |
+ </div> |
|
28 |
+ <div class="flex justify-between mt50"> |
|
29 |
+ <button |
|
30 |
+ type="button" |
|
31 |
+ title="글쓰기" |
|
32 |
+ class="new-btn" |
|
33 |
+ @click="goToPage('Board')" |
|
34 |
+ > |
|
35 |
+ 목록 |
|
36 |
+ </button> |
|
37 |
+ <div class="flex"> |
|
38 |
+ <button |
|
39 |
+ type="button" |
|
40 |
+ title="글쓰기" |
|
41 |
+ class="new-btn mr10" |
|
42 |
+ @click="goToPage('noticeInsert')" |
|
43 |
+ > |
|
44 |
+ 수정 |
|
45 |
+ </button> |
|
46 |
+ <button |
|
47 |
+ type="button" |
|
48 |
+ title="글쓰기" |
|
49 |
+ class="new-btn" |
|
50 |
+ @click="[deleteBoard(), goToPage('Board')]" |
|
51 |
+ > |
|
52 |
+ 삭제 |
|
53 |
+ </button> |
|
54 |
+ </div> |
|
55 |
+ </div> |
|
44 | 56 |
</template> |
45 | 57 |
|
46 | 58 |
<script> |
47 |
-import SvgIcon from '@jamescoyle/vue-icon'; |
|
48 |
-import { mdiMagnify } from '@mdi/js'; |
|
49 |
-import { mdilChevronRight,mdilChevronLeft } from '@mdi/light-js'; |
|
50 |
- |
|
59 |
+import SvgIcon from "@jamescoyle/vue-icon"; |
|
60 |
+import { mdiMagnify } from "@mdi/js"; |
|
61 |
+import { mdilChevronRight, mdilChevronLeft } from "@mdi/light-js"; |
|
62 |
+import axios from "axios"; |
|
51 | 63 |
|
52 | 64 |
export default { |
53 |
- data () { |
|
54 |
- return { |
|
55 |
- mdiMagnify: mdiMagnify, |
|
56 |
- mdilChevronRight: mdilChevronRight , |
|
57 |
- mdilChevronLeft:mdilChevronLeft, |
|
58 |
- } |
|
59 |
- }, |
|
60 |
- methods: { |
|
61 |
- goToPage(page) { |
|
62 |
- this.$router.push({ name: page }); |
|
63 |
- }, |
|
64 |
- }, |
|
65 |
- watch: { |
|
65 |
+ data() { |
|
66 |
+ return { |
|
67 |
+ mdiMagnify: mdiMagnify, |
|
68 |
+ mdilChevronRight: mdilChevronRight, |
|
69 |
+ mdilChevronLeft: mdilChevronLeft, |
|
66 | 70 |
|
71 |
+ dataList: null, |
|
72 |
+ sclsId: "", |
|
73 |
+ bbsId: "", |
|
74 |
+ |
|
75 |
+ title: "", |
|
76 |
+ content: "", |
|
77 |
+ category: "", |
|
78 |
+ file: "", |
|
79 |
+ time: "", |
|
80 |
+ user: "", |
|
81 |
+ }; |
|
82 |
+ }, |
|
83 |
+ methods: { |
|
84 |
+ goToPage(page) { |
|
85 |
+ this.$router.push({ name: page }); |
|
67 | 86 |
}, |
68 |
- computed: { |
|
69 |
- |
|
87 |
+ |
|
88 |
+ findBoard() { |
|
89 |
+ const vm = this; |
|
90 |
+ vm.bbsId = JSON.parse(sessionStorage.getItem("bbsId")); |
|
91 |
+ console.log(vm.bbsId); |
|
92 |
+ axios({ |
|
93 |
+ url: "/board/find.json", |
|
94 |
+ method: "post", |
|
95 |
+ headers: { |
|
96 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
97 |
+ }, |
|
98 |
+ data: { |
|
99 |
+ bbsId: vm.bbsId, |
|
100 |
+ }, |
|
101 |
+ }) |
|
102 |
+ .then(function (res) { |
|
103 |
+ console.log("boardData - response : ", res.data); |
|
104 |
+ vm.dataList = res.data.result[0].boardClass[0].board[0]; |
|
105 |
+ vm.title = vm.dataList.bbsTtl; |
|
106 |
+ vm.content = vm.dataList.bbsCnt; |
|
107 |
+ vm.category = vm.dataList.bbsCls; |
|
108 |
+ vm.time = vm.dataList.bbsTm; |
|
109 |
+ vm.findFile(); |
|
110 |
+ }) |
|
111 |
+ .catch(function (error) { |
|
112 |
+ console.log("boardData - error : ", error); |
|
113 |
+ }); |
|
70 | 114 |
}, |
71 |
- components:{ |
|
72 |
- SvgIcon |
|
115 |
+ |
|
116 |
+ findFile() { |
|
117 |
+ const vm = this; |
|
118 |
+ axios({ |
|
119 |
+ url: "/file/find.json", |
|
120 |
+ method: "post", |
|
121 |
+ headers: { |
|
122 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
123 |
+ }, |
|
124 |
+ data: { |
|
125 |
+ file_mng_id: vm.dataList.fileMngId, |
|
126 |
+ }, |
|
127 |
+ }) |
|
128 |
+ .then(function (res) { |
|
129 |
+ console.log("fileInfo - response : ", res.data.list[0]); |
|
130 |
+ vm.file = res.data.list[0]; |
|
131 |
+ sessionStorage.setItem("file", JSON.stringify(vm.file)); |
|
132 |
+ }) |
|
133 |
+ .catch(function (error) { |
|
134 |
+ console.log("result - error : ", error); |
|
135 |
+ }); |
|
73 | 136 |
}, |
74 |
- mounted() { |
|
75 |
- console.log('Main2 mounted'); |
|
76 |
- } |
|
77 |
-} |
|
78 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
137 |
+ |
|
138 |
+ prevBoard() { |
|
139 |
+ const vm = this; |
|
140 |
+ axios({ |
|
141 |
+ url: "/board/prevBoard.json", |
|
142 |
+ method: "post", |
|
143 |
+ headers: { |
|
144 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
145 |
+ }, |
|
146 |
+ data: { |
|
147 |
+ sclsId: vm.dataList.sclsId, |
|
148 |
+ bbsId: vm.dataList.bbsId, |
|
149 |
+ }, |
|
150 |
+ }) |
|
151 |
+ .then(function (res) { |
|
152 |
+ console.log("dataList - response : ", res.data); |
|
153 |
+ vm.dataList = res.data[0].boardClass[0].board[0]; |
|
154 |
+ vm.title = vm.dataList.bbsTtl; |
|
155 |
+ vm.content = vm.dataList.bbsCnt; |
|
156 |
+ vm.category = vm.dataList.bbsCls; |
|
157 |
+ vm.time = vm.dataList.bbsTm; |
|
158 |
+ vm.findFile(); |
|
159 |
+ }) |
|
160 |
+ .catch(function (error) { |
|
161 |
+ console.log("result - error : ", error); |
|
162 |
+ alert("첫번째 글 입니다."); |
|
163 |
+ }); |
|
164 |
+ }, |
|
165 |
+ |
|
166 |
+ nextBoard() { |
|
167 |
+ const vm = this; |
|
168 |
+ axios({ |
|
169 |
+ url: "/board/nextBoard.json", |
|
170 |
+ method: "post", |
|
171 |
+ headers: { |
|
172 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
173 |
+ }, |
|
174 |
+ data: { |
|
175 |
+ sclsId: vm.dataList.sclsId, |
|
176 |
+ bbsId: vm.dataList.bbsId, |
|
177 |
+ }, |
|
178 |
+ }) |
|
179 |
+ .then(function (res) { |
|
180 |
+ console.log("dataList - response : ", res.data); |
|
181 |
+ vm.dataList = res.data[0].boardClass[0].board[0]; |
|
182 |
+ vm.title = vm.dataList.bbsTtl; |
|
183 |
+ vm.content = vm.dataList.bbsCnt; |
|
184 |
+ vm.category = vm.dataList.bbsCls; |
|
185 |
+ vm.time = vm.dataList.bbsTm; |
|
186 |
+ vm.findFile(); |
|
187 |
+ }) |
|
188 |
+ .catch(function (error) { |
|
189 |
+ console.log("result - error : ", error); |
|
190 |
+ alert("가장 최신 글 입니다."); |
|
191 |
+ }); |
|
192 |
+ }, |
|
193 |
+ deleteBoard() { |
|
194 |
+ const vm = this; |
|
195 |
+ axios({ |
|
196 |
+ url: "/board/delete.json", |
|
197 |
+ method: "post", |
|
198 |
+ headers: { |
|
199 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
200 |
+ }, |
|
201 |
+ data: { |
|
202 |
+ bbsId: vm.dataList.bbsId, |
|
203 |
+ }, |
|
204 |
+ }) |
|
205 |
+ .then(function (res) { |
|
206 |
+ console.log("delete - response : ", res.data); |
|
207 |
+ alert("삭제 되었습니다."); |
|
208 |
+ }) |
|
209 |
+ .catch(function (error) { |
|
210 |
+ console.log("rssult - error : ", error); |
|
211 |
+ }); |
|
212 |
+ }, |
|
213 |
+ }, |
|
214 |
+ watch: {}, |
|
215 |
+ computed: {}, |
|
216 |
+ components: { |
|
217 |
+ SvgIcon, |
|
218 |
+ }, |
|
219 |
+ mounted() { |
|
220 |
+ console.log("Main2 mounted"); |
|
221 |
+ this.findBoard(); |
|
222 |
+ }, |
|
223 |
+}; |
|
224 |
+</script> |
--- client/views/pages/teacher/noticeInsert.vue
+++ client/views/pages/teacher/noticeInsert.vue
... | ... | @@ -1,9 +1,9 @@ |
1 | 1 |
<template> |
2 | 2 |
<div class="title-box flex justify-between mb40"> |
3 |
- <p class="title">공지 등록</p> |
|
3 |
+ <p class="title">{{ titleLabel }}</p> |
|
4 | 4 |
</div> |
5 | 5 |
<div class="board-wrap"> |
6 |
- <form @submit.prevent="handleSubmit"> |
|
6 |
+ <form @submit.prevent="handleButtonAction"> |
|
7 | 7 |
<div class="flex align-center"> |
8 | 8 |
<label for="title" class="title2">제목</label> |
9 | 9 |
<input type="text" id="title" class="data-wrap" v-model="title" /> |
... | ... | @@ -13,13 +13,21 @@ |
13 | 13 |
<hr /> |
14 | 14 |
<div class="flex align-center"> |
15 | 15 |
<label for="file" class="title2">첨부파일</label> |
16 |
- <input type="file" ref="fileInput" @change="handleFileUpload" /> |
|
16 |
+ <label for="file" class="title2"> {{ file.fileNm }}</label> |
|
17 |
+ <input |
|
18 |
+ type="file" |
|
19 |
+ ref="fileInput" |
|
20 |
+ @change="handleFileUpload" |
|
21 |
+ multiple |
|
22 |
+ /> |
|
17 | 23 |
</div> |
18 | 24 |
<div class="flex justify-between mt50"> |
19 | 25 |
<button title="글쓰기" class="new-btn" @click="goToPage('Board')"> |
20 | 26 |
목록 |
21 | 27 |
</button> |
22 |
- <button title="글쓰기" class="new-btn">등록</button> |
|
28 |
+ <button title="글쓰기" class="new-btn"> |
|
29 |
+ {{ buttonLabel }} |
|
30 |
+ </button> |
|
23 | 31 |
</div> |
24 | 32 |
</form> |
25 | 33 |
</div> |
... | ... | @@ -38,8 +46,16 @@ |
38 | 46 |
title: "", |
39 | 47 |
content: "", |
40 | 48 |
category: "Notice", |
49 |
+ file: "", |
|
41 | 50 |
sclsId: "", |
42 |
- selectedFile: null, |
|
51 |
+ bbsId: "", |
|
52 |
+ fileMngId: null, |
|
53 |
+ |
|
54 |
+ selectedFiles: [], |
|
55 |
+ dataList: "", |
|
56 |
+ |
|
57 |
+ // 데이터 편집 상태 (true = 수정, false = 등록) |
|
58 |
+ isEditMode: false, |
|
43 | 59 |
}; |
44 | 60 |
}, |
45 | 61 |
methods: { |
... | ... | @@ -48,26 +64,113 @@ |
48 | 64 |
}, |
49 | 65 |
|
50 | 66 |
handleFileUpload(e) { |
51 |
- this.selectedFile = e.target.files[0]; |
|
52 |
- console.log(this.selectedFile); |
|
67 |
+ this.selectedFiles = e.target.files; |
|
53 | 68 |
}, |
54 | 69 |
|
55 | 70 |
created() { |
56 | 71 |
const vm = this; |
57 | 72 |
const sclsId = JSON.parse(sessionStorage.getItem("sclsId")); |
73 |
+ const bbsId = JSON.parse(sessionStorage.getItem("bbsId")); |
|
74 |
+ const file = JSON.parse(sessionStorage.getItem("file")); |
|
58 | 75 |
|
59 | 76 |
if (sclsId) { |
60 | 77 |
vm.sclsId = sclsId; |
78 |
+ if (bbsId && file) { |
|
79 |
+ vm.bbsId = bbsId; |
|
80 |
+ vm.file = file; |
|
81 |
+ vm.fileMngId = file.fileMngId; |
|
82 |
+ vm.isEditMode = true; |
|
83 |
+ vm.findBoard(); |
|
84 |
+ } else { |
|
85 |
+ vm.isEditMode = false; |
|
86 |
+ } |
|
61 | 87 |
} |
62 |
- console.log(sclsId); |
|
63 | 88 |
}, |
64 | 89 |
|
65 |
- async handleSubmit() { |
|
90 |
+ // 게시글 상세 조회 |
|
91 |
+ findBoard() { |
|
92 |
+ const vm = this; |
|
93 |
+ vm.bbsId = JSON.parse(sessionStorage.getItem("bbsId")); |
|
94 |
+ console.log(vm.bbsId); |
|
95 |
+ axios({ |
|
96 |
+ url: "/board/find.json", |
|
97 |
+ method: "post", |
|
98 |
+ headers: { |
|
99 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
100 |
+ }, |
|
101 |
+ data: { |
|
102 |
+ bbsId: vm.bbsId, |
|
103 |
+ }, |
|
104 |
+ }) |
|
105 |
+ .then(function (res) { |
|
106 |
+ console.log("boardData - response : ", res.data); |
|
107 |
+ vm.dataList = res.data.result[0].boardClass[0].board[0]; |
|
108 |
+ vm.title = vm.dataList.bbsTtl; |
|
109 |
+ vm.content = vm.dataList.bbsCnt; |
|
110 |
+ vm.category = vm.dataList.bbsCls; |
|
111 |
+ vm.time = vm.dataList.bbsTm; |
|
112 |
+ }) |
|
113 |
+ .catch(function (error) { |
|
114 |
+ console.log("boardData - error : ", error); |
|
115 |
+ }); |
|
116 |
+ }, |
|
117 |
+ |
|
118 |
+ // 게시글 등록 |
|
119 |
+ async dataInsert() { |
|
66 | 120 |
const vm = this; |
67 | 121 |
try { |
68 | 122 |
// 파일 업로드 |
123 |
+ if (this.selectedFiles && this.selectedFiles.length > 0) { |
|
124 |
+ // 파일 업로드 |
|
125 |
+ const formData = new FormData(); |
|
126 |
+ for (let i = 0; i < this.selectedFiles.length; i++) { |
|
127 |
+ formData.append("files", this.selectedFiles[i]); |
|
128 |
+ } |
|
129 |
+ |
|
130 |
+ const fileUploadResponse = await axios.post( |
|
131 |
+ "/file/upload.json", |
|
132 |
+ formData, |
|
133 |
+ { |
|
134 |
+ headers: { |
|
135 |
+ "Content-Type": "multipart/form-data", |
|
136 |
+ }, |
|
137 |
+ } |
|
138 |
+ ); |
|
139 |
+ |
|
140 |
+ // 업로드 후 파일 매니지 아이디 호출 |
|
141 |
+ fileMngId = fileUploadResponse.data.fileMngId; |
|
142 |
+ } |
|
143 |
+ |
|
144 |
+ // 게시물 등록 |
|
145 |
+ const newData = { |
|
146 |
+ bbsTtl: vm.title, |
|
147 |
+ bbsCls: vm.category, |
|
148 |
+ bbsCnt: vm.content, |
|
149 |
+ fileMngId: vm.fileMngId, |
|
150 |
+ sclsId: vm.sclsId, |
|
151 |
+ }; |
|
152 |
+ |
|
153 |
+ await axios.post("/board/insert.json", newData); |
|
154 |
+ |
|
155 |
+ alert("게시물 등록 성공"); |
|
156 |
+ vm.$router.push({ name: "Board" }); |
|
157 |
+ } catch (error) { |
|
158 |
+ console.error("게시물 등록 실패 ", error); |
|
159 |
+ alert("게시물 등록 실패"); |
|
160 |
+ } |
|
161 |
+ }, |
|
162 |
+ |
|
163 |
+ // 게시글 수정 |
|
164 |
+ async boardUpdate() { |
|
165 |
+ const vm = this; |
|
166 |
+ |
|
167 |
+ // 파일 업로드 |
|
168 |
+ if (this.selectedFiles && this.selectedFiles.length > 0) { |
|
169 |
+ // 파일 업로드 |
|
69 | 170 |
const formData = new FormData(); |
70 |
- formData.append("files", this.selectedFile); |
|
171 |
+ for (let i = 0; i < this.selectedFiles.length; i++) { |
|
172 |
+ formData.append("files", this.selectedFiles[i]); |
|
173 |
+ } |
|
71 | 174 |
|
72 | 175 |
const fileUploadResponse = await axios.post( |
73 | 176 |
"/file/upload.json", |
... | ... | @@ -80,28 +183,50 @@ |
80 | 183 |
); |
81 | 184 |
|
82 | 185 |
// 업로드 후 파일 매니지 아이디 호출 |
83 |
- const fileMngId = fileUploadResponse.data.fileMngId; |
|
186 |
+ fileMngId = fileUploadResponse.data.fileMngId; |
|
187 |
+ } |
|
84 | 188 |
|
85 |
- // 게시물 등록 |
|
86 |
- const newData = { |
|
87 |
- bbsTtl: vm.title, |
|
88 |
- bbsCls: vm.category, |
|
89 |
- bbsCnt: vm.content, |
|
90 |
- fileMngId: fileMngId, |
|
91 |
- sclsId: vm.sclsId, |
|
92 |
- }; |
|
189 |
+ const newData = { |
|
190 |
+ bbsTtl: vm.title, |
|
191 |
+ bbsCls: vm.category, |
|
192 |
+ bbsCnt: vm.content, |
|
193 |
+ fileMngId: vm.fileMngId, |
|
194 |
+ bbsId: vm.bbsId, |
|
195 |
+ }; |
|
196 |
+ await axios({ |
|
197 |
+ url: "/board/update.json", |
|
198 |
+ method: "post", |
|
199 |
+ headers: { |
|
200 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
201 |
+ }, |
|
202 |
+ data: newData, |
|
203 |
+ }) |
|
204 |
+ .then(function (res) { |
|
205 |
+ console.log("dataUpdate - response : ", res.data); |
|
206 |
+ }) |
|
207 |
+ .catch(function (error) { |
|
208 |
+ console.log("result - error : ", error); |
|
209 |
+ }); |
|
210 |
+ }, |
|
93 | 211 |
|
94 |
- await axios.post("/board/insert.json", newData); |
|
95 |
- |
|
96 |
- alert("게시물 등록 성공"); |
|
97 |
- } catch (error) { |
|
98 |
- console.error("게시물 등록 실패 ", error); |
|
99 |
- alert("게시물 등록 실패"); |
|
212 |
+ handleButtonAction() { |
|
213 |
+ if (this.isEditMode) { |
|
214 |
+ this.boardUpdate(); |
|
215 |
+ } else { |
|
216 |
+ this.dataInsert(); |
|
100 | 217 |
} |
101 | 218 |
}, |
102 | 219 |
}, |
103 | 220 |
watch: {}, |
104 |
- computed: {}, |
|
221 |
+ computed: { |
|
222 |
+ titleLabel() { |
|
223 |
+ return this.isEditMode ? "수정" : "공지 등록"; |
|
224 |
+ }, |
|
225 |
+ |
|
226 |
+ buttonLabel() { |
|
227 |
+ return this.isEditMode ? "수정" : "등록"; |
|
228 |
+ }, |
|
229 |
+ }, |
|
105 | 230 |
components: { |
106 | 231 |
SvgIcon, |
107 | 232 |
}, |
--- client/views/pages/teacher/textbook.vue
+++ client/views/pages/teacher/textbook.vue
... | ... | @@ -4,98 +4,163 @@ |
4 | 4 |
<select name="" id=""> |
5 | 5 |
<option value="">A반</option> |
6 | 6 |
</select> |
7 |
- </div> |
|
8 |
- <div class="content-t"> |
|
9 |
- <div class=" flex " style="gap: 50px;"> |
|
10 |
- <div class="textbook"> |
|
11 |
- <div class="box " style="gap: 10px;" @click="goToPage('TextBookDetail')"> |
|
12 |
- </div> |
|
13 |
- <div class="text "> |
|
14 |
- <p class="title1" style="color: #fff;">A 교재</p> |
|
15 |
- <div class="btnGroup mt15 flex align-center justify-end" style="gap: 10px;"> |
|
16 |
- <button>수정</button><p>|</p> |
|
17 |
- <button @click="showConfirm('delete')">삭제</button> |
|
18 |
- </div> |
|
19 |
- </div> |
|
7 |
+ </div> |
|
8 |
+ <div class="content-t"> |
|
9 |
+ <div class="flex" style="gap: 2.5%;" :style="{flexWrap: 'wrap'}"> |
|
10 |
+ <div class="textbook" v-for="textbookItem in textbookList" :key="textbookItem.book_id" style="width: 22.5%; margin-bottom: 30px;"> |
|
11 |
+ <div class="box" style="gap: 10px;" @click="goToPage('TextBookDetail', textbookItem.book_id)"> |
|
20 | 12 |
</div> |
21 |
- |
|
22 |
- <div class="textbook-add"> |
|
23 |
- <button @click="buttonSearch"><img src="../../../resources/img/btn32_98t_normal.png" alt=""></button> |
|
24 |
- |
|
13 |
+ <div class="text"> |
|
14 |
+ <p class="title1" style="color: #fff;">{{ textbookItem.book_nm }}</p> |
|
15 |
+ <div class="btnGroup mt15 flex align-center justify-end" style="gap: 10px;"> |
|
16 |
+ <button @click="editBook(textbookItem)">수정</button> |
|
17 |
+ <p>|</p> |
|
18 |
+ <button @click="deleteBook(textbookItem.book_id)">삭제</button> |
|
19 |
+ </div> |
|
25 | 20 |
</div> |
26 | 21 |
</div> |
27 |
- </div> |
|
28 |
- <div v-show="searchOpen" class="popup-wrap"> |
|
29 |
- <div class="popup-box "> |
|
22 |
+ |
|
23 |
+ <div class="textbook-add" style="width: 22.5%; margin-bottom: 30px;"> |
|
24 |
+ <button @click="buttonSearch"> |
|
25 |
+ <img src="../../../resources/img/btn32_98t_normal.png" alt=""> |
|
26 |
+ </button> |
|
27 |
+ </div> |
|
28 |
+ |
|
29 |
+ <div v-show="searchOpen" class="popup-wrap"> |
|
30 |
+ <div class="popup-box"> |
|
30 | 31 |
<div class="flex justify-between mb30"> |
31 | 32 |
<p class="popup-title">교재 이름</p> |
32 | 33 |
<button type="button" class="popup-close-btn" @click="closeBtn"> |
33 | 34 |
<svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon> |
34 |
- |
|
35 | 35 |
</button> |
36 | 36 |
</div> |
37 | 37 |
<div class="search-wrap mb30"> |
38 |
- <input type="text" class="data-wrap" placeholder=""> |
|
39 |
- <button type="button" title="교재 검색"> |
|
38 |
+ <input type="text" class="data-wrap" v-model="newBookName" placeholder="교재 이름을 입력하세요"> |
|
39 |
+ <button type="button" title="교재 검색" @click="insertBook"> |
|
40 | 40 |
<img src="../../../resources/img/look_t.png" alt=""> |
41 | 41 |
</button> |
42 | 42 |
</div> |
43 |
- <div class="flex justify-center "> |
|
44 |
- <button type="button" title="글쓰기" class="new-btn mr10"> |
|
43 |
+ <div class="flex justify-center"> |
|
44 |
+ <button type="button" title="취소" class="new-btn mr10" @click="closeBtn"> |
|
45 | 45 |
취소 |
46 | 46 |
</button> |
47 |
- <button type="button" title="글쓰기" class="new-btn"> |
|
48 |
- 생성 |
|
47 |
+ <button type="button" title="생성" class="new-btn" @click="editMode ? updateBook() : insertBook()"> |
|
48 |
+ {{ editMode ? '수정' : '생성' }} |
|
49 | 49 |
</button> |
50 | 50 |
</div> |
51 | 51 |
</div> |
52 | 52 |
</div> |
53 |
+ </div> |
|
54 |
+ </div> |
|
53 | 55 |
</template> |
56 |
+ |
|
57 |
+ |
|
54 | 58 |
|
55 | 59 |
<script> |
56 | 60 |
import SvgIcon from '@jamescoyle/vue-icon'; |
57 |
-import { mdiMagnify, mdiWindowClose } from '@mdi/js'; |
|
61 |
+import { mdiWindowClose } from '@mdi/js'; |
|
62 |
+import axios from 'axios'; |
|
58 | 63 |
|
59 | 64 |
export default { |
60 |
- data () { |
|
65 |
+ data() { |
|
61 | 66 |
return { |
62 | 67 |
mdiWindowClose: mdiWindowClose, |
63 | 68 |
showModal: false, |
64 | 69 |
searchOpen: false, |
70 |
+ textbookList: [], |
|
71 |
+ newBookName: '', |
|
72 |
+ editMode: false, |
|
73 |
+ editBookId: null, |
|
65 | 74 |
} |
66 | 75 |
}, |
67 | 76 |
methods: { |
68 |
- goToPage(page) { |
|
69 |
- this.$router.push({ name: page }); |
|
70 |
- }, |
|
71 |
- closeModal() { |
|
72 |
- this.showModal = false; |
|
77 |
+ goToPage(page, book_id) { |
|
78 |
+ this.$router.push({ name: page, query: { book_id }}); |
|
73 | 79 |
}, |
74 | 80 |
buttonSearch() { |
75 | 81 |
this.searchOpen = true; |
76 | 82 |
}, |
77 | 83 |
closeBtn() { |
78 | 84 |
this.searchOpen = false; |
79 |
- |
|
85 |
+ this.editMode = false; |
|
86 |
+ this.editBookId = null; |
|
87 |
+ this.newBookName = ''; |
|
80 | 88 |
}, |
81 |
- showConfirm(type) { |
|
82 |
- let message = ''; |
|
83 |
- if (type === 'delete') { |
|
84 |
- message = '삭제하시겠습니까?'; |
|
85 |
- } else if (type === 'reset') { |
|
86 |
- message = '초기화하시겠습니까?'; |
|
87 |
- } else if (type === 'save') { |
|
88 |
- message = '등록하시겠습니까?'; |
|
89 |
- } |
|
90 |
- |
|
91 |
- if (confirm(message)) { |
|
92 |
- this.goBack(); |
|
93 |
- } |
|
89 |
+ editBook(book) { |
|
90 |
+ this.newBookName = book.book_nm; |
|
91 |
+ this.editMode = true; |
|
92 |
+ this.editBookId = book.book_id; |
|
93 |
+ this.searchOpen = true; |
|
94 | 94 |
}, |
95 |
- |
|
96 |
- }, |
|
97 |
- watch: { |
|
98 |
- |
|
95 |
+ bookList() { |
|
96 |
+ axios({ |
|
97 |
+ url: "/book/findAll.json", |
|
98 |
+ method: "post", |
|
99 |
+ headers: { |
|
100 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
101 |
+ } |
|
102 |
+ }) |
|
103 |
+ .then(response => { |
|
104 |
+ this.textbookList = response.data; |
|
105 |
+ }) |
|
106 |
+ .catch(error => { |
|
107 |
+ console.error('Error fetching books:', error); |
|
108 |
+ }); |
|
109 |
+ }, |
|
110 |
+ insertBook() { |
|
111 |
+ const newBook = { |
|
112 |
+ book_nm: this.newBookName |
|
113 |
+ }; |
|
114 |
+ axios.post('/book/insert.json', newBook) |
|
115 |
+ .then(response => { |
|
116 |
+ this.bookList(); |
|
117 |
+ this.closeBtn(); |
|
118 |
+ }) |
|
119 |
+ .catch(error => { |
|
120 |
+ console.error('Error creating book:', error); |
|
121 |
+ }); |
|
122 |
+ }, |
|
123 |
+ updateBook() { |
|
124 |
+ const updatedBook = { |
|
125 |
+ book_id: this.editBookId, |
|
126 |
+ book_nm: this.newBookName |
|
127 |
+ }; |
|
128 |
+ axios({ |
|
129 |
+ url: "/book/update.json", |
|
130 |
+ method: "post", |
|
131 |
+ headers: { |
|
132 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
133 |
+ }, |
|
134 |
+ data: updatedBook, |
|
135 |
+ }) |
|
136 |
+ .then(response => { |
|
137 |
+ this.bookList(); |
|
138 |
+ this.closeBtn(); |
|
139 |
+ }) |
|
140 |
+ .catch(error => { |
|
141 |
+ console.error('Error updating book:', error); |
|
142 |
+ }); |
|
143 |
+ }, |
|
144 |
+ deleteBook(book_id) { |
|
145 |
+ if (confirm('삭제하시겠습니까?')) { |
|
146 |
+ axios({ |
|
147 |
+ url: "/book/delete.json", |
|
148 |
+ method: "post", |
|
149 |
+ headers: { |
|
150 |
+ "Content-Type": "application/json; charset=UTF-8", |
|
151 |
+ }, |
|
152 |
+ data: { |
|
153 |
+ book_id: book_id |
|
154 |
+ }, |
|
155 |
+ }) |
|
156 |
+ .then(response => { |
|
157 |
+ this.bookList(); |
|
158 |
+ }) |
|
159 |
+ .catch(error => { |
|
160 |
+ console.error('Error deleting book:', error); |
|
161 |
+ }); |
|
162 |
+ } |
|
163 |
+ } |
|
99 | 164 |
}, |
100 | 165 |
computed: { |
101 | 166 |
|
... | ... | @@ -105,6 +170,22 @@ |
105 | 170 |
}, |
106 | 171 |
mounted() { |
107 | 172 |
console.log('Main2 mounted'); |
173 |
+ this.bookList(); |
|
108 | 174 |
} |
109 | 175 |
} |
110 |
-</script>(파일 끝에 줄바꿈 문자 없음) |
|
176 |
+</script> |
|
177 |
+ |
|
178 |
+<style> |
|
179 |
+.content-t { |
|
180 |
+ flex-wrap: wrap; |
|
181 |
+ height: 90%; |
|
182 |
+ overflow-y: scroll; |
|
183 |
+} |
|
184 |
+.flex { |
|
185 |
+ display: flex; |
|
186 |
+ flex-wrap: wrap; |
|
187 |
+} |
|
188 |
+.textbook, .textbook-add { |
|
189 |
+ margin-bottom: 30px; |
|
190 |
+} |
|
191 |
+</style>(파일 끝에 줄바꿈 문자 없음) |
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?