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
<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>