Files
wordloop/frontend/src/components/SpellCard.vue
T
John 68c5efe573 Add spell practice, memory analytics, auth persistence, and word library UX.
Includes per-word training stats and curves, quiz session auto-save, remember-login,
paginated word list with floating page arrows, and Obsidian-style relationship graph baseline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 14:57:39 -07:00

137 lines
2.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, watch } from 'vue'
import type { QuizQuestion } from '../api/request'
const props = defineProps<{
question: QuizQuestion
index: number
total: number
showResult?: boolean
isCorrect?: boolean
submittedAnswer?: string
}>()
const emit = defineEmits<{
submit: [answer: string]
}>()
const input = ref('')
watch(
() => props.index,
() => {
input.value = ''
}
)
function onSubmit() {
const answer = input.value.trim()
if (!answer || props.showResult) return
emit('submit', answer)
}
defineExpose({
getDraft: () => input.value.trim(),
})
</script>
<template>
<div class="card quiz-card">
<div class="quiz-progress">{{ index + 1 }} / {{ total }}</div>
<div class="quiz-type">根据中文与读音拼写英文</div>
<div class="quiz-prompt">{{ question.prompt }}</div>
<div v-if="question.phonetic" class="phonetic">{{ question.phonetic }}</div>
<div v-else class="phonetic muted">暂无音标</div>
<input
v-model="input"
class="spell-input"
type="text"
placeholder="输入英文单词"
autocomplete="off"
autocapitalize="off"
spellcheck="false"
:disabled="showResult"
@keydown.enter="onSubmit"
/>
<button
v-if="!showResult"
class="btn btn-primary submit-btn"
:disabled="!input.trim()"
@click="onSubmit"
>
提交
</button>
<div v-if="showResult" class="result" :class="isCorrect ? 'ok' : 'fail'">
{{ isCorrect ? '拼写正确 ' : '拼写错误 ' }}
<template v-if="!isCorrect">
你的答案{{ submittedAnswer }} · 正确答案{{ question.correct_answer }}
</template>
</div>
</div>
</template>
<style scoped>
.quiz-progress {
font-size: 13px;
color: var(--muted);
margin-bottom: 8px;
}
.quiz-type {
font-size: 12px;
color: var(--primary);
margin-bottom: 8px;
}
.quiz-prompt {
font-size: 28px;
font-weight: 700;
text-align: center;
margin: 20px 0 8px;
}
.phonetic {
text-align: center;
font-size: 18px;
color: var(--primary);
margin-bottom: 20px;
}
.phonetic.muted {
color: var(--muted);
font-size: 14px;
}
.spell-input {
width: 100%;
padding: 14px 16px;
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: 18px;
text-align: center;
box-sizing: border-box;
}
.spell-input:focus {
outline: none;
border-color: var(--primary);
}
.spell-input:disabled {
background: #f3f4f6;
}
.submit-btn {
width: 100%;
margin-top: 12px;
}
.result {
margin-top: 16px;
padding: 12px;
border-radius: var(--radius);
font-size: 14px;
text-align: center;
line-height: 1.5;
}
.result.ok {
background: #d1fae5;
color: #047857;
}
.result.fail {
background: #fee2e2;
color: #b91c1c;
}
</style>