This commit is contained in:
root
2026-07-05 16:08:00 +00:00
parent 2b2070d11b
commit 2dac119791
+53 -2
View File
@@ -292,6 +292,25 @@
</div>
<div v-if="!showFeedback" class="flex flex-col sm:flex-row justify-center items-center gap-3 w-full">
<template v-if="hasStoredCorrectAnswer">
<button
@click="submitDescriptiveNormalGrading"
:disabled="!userDescriptiveAnswer.trim() || gradingDescriptive"
class="btn btn-primary btn-md sm:btn-lg w-full sm:w-auto sm:flex-1 shadow-md text-sm sm:text-base whitespace-normal break-keep"
>
일반 채점
</button>
<button
@click="submitDescriptiveGrading"
:disabled="!userDescriptiveAnswer.trim() || gradingDescriptive"
class="btn btn-secondary btn-md sm:btn-lg w-full sm:w-auto sm:flex-1 shadow-md gap-2 text-sm sm:text-base whitespace-normal break-keep"
>
<span v-if="gradingDescriptive" class="loading loading-spinner loading-sm"></span>
<SparklesIcon v-else :size="16" />
{{ gradingDescriptive ? 'AI 채점중...' : 'AI 채점' }}
</button>
</template>
<template v-else>
<button
@click="submitDescriptiveGrading"
:disabled="!userDescriptiveAnswer.trim() || gradingDescriptive"
@@ -301,6 +320,7 @@
<SparklesIcon v-else :size="18" />
{{ gradingDescriptive ? 'AI 채점 진행중...' : 'AI 채점 요청하기' }}
</button>
</template>
<button
@click="skipToExplanations"
:disabled="gradingDescriptive"
@@ -369,7 +389,7 @@
<!-- Feedback & Explanations -->
<div v-if="showFeedback" class="bg-base-300/80 border-t border-base-300 p-5 sm:p-6 md:p-8">
<div v-if="!isDescriptiveQuestion" class="alert shadow-lg mb-6" :class="isCorrect ? 'alert-success' : 'alert-error'">
<div v-if="!isDescriptiveQuestion || usedDescriptiveNormalGrading" class="alert shadow-lg mb-6" :class="isCorrect ? 'alert-success' : 'alert-error'">
<CheckCircleIcon v-if="isCorrect" :size="24" />
<XCircleIcon v-else :size="24" />
<div>
@@ -639,6 +659,7 @@ const userDescriptiveAnswer = ref('')
const descriptiveGradingResult = ref<DescriptiveGradingRecord | null>(null)
const descriptiveHistory = ref<DescriptiveGradingRecord[]>([])
const gradingError = ref('')
const usedDescriptiveNormalGrading = ref(false)
// OCR state
const ocrFileInput = ref<HTMLInputElement | null>(null)
@@ -807,6 +828,26 @@ function submitTextAnswerWithAi() {
submitDescriptiveGrading()
}
function submitDescriptiveNormalGrading() {
if (showFeedback.value || !userDescriptiveAnswer.value.trim()) return
const userClean = userDescriptiveAnswer.value.trim().replace(/\s+/g, '').toLowerCase()
const correctAnswers = (currentQuestion.value.correctAnswerStr || '')
.split(';;')
.map(ans => ans.trim().replace(/\s+/g, '').toLowerCase())
isCorrect.value = correctAnswers.includes(userClean)
const key = `${currentQuestion.value.source}_${currentQuestion.value.id}`
if (isCorrect.value && !scoredQuestions.value[key]) {
scoredQuestions.value[key] = true
score.value++
}
usedDescriptiveNormalGrading.value = true
showFeedback.value = true
}
async function submitDescriptiveGrading() {
const q = currentQuestion.value
if (!q || !userDescriptiveAnswer.value.trim() || gradingDescriptive.value) return
@@ -1006,6 +1047,11 @@ const isDescriptiveQuestion = computed(() => {
return ans === '주관식' || ans.length > 8 || ans.includes(' ') || ans.includes('및') || ans.includes('와')
})
const hasStoredCorrectAnswer = computed(() => {
const ans = currentQuestion.value?.correctAnswerStr?.trim()
return !!ans && ans !== '주관식'
})
const isPdf = computed(() => {
const url = currentQuestion.value.imageUrl
if (!url) return false
@@ -1403,6 +1449,7 @@ interface QuestionState {
isCorrect: boolean
userDescriptiveAnswer: string
descriptiveGradingResult: DescriptiveGradingRecord | null
usedDescriptiveNormalGrading: boolean
}
const questionStates = ref<Record<number, QuestionState>>({})
@@ -1414,7 +1461,8 @@ function saveCurrentState() {
showFeedback: showFeedback.value,
isCorrect: isCorrect.value,
userDescriptiveAnswer: userDescriptiveAnswer.value,
descriptiveGradingResult: descriptiveGradingResult.value
descriptiveGradingResult: descriptiveGradingResult.value,
usedDescriptiveNormalGrading: usedDescriptiveNormalGrading.value
}
}
@@ -1430,6 +1478,7 @@ function loadState(index: number) {
isCorrect.value = state.isCorrect
userDescriptiveAnswer.value = state.userDescriptiveAnswer || ''
descriptiveGradingResult.value = state.descriptiveGradingResult || null
usedDescriptiveNormalGrading.value = state.usedDescriptiveNormalGrading || false
} else {
selectedChoiceIndex.value = -1
userTextAnswer.value = ''
@@ -1440,6 +1489,7 @@ function loadState(index: number) {
descriptiveGradingResult.value = null
uploadedOcrImageBase64.value = ''
ocrResultText.value = null
usedDescriptiveNormalGrading.value = false
}
loadGradingHistory()
}
@@ -1477,6 +1527,7 @@ function resetQuiz() {
userTextAnswer.value = ''
userOXAnswer.value = ''
questionStates.value = {}
scoredQuestions.value = {}
}
const togglingBookmark = ref(false)