jichoi / lms_front star
박민혁 박민혁 2024-08-22
240822 박민혁 로드맵
@89eb4bd636d6cc1e28d3f19f2785bde0f8214681
client/resources/css/style.css
--- client/resources/css/style.css
+++ client/resources/css/style.css
@@ -969,6 +969,7 @@
     height: 100%;
     top: 0;
     left: 0;
+
 }
 
 .popup-box {
@@ -976,8 +977,9 @@
     min-width: 670px;
     /* min-height: 219px; */
     background-color: var(--color-white);
-    top:23%;
-    left: 37%;
+    top:50%;
+    left: 5%;
+    right: 5%;
     transform: translateY(-50%);
     border: 1px solid var(--color-gray);
     border-radius: 1rem;
client/views/pages/teacher/RoadMap.vue
--- client/views/pages/teacher/RoadMap.vue
+++ client/views/pages/teacher/RoadMap.vue
@@ -122,9 +122,9 @@
                                                 <P class="title2 mt10">{{ prblm.prblmExpln }}</P>
                                             </td>
                                             <td><button type="button" title="글쓰기" class="new-btn"
-                                                @click="deleteRoadMap('2', prblm.prblmId)">
-                                                삭제
-                                            </button></td>
+                                                    @click="deleteRoadMap('2', prblm.prblmId)">
+                                                    삭제
+                                                </button></td>
                                         </tr>
                                     </tbody>
                                 </table>
@@ -200,7 +200,7 @@
                                 <table>
                                     <thead>
                                         <tr>
-                                            <td>지문</td>
+                                            <td>단어장</td>
                                             <td></td>
                                         </tr>
                                     </thead>
@@ -319,7 +319,7 @@
                                 <table>
                                     <thead>
                                         <tr>
-                                            <td>지문</td>
+                                            <td>단어장</td>
                                             <td></td>
                                         </tr>
                                     </thead>
@@ -427,8 +427,7 @@
                     </thead>
                     <tbody>
                         <tr v-for="(post, index) in posts" :key="index" class="post">
-                            <td><input type="checkbox" :checked="post.check"
-                                @change="selectText(post)"></td>
+                            <td><input type="checkbox" :checked="post.check" @change="selectText(post)"></td>
                             <td>{{ index + 1 }}</td>
                             <td>{{ post.textTtl.slice(0, 20) }}{{ post.textTtl.length > 20 ? '...' : '' }}</td>
                             <td>{{ post.textCnt.slice(0, 20) }}{{ post.textCnt.length > 20 ? '...' : '' }}</td>
@@ -659,7 +658,7 @@
 
 <script>
 import SvgIcon from '@jamescoyle/vue-icon';
-import { mdiMagnify, mdilArrowRight } from '@mdi/js';
+import { mdiAccountTieHat, mdiMagnify, mdilArrowRight } from '@mdi/js';
 import { mdilArrowDown } from '@mdi/light-js';
 import ProgressBar from '../../component/ProgressBar.vue';
 import axios from 'axios';
@@ -678,11 +677,20 @@
             units: [],
             posts: [],
             RoadMap: [],
+            OrginRoadMap: [],
             problems: [],
             wordBooks: [],
             evals: [],
             selectedBook: "",
             selectedUnit: null,
+
+            wordContentId1: "",
+            wordContentId2: "",
+            wordContentId3: "",
+
+            learningId1: "",
+            learningId2: "",
+            learningId3: "",
 
             currentPage: 1,
             pageSize: 5,
@@ -696,6 +704,10 @@
             searchEvalOpen: false,
 
             selectedPop: 0,
+
+            isFirst: false,
+
+            insertRoadId: ''
         }
     },
     methods: {
@@ -763,7 +775,7 @@
         },
 
         // 로드맵 지정된 것 삭제
