重新设计组件结构
This commit is contained in:
40
src/App.vue
40
src/App.vue
@@ -1,15 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Toolbar from "@/components/Toolbar/Toolbar.vue";
|
||||
import Type from "@/components/Type.vue";
|
||||
import Side from "@/components/Side.vue";
|
||||
import Statistics from "@/components/Modal/Statistics.vue";
|
||||
import Backgorund from "@/components/Backgorund.vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {SaveKey} from "@/types.ts"
|
||||
import Footer from "@/components/Footer.vue"
|
||||
import TypeArticle from "@/components/TypeArticle.vue"
|
||||
import Practice from "@/components/Practice.vue"
|
||||
|
||||
const store = useBaseStore()
|
||||
// 查询当前系统主题颜色
|
||||
@@ -38,15 +33,8 @@ onMounted(() => {
|
||||
<template>
|
||||
<!-- <Backgorund/>-->
|
||||
<div class="main-page">
|
||||
<div class="center">
|
||||
<Toolbar/>
|
||||
<div class="content">
|
||||
<!-- <Type/>-->
|
||||
<TypeArticle/>
|
||||
</div>
|
||||
<Footer/>
|
||||
<Side/>
|
||||
</div>
|
||||
<Practice/>
|
||||
<!-- <Side/>-->
|
||||
<Statistics></Statistics>
|
||||
</div>
|
||||
</template>
|
||||
@@ -57,32 +45,12 @@ onMounted(() => {
|
||||
.main-page {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100vw;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-size: 14rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: var(--color-main-bg);
|
||||
|
||||
.center {
|
||||
width: var(--toolbar-width);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
//border: 1px solid gray;
|
||||
position: relative;
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
--color-item-hover: white;
|
||||
--color-item-active: rgb(75, 110, 175);
|
||||
--color-main-active: rgb(12,140,233);
|
||||
//--toolbar-width: 700rem;
|
||||
--toolbar-width: 50vw;
|
||||
--toolbar-width: 700rem;
|
||||
//--toolbar-width: 50vw;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
|
||||
@@ -16,7 +16,7 @@ interface IProps {
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
total: 0,
|
||||
startDate: Date.now,
|
||||
startDate: Date.now(),
|
||||
inputNumber: 0,
|
||||
wrongNumber: 0,
|
||||
correctRate: 0,
|
||||
@@ -24,8 +24,8 @@ const props = withDefaults(defineProps<IProps>(), {
|
||||
|
||||
const store = useBaseStore()
|
||||
|
||||
function format(val: number, suffix: string = '') {
|
||||
return val === 0 ? '-' : (val + suffix)
|
||||
function format(val: number, suffix: string = '', check: number = -1) {
|
||||
return val === check ? '-' : (val + suffix)
|
||||
}
|
||||
|
||||
const progress = $computed(() => {
|
||||
@@ -72,12 +72,12 @@ onUnmounted(() => {
|
||||
<div class="name">单词总数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ inputNumber }}</div>
|
||||
<div class="num">{{ format(inputNumber, '', 0) }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">输入数</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="num">{{ format(props.wrongNumber) }}</div>
|
||||
<div class="num">{{ format(props.wrongNumber, '', 0) }}</div>
|
||||
<div class="line"></div>
|
||||
<div class="name">错误数</div>
|
||||
</div>
|
||||
@@ -100,7 +100,7 @@ onUnmounted(() => {
|
||||
@import "@/assets/css/colors.scss";
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
width: var(--toolbar-width);
|
||||
margin-bottom: 30rem;
|
||||
transition: all .3s;
|
||||
position: relative;
|
||||
|
||||
24
src/components/Practice.vue
Normal file
24
src/components/Practice.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Toolbar from "@/components/Toolbar/Toolbar.vue"
|
||||
import TypeArticle from "@/components/TypeArticle.vue"
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="practice">
|
||||
<Toolbar/>
|
||||
<TypeArticle/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.practice {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -130,9 +130,9 @@ watch(() => store.setting.showToolbar, n => {
|
||||
@import "@/assets/css/colors.scss";
|
||||
|
||||
header {
|
||||
width: var(--toolbar-width);
|
||||
margin-top: 10rem;
|
||||
min-height: 60rem;
|
||||
width: 100%;
|
||||
background: var(--color-header-bg);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -39,6 +39,21 @@ const [playCorrect] = useSound([correct], 1)
|
||||
const [playAudio] = usePlayWordAudio()
|
||||
|
||||
|
||||
interface IProps {
|
||||
total: number,
|
||||
startDate: number
|
||||
inputNumber: number
|
||||
wrongNumber: number
|
||||
correctRate: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
total: 0,
|
||||
startDate: Date.now(),
|
||||
inputNumber: 0,
|
||||
wrongNumber: 0,
|
||||
correctRate: 0,
|
||||
})
|
||||
|
||||
const resetWord = $computed(() => {
|
||||
return store.word.name.slice(input.length + wrong.length)
|
||||
|
||||
281
src/components/Type2.vue
Normal file
281
src/components/Type2.vue
Normal file
@@ -0,0 +1,281 @@
|
||||
<script setup lang="ts">
|
||||
import {computed, onMounted, onUnmounted, provide, watch} from "vue"
|
||||
import 快速打字的机械键盘声音Mp3 from '../assets/sound/key-sounds/快速打字的机械键盘声音.mp3'
|
||||
import 键盘快速打字的声音Mp3 from '../assets/sound/key-sounds/键盘快速打字的声音.mp3'
|
||||
import 电话打字的声音Mp3 from '../assets/sound/key-sounds/电话打字的声音.mp3'
|
||||
import 老式机械 from '../assets/sound/key-sounds/老式机械.mp3'
|
||||
import 机械0 from '../assets/sound/key-sounds/jixie/机械0.mp3'
|
||||
import 机械1 from '../assets/sound/key-sounds/jixie/机械1.mp3'
|
||||
import 机械2 from '../assets/sound/key-sounds/jixie/机械2.mp3'
|
||||
import 机械3 from '../assets/sound/key-sounds/jixie/机械3.mp3'
|
||||
import beep from '../assets/sound/beep.wav'
|
||||
import correct from '../assets/sound/correct.wav'
|
||||
import {$computed, $ref} from "vue/macros"
|
||||
import {useSound} from "@/hooks/useSound.ts"
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import {DictType, SaveKey, ShortKeyMap, Statistics, Word} from "../types";
|
||||
import {usePlayWordAudio} from "@/hooks/usePlayWordAudio.ts"
|
||||
import useTheme from "@/hooks/useTheme.ts";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {
|
||||
Down,
|
||||
Delete,
|
||||
} from "@icon-park/vue-next"
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
import {cloneDeep} from "lodash"
|
||||
|
||||
let input = $ref('')
|
||||
let wrong = $ref('')
|
||||
let showFullWord = $ref(false)
|
||||
let activeIndex = $ref(-1)
|
||||
const store = useBaseStore()
|
||||
|
||||
// const [playKeySound, setAudio] = useSound([机械0, 机械1, 机械2, 机械3], 1)
|
||||
// const [playKeySound, setAudio] = useSound([老式机械], 3)
|
||||
const [playKeySound, setAudio] = useSound([电话打字的声音Mp3], 3)
|
||||
const [playBeep] = useSound([beep], 1)
|
||||
const [playCorrect] = useSound([correct], 1)
|
||||
const [playAudio] = usePlayWordAudio()
|
||||
|
||||
interface IProps {
|
||||
words: Word[],
|
||||
index: number,
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
words: [],
|
||||
index: -1
|
||||
})
|
||||
let data = $ref({
|
||||
index: props.index,
|
||||
words: props.words,
|
||||
wrongWords: [],
|
||||
originWrongWords: [],
|
||||
repeatNumber: 0,
|
||||
startDate: Date.now(),
|
||||
correctRate: -1,
|
||||
})
|
||||
let word = $computed(() => {
|
||||
return data.words[data.index] ?? {
|
||||
trans: [],
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
}
|
||||
})
|
||||
let resetWord = $computed(() => {
|
||||
return word.name.slice(input.length + wrong.length)
|
||||
})
|
||||
|
||||
watch(data, () => {
|
||||
if (data.index < 1) {
|
||||
return data.correctRate = -1
|
||||
}
|
||||
if (data.wrongWords.length > data.index) {
|
||||
return data.correctRate = 0
|
||||
}
|
||||
data.correctRate = 100 - Math.trunc((data.wrongWords.length / data.index) * 100)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
window.addEventListener('keyup', onKeyUp)
|
||||
|
||||
emitter.on(EventKey.resetWord, () => {
|
||||
input = ''
|
||||
})
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
// console.log('onUnmounted')
|
||||
window.removeEventListener('keydown', onKeyDown)
|
||||
window.removeEventListener('keyup', onKeyUp)
|
||||
})
|
||||
|
||||
function next() {
|
||||
if (data.index === props.words.length - 1) {
|
||||
if (data.wrongWords.length) {
|
||||
data.words = cloneDeep(data.wrongWords)
|
||||
if (!data.originWrongWords.length) {
|
||||
data.originWrongWords = cloneDeep(data.wrongWords)
|
||||
}
|
||||
data.index = 0
|
||||
data.repeatNumber++
|
||||
data.wrongWords = []
|
||||
} else {
|
||||
console.log('这本书完了')
|
||||
emitter.emit(EventKey.openStatModal)
|
||||
}
|
||||
} else {
|
||||
data.index++
|
||||
console.log('这个词完了')
|
||||
if ([DictType.customDict, DictType.innerDict].includes(store.current.dictType)
|
||||
&& store.skipWordNames.includes(word.name.toLowerCase())) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
wrong = input = ''
|
||||
}
|
||||
|
||||
function onKeyUp(e: KeyboardEvent) {
|
||||
showFullWord = false
|
||||
}
|
||||
|
||||
async function onKeyDown(e: KeyboardEvent) {
|
||||
//TODO 还有横杠
|
||||
if ((e.keyCode >= 65 && e.keyCode <= 90) || e.code === 'Space') {
|
||||
let letter = e.key
|
||||
if ((input + letter).toLowerCase() === word.name.toLowerCase().slice(0, input.length + 1)) {
|
||||
input += letter
|
||||
wrong = ''
|
||||
playKeySound()
|
||||
} else {
|
||||
if (!store.wrongWordDict.originWords.find((v: Word) => v.name.toLowerCase() === word.name.toLowerCase())) {
|
||||
store.wrongWordDict.originWords.push(word)
|
||||
store.wrongWordDict.words.push(word)
|
||||
store.wrongWordDict.chapterWords = [store.wrongWordDict.words]
|
||||
}
|
||||
if (!data.wrongWords.find((v: Word) => v.name.toLowerCase() === word.name.toLowerCase())) {
|
||||
data.wrongWords.push(word)
|
||||
}
|
||||
wrong = letter
|
||||
playKeySound()
|
||||
playBeep()
|
||||
setTimeout(() => {
|
||||
wrong = ''
|
||||
}, 500)
|
||||
}
|
||||
if (input.toLowerCase() === word.name.toLowerCase()) {
|
||||
playCorrect()
|
||||
setTimeout(next, 300)
|
||||
}
|
||||
} else {
|
||||
// console.log('e', e)
|
||||
switch (e.key) {
|
||||
case 'Backspace':
|
||||
if (wrong) {
|
||||
wrong = ''
|
||||
} else {
|
||||
input = input.slice(0, -1)
|
||||
}
|
||||
break
|
||||
case ShortKeyMap.Collect:
|
||||
if (!store.newWordDict.originWords.find((v: Word) => v.name === word.name)) {
|
||||
store.newWordDict.originWords.push(word)
|
||||
store.newWordDict.words.push(word)
|
||||
store.newWordDict.chapterWords = [store.newWordDict.words]
|
||||
}
|
||||
activeIndex = 1
|
||||
break
|
||||
case ShortKeyMap.Remove:
|
||||
if (!store.skipWordNames.includes(word.name)) {
|
||||
store.skipWordDict.originWords.push(word)
|
||||
store.skipWordDict.words.push(word)
|
||||
store.skipWordDict.chapterWords = [store.skipWordDict.words]
|
||||
}
|
||||
activeIndex = 0
|
||||
next()
|
||||
break
|
||||
case ShortKeyMap.Ignore:
|
||||
e.preventDefault()
|
||||
activeIndex = 2
|
||||
next()
|
||||
break
|
||||
case ShortKeyMap.Show:
|
||||
showFullWord = true
|
||||
break
|
||||
}
|
||||
setTimeout(() => {
|
||||
activeIndex = -1
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="type-word">
|
||||
<div class="translate">{{ word.trans.join(';') }}</div>
|
||||
<div class="word-wrapper">
|
||||
<div class="word" :class="wrong && 'is-wrong'">
|
||||
<span class="input" v-if="input">{{ input }}</span>
|
||||
<span class="wrong" v-if="wrong">{{ wrong }}</span>
|
||||
<template v-if="store.isDictation">
|
||||
<span class="letter" v-if="!showFullWord"
|
||||
@mouseenter="showFullWord = true">{{ resetWord.split('').map(v => '_').join('') }}</span>
|
||||
<span class="letter" v-else @mouseleave="showFullWord = false">{{ resetWord }}</span>
|
||||
</template>
|
||||
<span class="letter" v-else>{{ resetWord }}</span>
|
||||
</div>
|
||||
<div class="audio" @click="playAudio(word.name)">播放</div>
|
||||
</div>
|
||||
<div class="phonetic">{{ word.usphone }}</div>
|
||||
<div class="options">
|
||||
<BaseButton keyboard="`" :active="activeIndex === 0">
|
||||
忽略
|
||||
</BaseButton>
|
||||
<BaseButton keyboard="Enter" :active="activeIndex === 1">
|
||||
收藏
|
||||
</BaseButton>
|
||||
<BaseButton keyboard="Tab" :active="activeIndex === 2">
|
||||
下一个
|
||||
</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "@/assets/css/colors.scss";
|
||||
|
||||
.type-word {
|
||||
display: flex;
|
||||
//display: none;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
font-size: 14rem;
|
||||
color: gray;
|
||||
gap: 2rem;
|
||||
|
||||
.options {
|
||||
margin-top: 10rem;
|
||||
display: flex;
|
||||
gap: 15rem;
|
||||
font-size: 18rem;
|
||||
}
|
||||
|
||||
.phonetic, .translate {
|
||||
font-size: 20rem;
|
||||
margin-left: -30rem;
|
||||
}
|
||||
|
||||
.word-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
|
||||
.word {
|
||||
font-size: 48rem;
|
||||
line-height: 1;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
|
||||
letter-spacing: 5rem;
|
||||
|
||||
.input {
|
||||
color: rgb(22, 163, 74);
|
||||
}
|
||||
|
||||
.wrong {
|
||||
color: rgba(red, 0.6);
|
||||
}
|
||||
|
||||
&.is-wrong {
|
||||
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {usePlayWordAudio} from "@/hooks/usePlayWordAudio.ts"
|
||||
import {computed, nextTick, onMounted, reactive} from "vue"
|
||||
import {computed, nextTick, onMounted, reactive, watch} from "vue"
|
||||
import {cloneDeep} from "lodash"
|
||||
import 快速打字的机械键盘声音Mp3 from '../assets/sound/key-sounds/快速打字的机械键盘声音.mp3'
|
||||
import 键盘快速打字的声音Mp3 from '../assets/sound/key-sounds/键盘快速打字的声音.mp3'
|
||||
@@ -18,6 +18,7 @@ import {CnKeyboardMap, useSplitArticle} from "@/hooks/useSplitArticle";
|
||||
import {$computed, $ref} from "vue/macros";
|
||||
import {Article, DictType, SaveKey, Sentence, ShortKeyMap, Word} from "@/types";
|
||||
import {useBaseStore} from "@/stores/base";
|
||||
import Footer2 from "@/components/Footer2.vue"
|
||||
|
||||
let article1 = `How does the older investor differ in his approach to investment from the younger investor?
|
||||
There is no shortage of tipsters around offering 'get-rich-quick' opportunities. But if you are a serious private investor, leave the Las Vegas mentality to those with money to fritter. The serious investor needs a proper 'portfolio' -- a well-planned selection of investments, with a definite structure and a clear aim. But exactly how does a newcomer to the stock market go about achieving that?
|
||||
@@ -56,7 +57,6 @@ const [playCorrect] = useSound([correct], 1)
|
||||
|
||||
const store = useBaseStore()
|
||||
|
||||
|
||||
let sectionIndex = $ref(0)
|
||||
let sentenceIndex = $ref(0)
|
||||
let wordIndex = $ref(6)
|
||||
@@ -64,12 +64,20 @@ let index = $ref(0)
|
||||
let input = $ref('')
|
||||
let wrong = $ref('')
|
||||
let isSpace = $ref(false)
|
||||
let isDictation = $ref(false)
|
||||
let isDictation = $ref(true)
|
||||
let showFullWord = $ref(false)
|
||||
let hoverIndex = $ref({
|
||||
sectionIndex: 0,
|
||||
sentenceIndex: 0,
|
||||
})
|
||||
let statistics = $ref({
|
||||
wrongWords: [],
|
||||
total: 0,
|
||||
startDate: 0,
|
||||
inputNumber: 0,
|
||||
wrongNumber: 0,
|
||||
correctRate: -1,
|
||||
})
|
||||
|
||||
let article = reactive<Article>({
|
||||
article: article1,
|
||||
@@ -81,39 +89,30 @@ let article = reactive<Article>({
|
||||
translate: [],
|
||||
})
|
||||
|
||||
watch(statistics, () => {
|
||||
if (statistics.inputNumber < 1) {
|
||||
return statistics.correctRate = -1
|
||||
}
|
||||
if (statistics.wrongNumber > statistics.inputNumber) {
|
||||
return statistics.correctRate = 0
|
||||
}
|
||||
statistics.correctRate = 100 - Math.trunc(((statistics.wrongNumber) / (statistics.inputNumber)) * 100)
|
||||
})
|
||||
onMounted(() => {
|
||||
let sections = useSplitArticle(article.article)
|
||||
let wordNumber = 0
|
||||
sections.map(v => {
|
||||
v.map(w => {
|
||||
w.words.map(s=>{
|
||||
if (!store.skipWordNames.includes(s.toLowerCase())){
|
||||
w.words.map(s => {
|
||||
if (!store.skipWordNamesWithSimpleWords.includes(s.toLowerCase())) {
|
||||
wordNumber++
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
console.log('sections', sections)
|
||||
console.log('wordNumber', wordNumber)
|
||||
statistics.total = wordNumber
|
||||
statistics.startDate = Date.now()
|
||||
|
||||
setTimeout(() => {
|
||||
store.current = {
|
||||
dictType: DictType.innerDict,
|
||||
words: [],
|
||||
index: wordIndex,
|
||||
wrongWords: [],
|
||||
originWrongWords: [],
|
||||
repeatNumber: 0,
|
||||
statistics: {
|
||||
startDate: Date.now(),
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
wordNumber: wordNumber,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
}
|
||||
}
|
||||
}, 1000)
|
||||
let temp = useSplitArticle(article.articleTranslate, 'cn', CnKeyboardMap)
|
||||
temp.map((v, i) => {
|
||||
v.map((w, j) => {
|
||||
@@ -187,7 +186,9 @@ function onKeyDown(e: KeyboardEvent) {
|
||||
isSpace = false
|
||||
index = 0
|
||||
wordIndex++
|
||||
store.current.index++
|
||||
if (!store.skipWordNamesWithSimpleWords.includes(currentWord.toLowerCase())) {
|
||||
statistics.inputNumber++
|
||||
}
|
||||
|
||||
playCorrect()
|
||||
if (!currentSentence.words[wordIndex]) {
|
||||
@@ -257,21 +258,23 @@ function onKeyDown(e: KeyboardEvent) {
|
||||
ukphone: '',
|
||||
trans: []
|
||||
}
|
||||
if (!store.wrongWordDict.originWords.find((v: Word) => v.name === currentWord)) {
|
||||
if (!store.wrongWordDict.originWords.find((v: Word) => v.name.toLowerCase() === currentWord.toLowerCase())) {
|
||||
store.wrongWordDict.originWords.push(word)
|
||||
store.wrongWordDict.words.push(word)
|
||||
store.wrongWordDict.chapterWords = [store.wrongWordDict.words]
|
||||
}
|
||||
if (!store.current.wrongWords.find((v: Word) => v.name === currentWord)) {
|
||||
store.current.wrongWords.push(word)
|
||||
|
||||
if (!store.skipWordNamesWithSimpleWords.includes(currentWord.toLowerCase())) {
|
||||
if (!statistics.wrongWords.find((v) => v.toLowerCase() === currentWord.toLowerCase())) {
|
||||
statistics.wrongWords.push(currentWord)
|
||||
statistics.wrongNumber++
|
||||
}
|
||||
}
|
||||
store.current.statistics.correctRate = Math.trunc(((store.current.index + 1 - store.current.wrongWords.length) / (store.current.index + 1)) * 100)
|
||||
|
||||
wrong = letter
|
||||
playBeep()
|
||||
setTimeout(() => {
|
||||
wrong = ''
|
||||
// wrong = input = ''
|
||||
}, 500)
|
||||
console.log('未匹配')
|
||||
}
|
||||
@@ -321,7 +324,6 @@ function onKeyUp() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function playWord(word: string) {
|
||||
playAudio(word)
|
||||
}
|
||||
@@ -370,14 +372,11 @@ function otherWord(word: string, i: number, i2: number, i3: number) {
|
||||
|
||||
<template>
|
||||
<div class="type-wrapper">
|
||||
<div class="trans">
|
||||
<span>翻译:</span>
|
||||
<span class="text">上周我去看戏了</span>
|
||||
</div>
|
||||
<div class="article-wrapper" ref="articleWrapperRef">
|
||||
<article @click="focus">
|
||||
<div class="section"
|
||||
v-for="(section,indexI) in article.sections">
|
||||
<div class="content">
|
||||
<div class="article-wrapper" ref="articleWrapperRef">
|
||||
<article @click="focus">
|
||||
<div class="section"
|
||||
v-for="(section,indexI) in article.sections">
|
||||
<span class="sentence"
|
||||
:class="[
|
||||
sectionIndex === indexI && sentenceIndex === indexJ ?'isDictation':''
|
||||
@@ -416,22 +415,30 @@ function otherWord(word: string, i: number, i2: number, i3: number) {
|
||||
]"> </span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
<div class="translate">
|
||||
<div class="row"
|
||||
:class="`translate${item.location}`"
|
||||
v-for="item in article.translate">
|
||||
<span class="space"></span>
|
||||
<span class="text">{{ item.sentence }}</span>
|
||||
</div>
|
||||
</article>
|
||||
<div class="translate">
|
||||
<div class="row"
|
||||
:class="`translate${item.location}`"
|
||||
v-for="item in article.translate">
|
||||
<span class="space"></span>
|
||||
<span class="text">{{ item.sentence }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input ref="inputRef"
|
||||
class="inputEl"
|
||||
type="text"
|
||||
@keyup="onKeyUp"
|
||||
@keydown="onKeyDown">
|
||||
</div>
|
||||
<input ref="inputRef"
|
||||
class="inputEl"
|
||||
type="text"
|
||||
@keyup="onKeyUp"
|
||||
@keydown="onKeyDown">
|
||||
<Footer2
|
||||
:total="statistics.total"
|
||||
:startDate="statistics.startDate"
|
||||
:inputNumber="statistics.inputNumber"
|
||||
:wrongNumber="statistics.wrongNumber"
|
||||
:correctRate="statistics.correctRate"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -444,22 +451,16 @@ function otherWord(word: string, i: number, i2: number, i3: number) {
|
||||
}
|
||||
|
||||
.type-wrapper {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.trans {
|
||||
height: 40rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: none;
|
||||
|
||||
.text {
|
||||
color: var(--color-font-1);
|
||||
|
||||
font-size: 22rem;
|
||||
}
|
||||
.content {
|
||||
width: 60%;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
article {
|
||||
|
||||
@@ -19,7 +19,7 @@ export function useSound(srcList?: string[], num?: number) {
|
||||
})
|
||||
|
||||
let index = $ref(0)
|
||||
const play = () => {
|
||||
const play: Function = () => {
|
||||
index++
|
||||
if (audioList.length > 1 && audioList.length !== audioLength) {
|
||||
audioList[index % audioList.length].play()
|
||||
|
||||
@@ -98,6 +98,9 @@ export const useBaseStore = defineStore('base', {
|
||||
},
|
||||
getters: {
|
||||
skipWordNames: (state: State) => {
|
||||
return state.skipWordDict.originWords.map(v => v.name.toLowerCase())
|
||||
},
|
||||
skipWordNamesWithSimpleWords: (state: State) => {
|
||||
return state.skipWordDict.originWords.map(v => v.name.toLowerCase()).concat(state.simpleWords)
|
||||
},
|
||||
currentDict(state: State): Dict {
|
||||
|
||||
Reference in New Issue
Block a user