-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
704 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<script setup lang="ts"> | ||
/** 单字练习 */ | ||
import { shallowRef, onMounted, provide } from "vue"; | ||
import { ChaiCard, ZigenCard, cache, fetchJsonWithCache } from "./share"; | ||
import Train from "./anki/TrainAnki.vue"; | ||
const p = defineProps<{ | ||
/** 卡片组的名字 */ | ||
name: string, | ||
/** 单字练习的数据的JSON文件的路径,要加 / */ | ||
chaiJson: string | ||
/** 练习的范围,从第几条到第几条,不填则是全部 */ | ||
range?: [start: number, end: number] | ||
/** 字根练习的数据JSON文件的路径,如果chaiJson里只有拆分没有编码,则必须提供字根数据 */ | ||
zigenJson?: string, | ||
/** 字根的字体CSS名称 */ | ||
fontClass?: string | ||
}>() | ||
provide("font", p.fontClass) | ||
let cardsName = p.name + '_single' | ||
const range = p.range | ||
if (range) { | ||
cardsName += `_${range[0]}_${range[1]}` | ||
} | ||
const cards = shallowRef<ChaiCard[]>(cache[cardsName]) | ||
onMounted(async () => { | ||
/** 初始化时候,要处理请求json数据、截断数据、补齐编码字段 */ | ||
if (cards.value) return; | ||
let chaifenCards: ChaiCard[] = await fetchJsonWithCache(p.chaiJson) | ||
if (range) { | ||
chaifenCards = chaifenCards.slice(range[0], range[1]) | ||
} | ||
// 填上编码信息 | ||
if (p.zigenJson) { | ||
const zigenCard = await fetchJsonWithCache(p.zigenJson) as ZigenCard[] | ||
const zigenKeyMap = new Map(zigenCard.map(v => [v.name, v.key])) | ||
for (const e of chaifenCards) { | ||
if (e.key) continue | ||
if (!e.comp) { | ||
const msg = `${p.zigenJson} 文件里 ${e} 没有comp字段也没有key字段` | ||
alert(msg) | ||
throw new Error(msg) | ||
} | ||
e.key = [...e.comp].map(gen => zigenKeyMap.get(gen) || '').join('') | ||
} | ||
} | ||
cache[cardsName] = chaifenCards | ||
return cards.value = chaifenCards | ||
}) | ||
</script> | ||
|
||
<template> | ||
<Train v-if="cards" :name="cardsName" :cards /> | ||
<h2 class="text-gray-700" v-else> | ||
下载数据中…… | ||
</h2> | ||
</template>./TrainAnki2.vue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<script setup lang="ts"> | ||
import { shallowRef, watch, onMounted, inject, nextTick } from "vue"; | ||
import { useAnki } from "./useAnki"; | ||
import { Card, startConfette } from "../share"; | ||
const p = defineProps<{ | ||
/** 复习卡片的数据 */ | ||
cards: Card[] | ||
/** 复习卡片的名字 */ | ||
name: string | ||
}>() | ||
const fontClass = inject('font') | ||
const { | ||
progress, | ||
card, | ||
answer, | ||
restart, | ||
} = useAnki(p.cards, p.name) | ||
const isCorrect = shallowRef(true) | ||
const userKeys = shallowRef('') | ||
// 聚焦输入框 | ||
onMounted(() => { | ||
const element = document.getElementById('input_el') | ||
element?.focus() | ||
}) | ||
watch(userKeys, (newKeys) => { | ||
// 多个编码没有打完就不提示错误 | ||
if (newKeys.length < card.value!.key.length) | ||
return | ||
// 检查回答 | ||
if (newKeys === card.value.key) { | ||
answer(isCorrect.value) | ||
isCorrect.value = true | ||
} else { | ||
isCorrect.value = false | ||
} | ||
// 清空输入 | ||
userKeys.value = '' | ||
}) | ||
// 烟花效果 | ||
const showConfetti = shallowRef(false) | ||
watch(progress, async (newV, oldV) => { | ||
const newLearn = newV.meet | ||
const oldLearn = oldV.meet | ||
if (newLearn === p.cards.length && newLearn > oldLearn) { | ||
showConfetti.value = true | ||
await nextTick() | ||
startConfette() | ||
} | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div | ||
:class="['md:w-2/3 w-full shadow-sm my-12 pb-24 bg-opacity-10 transition-color rounded-md', { 'bg-red-700': !isCorrect, 'bg-slate-500': isCorrect }]"> | ||
<div class="flex justify-center mb-24"> | ||
<progress class="progress w-full" :value="progress.familiar" :max="cards.length" /> | ||
</div> | ||
<template v-if="!showConfetti"> | ||
<div class="flex justify-around mb-8"> | ||
|
||
<div :key="card.name" | ||
:class="['text-6xl animate__animated', 'kaiti-font', { 'text-red-400': !isCorrect, 'animate__headShake': !isCorrect }]"> | ||
{{ card.name }}</div> | ||
|
||
|
||
</div> | ||
<div class="flex justify-center p-5"> | ||
<input id="input_el" type="text" placeholder="输入编码" v-model="userKeys" | ||
:class="['input w-half max-w-xs input-bordered text-center input-sm dark:bg-slate-800 bg-white', { 'input-error': !isCorrect }]" /> | ||
</div> | ||
<div :class="['text-center', { 'opacity-0': isCorrect }]">答案是 <b class="font-mono">{{ card.key }}</b> | ||
<span :class="[fontClass]" v-if="'comp' in card">({{ card.comp }})</span> | ||
</div> | ||
</template> | ||
|
||
<template v-else> | ||
<div class="p-10 text-6xl text-center font-bold text-orange-800 font-sans tracking-widest -rotate-6"> | ||
🎉恭喜过关!!</div> | ||
<div class="flex justify-center mt-10"> | ||
<button class="btn btn-success" @click="_ => showConfetti = false">继续练习</button> | ||
</div> | ||
</template> | ||
|
||
</div> | ||
|
||
<div class="text-gray-500 flex justify-between"> | ||
<div class="text-gray-500">训练进度: {{ progress.meet }} / {{ cards.length }}</div> | ||
<button class="btn btn-ghost btn-sm font-light" @click="_ => restart()">restart</button> | ||
</div> | ||
</template> |
Oops, something went wrong.