-        deleteRoadMap(page, id){
+        deleteRoadMap(page, id) {
             if (page === '2' || page === '3' || page === '6') {
                 this.RoadMap[page] = this.RoadMap[page].filter(prblm => prblm.prblmId !== id);
             } else if (page === '0' || page === '4' || page === '8') {
@@ -772,7 +784,7 @@
                 this.RoadMap[page] = this.RoadMap[page].filter(wordBook => wordBook.wdBookId !== id);
             } else if (page === '7' || page === '10') {
                 this.RoadMap[page] = this.RoadMap[page].filter(evaluation => evaluation.evalId !== id);
-            } 
+            }
         },
 
         fetchBooks() {
@@ -819,7 +831,7 @@
         // 단원을 선택했을 때 호출되는 메서드
         selectUnit(unitId) {
             this.selectedUnit = unitId;
-            //this.fetchData();
+            this.fetchRoadmapData();
         },
 
         // 문제 가져오기
@@ -1073,8 +1085,15 @@
             // 이미 있는 데이터인지 확인
             selectedProblems.forEach(problem => {
                 const exists = this.RoadMap[this.selectedPop].some(existingProblem => existingProblem.prblmId === problem.prblmId);
+
                 if (!exists) {
-                    this.RoadMap[this.selectedPop].push(problem); // 존재하지 않으면 추가
+                    // isFirst가 true일 경우, 기존 learningId를 유지하도록 처리
+                    const learningId = this.isFirst ? (this.RoadMap[this.selectedPop][0]?.learningId || null) : null;
+                    this.RoadMap[this.selectedPop].push({
+                        prblmId: problem.prblmId,
+                        prblmExpln: problem.prblmExpln,
+                        learningId: learningId
+                    });
                 }
             });
             this.closeBtn();
@@ -1083,7 +1102,16 @@
         // 팝업 지문 데이터 가져오기
         insertRoadMap2() {
             const selectedTexts = this.posts.filter(post => post.check);
-            this.RoadMap[this.selectedPop] = selectedTexts;
+            if (selectedTexts.length > 0) {
+                const selectedText = selectedTexts[0];
+                const learningId = this.isFirst ? (this.RoadMap[this.selectedPop][0]?.learningId || null) : null;
+
+                this.RoadMap[this.selectedPop] = [{
+                    textId: selectedText.textId,
+                    textTtl: selectedText.textTtl,
+                    learningId: learningId
+                }];
+            }
             this.closeBtn();
         },
         // 팝업 단어장 데이터 가져오기
@@ -1097,36 +1125,445 @@
             // 이미 있는 데이터인지 확인
             selectedBooks.forEach(wordBook => {
                 const exists = this.RoadMap[this.selectedPop].some(existingBook => existingBook.wdBookId === wordBook.wdBookId);
+
                 if (!exists) {
-                    this.RoadMap[this.selectedPop].push(wordBook); // 존재하지 않으면 추가
+                    const existingItem = this.RoadMap[this.selectedPop][0] || {};
+                    const learningId = this.isFirst ? existingItem.learningId : null;
+
+                    this.RoadMap[this.selectedPop].push({
+                        wdBookId: wordBook.wdBookId,
+                        learningId: learningId,
+                        textTtl: wordBook.textTtl
+                    });
                 }
             });
             this.closeBtn();
         },
-
         // 평가 데이터 가져오기
         insertRoadMap4() {
             const selectedEval = this.evals.filter(evaluation => evaluation.check);
-            this.RoadMap[this.selectedPop] = selectedEval;
+            if (selectedEval.length > 0) {
+                const evalData = selectedEval[0];
+                const learningId = this.isFirst ? (this.RoadMap[this.selectedPop][0]?.learningId || null) : null;
+
+                this.RoadMap[this.selectedPop] = [{
+                    evalId: evalData.evalId,
+                    problemCount: evalData.problemCount,
+                    learningId: learningId
+                }];
+            }
             this.closeBtn();
         },
 
