
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
2024-11-19
2024-11-19
<template>
<div class="title-box flex justify-between mb40">
<p class="title">문제 상세 페이지</p>
</div>
<div class="content-t">
<label for="" class="title1">상세 내용</label>
<div class="board-wrap mt20">
<div class="flex align-center mb20">
<label for="" class="title2">단원</label>
<select v-model="selectedUnit" class="mr10 data-wrap">
<option v-for="(unit, index) in units" :key="index" :value="unit.unitId">
{{ unit.unitName }}
</option>
</select>
</div>
<div class="flex align-center mb20">
<label for="" class="title2">평가 유형</label>
<select v-model="selectedType" class="mr10 data-wrap">
<option value="중간평가">중간평가</option>
<option value="최종평가">최종평가</option>
</select>
</div>
<hr>
<button type="button" title="글쓰기" class="new-btn ml10" @click="buttonSearch">
문제 추가
</button>
<hr>
<div class="flex align-center mb20">
<table>
<thead>
<tr>
<td>No.</td>
<td>문제</td>
<td>유형</td>
<td>점수</td>
<td>순서</td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(evaluation, index) in evals" :key="evaluation.prblmId">
<td>{{ index + 1 }}</td>
<td>{{ evaluation.prblmExpln }}</td>
<td>{{ evaluation.prblmTypeNm }}</td>
<td>{{ evaluation.prblmScr }}</td>
<td><input v-model="evaluation.seq"></td>
<td><button type="button" title="글쓰기" class="new-btn"
@click="deleteEvalProblem(evaluation.prblmId)">
삭제
</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="flex justify-between mt50">
<button type="button" title="글쓰기" class="new-btn" @click="goToPage('ExamList')">
목록
</button>
<div class="flex">
<button type="button" title="글쓰기" class="new-btn" @click="submitDetailForm">
문제 수정
</button>
<button type="button" title="글쓰기" class="new-btn" @click="deleteEval">
평가 삭제
</button>
</div>
</div>
<div v-show="searchOpen" class="popup-wrap">
<div class="popup-box ">
<div class="flex justify-between mb30">
<p class="popup-title">문제 검색</p>
<button type="button" class="popup-close-btn" @click="closeBtn">
<svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
</button>
</div>
<div class="search-wrap mb30">
<input type="text" class="data-wrap" placeholder="" v-model="searchKeyword">
<button type="button" @click="fetchProblems">
<img src="../../../resources/img/look_t.png" alt="">
</button>
</div>
<div class="table-wrap">
<table>
<colgroup>
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 30%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<td></td>
<td>No.</td>
<td>문제</td>
<td>유형</td>
<td>점수</td>
<td>작성자</td>
<td>등록일</td>
</tr>
</thead>
<tbody>
<tr v-for="(problem, index) in problems" :key="problem.prblmId">
<td><input type="checkbox" v-model="problem.check"></td>
<td>{{ index + 1 }}</td>
<td>{{ problem.prblmExpln }}</td>
<td>{{ problem.prblmTypeNm }}</td>
<td>{{ problem.prblmScr }}</td>
<td>{{ problem.userId }}</td>
<td>{{ problem.regDt }}</td>
</tr>
</tbody>
</table>
<article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px;">
<button @click="changePage(currentPage - 1)" :disabled="currentPage === 1">
<img src="../../../resources/img/btn27_90t_normal.png" alt="Previous">
</button>
<button v-for="page in paginationButtons" :key="page" @click="changePage(page)"
:class="{ 'selected-btn': currentPage === page }">
{{ page }}
</button>
<button @click="changePage(currentPage + 1)" :disabled="currentPage === totalPages">
<img src="../../../resources/img/btn28_90t_normal.png" alt="Next">
</button>
</article>
</div>
<div class="flex justify-end ">
<button type="button" title="" class="new-btn mr10" @click="closeBtn">
취소
</button>
<button type="button" title="" class="new-btn" @click="insertEval">
등록
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import SvgIcon from '@jamescoyle/vue-icon';
import { mdiMagnify } from '@mdi/js';
import axios from 'axios';
export default {
data() {
return {
mdiMagnify: mdiMagnify,
units: [],
problems: [],
selectedUnit: null,
currentPage: 1,
pageSize: 5,
totalPosts: 0,
searchOption: '',
searchKeyword: '',
searchOpen: false,
evals: [],
evalData: {},
}
},
methods: {
goToPage(page) {
this.$router.push({ name: page });
},
buttonSearch() {
this.searchOpen = true;
this.fetchProblems();
},
closeBtn() {
this.searchOpen = false;
},
fetchUnits() {
axios({
url: "/unit/findAll.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
})
.then(response => {
console.log(response.data)
this.units = response.data;
if (this.$route.query.unit_id) {
this.selectedUnit = this.$route.query.unit_id;
}
})
.catch(error => {
console.error("fetchUnits - error: ", error);
alert("단원 목록을 불러오는 중 오류가 발생했습니다.");
});
},
// 문제 가져오기
async fetchProblems(page = 1) {
try {
const response = await axios.post('/problem/problemList.json', {
option: this.searchOption,
keyword: this.searchKeyword,
unitId: this.selectedUnit,
pageSize: this.pageSize,
startIndex: (page - 1) * 5
});
this.problems = response.data.problems;
this.totalPosts = response.data.totalProblem;
this.currentPage = page;
} catch (error) {
console.error('문제 목록을 불러오는 중 오류가 발생했습니다.', error);
}
},
changePage(page) {
if (page < 1 || page > this.totalPages) return;
this.currentPage = page;
this.fetchProblems(page);
},
// 팝업 데이터 가져오기
insertEval() {
const selectedProblems = this.problems.filter(problem => problem.check).map(problem => ({
...problem,
isNew: true, // 새로운 문제라는 플래그 추가
}));
this.evals.push(...selectedProblems);
this.closeBtn();
},
// 평가 정보 가져오기
fetchEvalData() {
axios({
url: "/evalProblem/selectEvalProblem.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: {
evalId: this.$route.query.eval_id
},
})
.then(response => {
this.evalData = response.data[0];
this.selectedType = this.evalData.eval_type;
})
.catch(error => {
console.error("fetchData - error: ", error);
alert("검색 중 오류가 발생했습니다.");
});
},
// 평가 문제 정보 가져오기
fetchEvalQues() {
axios({
url: "/problem/evaluationProblemList.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: {
evalId: this.$route.query.eval_id
},
})
.then(response => {
this.evals = response.data.map(problem => ({
...problem,
originalSeq: problem.seq
}));
})
.catch(error => {
console.error("fetchData - error: ", error);
alert("검색 중 오류가 발생했습니다.");
});
},
// 평가 문제 하나 삭제하기
deleteEvalProblem(prblmId) {
const result = confirm('문제를 삭제 하시겠습니까?')
if (result) {
} else {
alert("삭제를 취소했습니다")
return;
}
const problem = this.evals.find(evaluation => evaluation.prblmId === prblmId);
if (problem.isNew) {
alert("새로 추가된 문제는 삭제할 수 없습니다.");
return;
}
axios({
url: "/evalProblem/deleteEvalProblem.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: {
evalId: this.$route.query.eval_id,
prblmId: prblmId,
},
})
.then(response => {
this.fetchEvalQues();
})
.catch(error => {
console.error("fetchData - error: ", error);
alert("검색 중 오류가 발생했습니다.");
});
},
// 평가 문제 상세 업로드
async submitDetailForm() {
const evalProblemVOList = this.evals
.filter(evaluation => evaluation.isNew)
.map(evaluation => ({
evalId: this.$route.query.eval_id,
prblmId: evaluation.prblmId,
}));
const hasNewProblems = evalProblemVOList.length > 0;
try {
if (hasNewProblems) {
const response = await axios.post('/evalProblem/insertEvalProblem.json', evalProblemVOList);
console.log('성공:', response.data);
} else {
console.log('새로 추가된 문제가 없습니다.');
}
// 순서가 변경된 문제가 있을 경우 updateSequence 실행
await this.updateSequence();
// 업데이트 후 평가 문제 목록 갱신
alert('문제 수정에 성공했습니다!');
this.fetchEvalQues();
} catch (error) {
console.error('오류:', error);
}
},
// 문제 정보 수정하기 (순서 변경)
async updateSequence() {
const evalList = this.evals
.filter(evaluation => evaluation.seq !== evaluation.originalSeq) // 순서가 변경된 문제만 필터링
.map(evaluation => ({
prblmId: evaluation.prblmId,
seq: evaluation.seq,
}));
if (evalList.length === 0) {
console.log('순서가 변경된 문제가 없습니다.');
return;
}
try {
const response = await axios.post('/problem/updateProblemSeq.json', evalList);
console.log('순서 업데이트 성공:', response.data);
} catch (error) {
console.error('순서 업데이트 오류:', error);
}
},
// 평가 자체를 삭제하기
deleteEval() {
const result = confirm('이 평가를 삭제 하시겠습니까?')
if (result) {
} else {
alert("삭제를 취소했습니다")
return;
}
axios({
url: "/evaluation/deleteEvaluation.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: {
evalId: this.$route.query.eval_id,
},
})
.then(response => {
this.goToPage('ExamList');
})
.catch(error => {
console.error("fetchData - error: ", error);
alert("삭제 중 오류가 발생했습니다.");
});
},
},
watch: {
},
computed: {
totalPages() {
return Math.ceil(this.totalPosts / this.pageSize);
},
paginationButtons() {
let start = Math.max(0, this.currentPage - 2);
let end = Math.min(start + 5, this.totalPages);
if (end - start < 5) {
start = Math.max(0, end - 5);
}
return Array.from({ length: end - start }, (_, i) => start + i + 1);
},
startIndex() {
return this.currentPage * this.itemsPerPage;
}
},
components: {
SvgIcon
},
mounted() {
this.fetchUnits();
this.fetchEvalData();
this.fetchEvalQues();
}
}
</script>