diff --git a/apps/client/components/main/QuestionInput/QuestionInput.vue b/apps/client/components/main/QuestionInput/QuestionInput.vue index 0461f9efd..229e1c18b 100644 --- a/apps/client/components/main/QuestionInput/QuestionInput.vue +++ b/apps/client/components/main/QuestionInput/QuestionInput.vue @@ -10,7 +10,22 @@ :class="getWordsClassNames(i)" :style="{ minWidth: `${inputWidth(w)}ch` }" > - {{ userInputWords[i]["userInput"] }} + + + + + + {{ userInputWords[i]["userInput"] }} + courseStore.currentStatement?.english!, - setInputCursorPosition, - getInputCursorPosition, - inputChangedCallback, - }); -const { showAnswerTip, hiddenAnswerTip } = useAnswerTip(); +const { + inputValue, + userInputWords, + submitAnswer, + setInputValue, + handleKeyboardInput, + isFixMode, + tipWords, +} = useInput({ + source: () => courseStore.currentStatement?.english!, + setInputCursorPosition, + getInputCursorPosition, + inputChangedCallback, +}); +const { showAnswerTip, hiddenAnswerTip, isAnswerTip } = useAnswerTip(); onMounted(() => { focusInput(); @@ -82,6 +104,7 @@ focusInputWhenWIndowFocus(); watch( () => inputValue.value, (val) => { + hiddenAnswerTip(); setInputValue(val); courseTimer.time(String(courseStore.statementIndex)); }, @@ -210,7 +233,7 @@ function handleKeydown(e: KeyboardEvent) { useSpaceSubmitAnswer: { enable: isUseSpaceSubmitAnswer(), rightCallback: handleAnswerRight, - errorCallback: handleAnswerError, + errorCallback: handleAnswerError, // 错误提示 }, }); } diff --git a/apps/client/composables/main/answerTip.ts b/apps/client/composables/main/answerTip.ts index 88b7f2987..d0fd08ed3 100644 --- a/apps/client/composables/main/answerTip.ts +++ b/apps/client/composables/main/answerTip.ts @@ -1,10 +1,12 @@ import { ref } from "vue"; +import { validateInput } from "./question"; const answerTip = ref(false); export function useAnswerTip() { function showAnswerTip() { answerTip.value = true; + validateInput() } function hiddenAnswerTip() { answerTip.value = false; diff --git a/apps/client/composables/main/question.ts b/apps/client/composables/main/question.ts index 42d3add21..0fa73e3f8 100644 --- a/apps/client/composables/main/question.ts +++ b/apps/client/composables/main/question.ts @@ -1,4 +1,5 @@ import { nextTick, reactive, ref, watchEffect } from "vue"; +import { useCourseStore } from "~/store/course"; interface Word { text: string; @@ -32,6 +33,44 @@ export function clearQuestionInput() { inputValue.value = ""; } +interface TipWord { + noInput: boolean; + characters: { incorrect: boolean; character: string }[]; +} + +const tipWords = reactive([]); + +export function validateInput() { + const userInputs = inputValue.value.toLowerCase().split(separator) + + function getUserInput(index: number) { + return userInputs[index] || ""; + } + + function validateCharacter(word: string, index: number) { + const userInput = getUserInput(index); + const inputCharacters = userInput.split(""); + + const overLength = userInput.length > word.length; + + return word + .toLowerCase() + .split("") + .map((character, index) => ({ + character, + incorrect: character !== inputCharacters[index] || overLength, + })); + } + + const courseStore = useCourseStore(); + courseStore.words.forEach((word, index) => { + tipWords[index] = { + noInput: !Boolean(getUserInput(index)), + characters: validateCharacter(word, index), + }; + }); +} + export function useInput({ source, setInputCursorPosition, @@ -354,5 +393,6 @@ export function useInput({ fixFirstIncorrectWord, resetUserInputWords, isFixMode, + tipWords, }; }