-        // 로드맵 등록하기
-        postRoadMaps(){
-            console.log(this.RoadMap);
+        // 로드맵 정보 가져오기
+        fetchRoadmapData() {
+            axios({
+                url: "/unitLearning/find.json",
+                method: "post",
+                headers: {
+                    "Content-Type": "application/json; charset=UTF-8",
+                },
+                data: {
+                    unit_id: this.selectedUnit,
+                    book_id: this.selectedBook
+                }
+            })
+                .then(response => {
+                    if (response.data.length != 0) {
+                        // RoadMap을 초기화
+                        this.RoadMap = Array.from({ length: 11 }, () => []);
 
+                        // RoadMap을 구성하는 데이터 삽입
+                        response.data.forEach(item => {
+                            const seqIndex = item.seq - 1;
+
+                            if (item.text_id && item.text_ttl) {
+                                this.RoadMap[seqIndex].push({
+                                    learningId: item.learning_id,
+                                    textId: item.text_id,
+                                    textTtl: item.text_ttl
+                                });
+                            }
+
+                            if (item.wd_cnt_id) {
+                                if (seqIndex === 1) {
+                                    this.wordContentId1 = item.wd_cnt_id;
+                                }
+                                if (seqIndex === 5) {
+                                    this.wordContentId2 = item.wd_cnt_id;
+                                }
+                                if (seqIndex === 9) {
+                                    this.wordContentId3 = item.wd_cnt_id;
+                                }
+                                this.RoadMap[seqIndex].push(...item.wordBooks.map(wb => ({
+                                    wdCntId: item.wd_cnt_id,
+                                    learningId: item.learning_id,
+                                    wdBookId: wb.wd_book_id,
+                                    textTtl: wb.text_ttl2
+                                })));
+                            }
+
+                            if (item.prblm_id && item.prblm_id.length > 0) {
+                                item.prblm_id.forEach(prblm => {
+                                    this.RoadMap[seqIndex].push({
+                                        learningId: item.learning_id,
+                                        prblmId: prblm.prblm_id,
+                                        prblmExpln: prblm.prblm_expln
+                                    });
+                                });
+                            }
+
+                            if (item.eval_id) {
+                                this.RoadMap[seqIndex].push({
+                                    learningId: item.learning_id,
+                                    evalId: item.eval_id,
+                                    problemCount: item.problem_count
+                                });
+                            }
+                        });
+                        // 완성된 RoadMap을 OrginRoadMap에 깊은 복사하여 저장
+                        this.isFirst = true;
+                        this.OrginRoadMap = JSON.parse(JSON.stringify(this.RoadMap));
+
+                    } else {
+                        this.RoadMap = [];
+                        this.OrginRoadMap = [];
+                        this.isFirst = false;
+                    }
+                })
+                .catch(error => {
+                    console.error("Error fetching roadmap data:", error);
+                });
+        },
+        // wordcontent 처리하기
+        async postWordContent() {
+
+            const validPositions = [1, 5, 9];
+
+            for (const position of validPositions) {
+                const currentSeq = this.RoadMap[position];
+                const originalSeq = this.OrginRoadMap[position] || [];
+                const insertList = [];
+                const insertExistList = [];
+                const updateList = [];
+                const deleteList = [];
+
+                // 원본 데이터의 wdCntId와 wdBookId를 매핑하여 쉽게 조회할 수 있도록 객체화
+                const originalMap = {};
+                originalSeq.forEach(item => {
+                    originalMap[item.wdCntId] = item.wdBookId;
+                });
+
+                // currentSeq와 originalSeq 비교
+                const isEqual = currentSeq.length === originalSeq.length && currentSeq.every((currentItem, index) => {
+                    const originalItem = originalSeq[index];
+                    return currentItem.wdCntId === originalItem.wdCntId && currentItem.wdBookId === originalItem.wdBookId;
+                });
+
+                // 동일할 경우 아무 작업도 하지 않음
+                if (isEqual) {
+                    console.log(`Position ${position}: currentSeq and originalSeq are identical. No action taken.`);
+                    continue; // 다음 위치로 넘어감
+                }
+                // 삭제할 데이터 찾기
+                originalSeq.forEach(originalItem => {
+                    const { wdCntId, wdBookId } = originalItem;
+                    const currentItemExists = currentSeq.some(item => item.wdCntId === wdCntId);
+
+                    // 현재 시퀀스에 존재하지 않는 경우 삭제 리스트에 추가
+                    if (!currentItemExists) {
+                        deleteList.push({
+                            wordContentId: wdCntId,
+                            wordBookId: wdBookId,
+                        });
+                    }
+                });
+
+                currentSeq.forEach(currentItem => {
+                    const { wdBookId, wdCntId } = currentItem;
+
+                    if (!this.isFirst) {
+                        insertList.push({ wordBookId: wdBookId });
+                    } else {
+                        // 현재 아이템의 wdCntId가 원본에 존재하는지 확인
+                        if (originalMap[wdCntId] !== undefined) {
+                            // 원본에 존재하는 경우
+                            const originalWdBookId = originalMap[wdCntId];
+
+                            if (originalWdBookId !== wdBookId) {
+                                // wdBookId가 변경된 경우 업데이트 리스트에 추가
+                                updateList.push({
+                                    wordContentId: wdCntId,
+                                    wordBookId: originalWdBookId, // 기존 wdBookId
+                                    NewWordBookId: wdBookId, // 새로운 wdBookId
+                                });
+                            }
+                        } else {
+                            // 원본에 존재하지 않는 경우
+                            let cntId = null;
+                            if (position === 1) {
+                                cntId = this.wordContentId1;
+                            } else if (position === 5) {
+                                cntId = this.wordContentId2;
+                            } else if (position === 9) {
+                                cntId = this.wordContentId3;
+                            }
+                            insertExistList.push({ wordBookId: wdBookId, wordContentId: cntId });
+                        }
+                    }
+                });
+
+                // ID 생성 및 삽입 요청
+                if (insertList.length > 0) {
+                    const insertedId = await this.sendInsertRequest(insertList);
+                    currentSeq.forEach(currentItem => {
+                        if (!currentItem.wdCntId) {
+                            if (position === 1) {
+                                this.wordContentId1 = insertedId;
+                            } else if (position === 5) {
+                                this.wordContentId2 = insertedId;
+                            } else if (position === 9) {
+                                this.wordContentId3 = insertedId;
+                            }
+                        }
+                    });
+                }
+
+                // 필요 시에만 추가 요청 보내기
+                const promises = [];
+                if (insertExistList.length > 0) {
+                    promises.push(this.sendInsertExistRequest(insertExistList));
+                }
+                if (updateList.length > 0) {
+                    promises.push(this.sendUpdateRequest(updateList));
+                }
+                if (deleteList.length > 0) {
+                    promises.push(this.sendDeleteRequest(deleteList));
+                }
+
+                // 모든 요청을 병렬로 실행
+                if (promises.length > 0) {
+                    await Promise.all(promises);
+                }
+
+            }
+        },
+
+        // 데이터 삽입 요청 보내기
+        async sendInsertRequest(insertList) {
+            try {
+                const response = await axios.post("/wordContent/insertContent.json", insertList);
+                console.log("Insert response:", response.data);
+                return response.data; // 응답에서 새로 생성된 ID 반환
+            } catch (error) {
+                console.error("Error inserting data:", error);
+                throw error; // 오류 발생 시 재던지기
+            }
+        },
+
+        // 존재하는 데이터 삽입 요청 보내기
+        async sendInsertExistRequest(insertExistList) {
+            try {
+                const response = await axios.post("/wordContent/insertContentExist.json", insertExistList);
+                console.log("Insert Exist response:", response.data);
+            } catch (error) {
+                console.error("Error inserting existing data:", error);
+            }
+        },
+
+        // 데이터 업데이트 요청 보내기
+        async sendUpdateRequest(updateList) {
+            try {
+                const response = await axios.post("/wordContent/updateContent.json", updateList);
+                console.log("Update response:", response.data);
+            } catch (error) {
+                console.error("Error updating data:", error);
+            }
+        },
+
+        // 데이터 삭제 요청 보내기 
+        async sendDeleteRequest(deleteList) {
+            try {
+                const response = await axios.post("/wordContent/deleteContent.json", deleteList);
+                console.log("Delete response:", response.data);
+            } catch (error) {
+                console.error("Error deleting data:", error);
+            }
+        },
+
+        // 로드맵 데이터 사용
+        async postRoadMaps() {
+            console.log("로드맵", this.RoadMap);
+
+            // RoadMap 배열의 각 요소 체크
+            let isEmpty = false;
+
+            this.RoadMap.forEach((item, index) => {
+                if (!item) {
+                    isEmpty = true;
+                }
+            });
+
+            // 배열이 비어있으면 함수 종료
+            if (isEmpty) {
+                alert(`학습 로드맵에 비어있는 데이터가 존재합니다.`);
+                return;
+            }
+
+            // 먼저 워드 콘텐츠 등록
+            await this.postWordContent();;
+
+            if (this.isFirst) {
+                this.updateRoadData();
+            } else {
+                this.insertRoadData();
+            }
+
+
+        },
+
+        // 로드맵 등록하기
+        insertRoadData() {
+            const unitLearningList = this.RoadMap.map((item, index) => {
+                // item이 배열인 경우 첫 번째 요소를 가져옵니다.
+                let firstItem = item.length > 0 ? item[0] : {};
+
+                // RoadMap의 인덱스에 따라 wordContentId 설정
+                let wd_cnt_id;
+                if (index === 1) {
+                    wd_cnt_id = this.wordContentId1;
+                    firstItem.textId = null;
+                } else if (index === 5) {
+                    wd_cnt_id = this.wordContentId2;
+                    firstItem.textId = null;
+                } else if (index === 9) {
+                    wd_cnt_id = this.wordContentId3;
+                    firstItem.textId = null;
+                } else {
+                    wd_cnt_id = null; // 다른 인덱스에 대해선 null 설정
+                }
+
+                return {
+                    unit_id: this.selectedUnit,
+                    wd_cnt_id: wd_cnt_id, // wordContentId 
+                    text_id: firstItem.textId || null, // 텍스트 ID
+                    eval_id: firstItem.evalId || null, // 평가 ID
+                    seq: index + 1 // seq는 1부터 시작
+                };
+            });
+
+            axios.post("/unitLearning/insert.json", unitLearningList)
+                .then(response => {
+                    console.log(`Insert successful:`, response.data);
+                    if (response.data) {
+                        const learningIds = response.data;
+                        learningIds.forEach(item => {
+                            if (item.seq === 3) {
+                                this.learningId1 = item.learning_id;
+                            } else if (item.seq === 4) {
+                                this.learningId2 = item.learning_id;
+                            } else if (item.seq === 7) {
+                                this.learningId3 = item.learning_id;
+                            }
+                        });
+                        this.postPrblmBook();
+                    }
+
+                })
+                .catch(error => {
+                    console.error(`Error during insert`, error);
+                });
+        },
+
+        // 로드맵 업데이트하기
+        updateRoadData() {
+            const unitLearningList = this.RoadMap.map((item, index) => {
+                // item이 배열인 경우 첫 번째 요소를 가져옵니다.
+                let firstItem = item.length > 0 ? item[0] : {};
+
+                // RoadMap의 인덱스에 따라 wordContentId 설정
+                let wd_cnt_id;
+                if (index === 1) {
+                    wd_cnt_id = this.wordContentId1;
+                    firstItem.textId = null;
+                } else if (index === 5) {
+                    wd_cnt_id = this.wordContentId2;
+                    firstItem.textId = null;
+                } else if (index === 9) {
+                    wd_cnt_id = this.wordContentId3;
+                    firstItem.textId = null;
+                } else {
+                    wd_cnt_id = null; // 다른 인덱스에 대해선 null 설정
+                }
+
+                return {
+                    learning_id: firstItem.learningId, // 기존 학습 ID를 사용
+                    wd_cnt_id: wd_cnt_id, // wordContentId
+                    text_id: firstItem.textId || null, // 텍스트 ID
+                    eval_id: firstItem.evalId || null, // 평가 ID
+                    seq: index + 1 // seq는 1부터 시작
+                };
+            });
+
+            // 업데이트 요청 보내기
+            axios.post("/unitLearning/update.json", unitLearningList)
+                .then(response => {
+                    console.log(`Update successful:`, response.data);
+                    if (response.data > 0) {
+                    }
+                })
+                .catch(error => {
+                    console.error(`Error during update`, error);
+                });
         },
 
         // prblmbook 만들어 id 가져오기
         postPrblmBook() {
+            const problemList = [];
 
+            // RoadMap에서 문제 ID 가져오기
+            const roadMapIndices = [2, 3, 6];
+
+            if (this.learningId1) {
+                this.RoadMap[roadMapIndices[0]].forEach(prblm => {
+                    problemList.push({
+                        learningId: this.learningId1,
+                        prblmId: prblm.prblmId // RoadMap에서 가져온 문제 ID
+                    });
+                });
+            }
+
+            // learningId2에 대해 문제 등록
+            if (this.learningId2) {
+                this.RoadMap[roadMapIndices[1]].forEach(prblm => {
+                    problemList.push({
+                        learningId: this.learningId2,
+                        prblmId: prblm.prblmId // RoadMap에서 가져온 문제 ID
+                    });
+                });
+            }
+
+            // learningId3에 대해 문제 등록
+            if (this.learningId3) {
+                this.RoadMap[roadMapIndices[2]].forEach(prblm => {
+                    problemList.push({
+                        learningId: this.learningId3,
+                        prblmId: prblm.prblmId // RoadMap에서 가져온 문제 ID
+                    });
+                });
+            }
+
+            // 문제 등록 API 호출
+            axios.post("/problemBook/register.json", problemList)
+                .then(response => {
+                    console.log("Problems registered successfully:", response.data);
+                    this.fetchRoadmapData();
+                    alert("학습로드맵 등록이 완료되었습니다!");
+                })
+                .catch(error => {
+                    console.error("Error during registering problems:", error);
+                });
         },
-        // wordcontent 만들어 id 가져오기
-        postWordContent() {
-
-        },
-
-        // 로드맵 정보 가져오기
     },
     watch: {
 
@@ -1162,7 +1599,7 @@
 
         this.fetchBooks();
         this.fetchUnits();
-
+        this.fetchRoadmapData();
     }
 }
 </script>
Add a comment
List