Merge branch 'refs/heads/master' into dev

This commit is contained in:
Zyronon
2025-11-14 23:56:44 +08:00
10 changed files with 80 additions and 56 deletions

View File

@@ -492,7 +492,7 @@
</div>
</a>
</div>
<div>蜀ICP备2025157466号</div>
<div><a href="https://beian.miit.gov.cn/" target="_blank">蜀ICP备2025157466号</a></div>
</div>
<div class="mask" onclick="closeDialog()"></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

@@ -10,6 +10,7 @@ async function generateSitemap() {
// 静态路由(首页、练习页等)
const staticPages = [
{url: '/index.html', changefreq: 'monthly', priority: 1.0},
{url: '/', changefreq: 'daily', priority: 1.0},
{url: '/words', changefreq: 'daily', priority: 0.9},
{url: '/articles', changefreq: 'daily', priority: 0.9},

View File

@@ -66,7 +66,9 @@ async function init() {
setTheme(settingStore.theme)
if (!settingStore.first) {
if (settingStore.first) {
set(APP_VERSION.key,APP_VERSION.version)
}else {
get(APP_VERSION.key).then(r => {
runtimeStore.isNew = r ? (APP_VERSION.version > Number(r)) : true
})

View File

@@ -60,7 +60,7 @@ export const SAVE_DICT_KEY = {
}
export const SAVE_SETTING_KEY = {
key: 'typing-word-setting',
version: 16
version: 17
}
export const EXPORT_DATA_KEY = {
key: 'typing-word-export',

View File

@@ -1,25 +1,24 @@
<script setup lang="ts">
import { inject, onMounted, onUnmounted, watch } from "vue"
import {inject, onMounted, onUnmounted, watch} from "vue"
import {Article, ArticleWord, PracticeArticleWordType, Sentence, ShortcutKey, Word} from "@/types/types.ts";
import { useBaseStore } from "@/stores/base.ts";
import { useSettingStore } from "@/stores/setting.ts";
import { usePlayBeep, usePlayCorrect, usePlayKeyboardAudio } from "@/hooks/sound.ts";
import {useBaseStore} from "@/stores/base.ts";
import {useSettingStore} from "@/stores/setting.ts";
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio} from "@/hooks/sound.ts";
import {emitter, EventKey, useEvents} from "@/utils/eventBus.ts";
import { _dateFormat, _nextTick, msToHourMinute, msToMinute, total } from "@/utils";
import {_dateFormat, _nextTick, msToHourMinute, total} from "@/utils";
import '@imengyu/vue3-context-menu/lib/vue3-context-menu.css'
import ContextMenu from '@imengyu/vue3-context-menu'
import { getTranslateText } from "@/hooks/article.ts";
import BaseButton from "@/components/BaseButton.vue";
import QuestionForm from "@/pages/article/components/QuestionForm.vue";
import { getDefaultArticle, getDefaultWord } from "@/types/func.ts";
import {getDefaultArticle, getDefaultWord} from "@/types/func.ts";
import Toast from '@/components/base/toast/Toast.ts'
import TypingWord from "@/pages/article/components/TypingWord.vue";
import Space from "@/pages/article/components/Space.vue";
import { useWordOptions } from "@/hooks/dict.ts";
import {useWordOptions} from "@/hooks/dict.ts";
import nlp from "compromise/three";
import { nanoid } from "nanoid";
import { usePracticeStore } from "@/stores/practice.ts";
import { PracticeSaveArticleKey } from "@/config/env.ts";
import {nanoid} from "nanoid";
import {usePracticeStore} from "@/stores/practice.ts";
import {PracticeSaveArticleKey} from "@/config/env.ts";
interface IProps {
article: Article,
@@ -246,6 +245,7 @@ function nextSentence() {
}
function onTyping(e: KeyboardEvent) {
debugger
if (!props.article.sections.length) return
if (isTyping || isEnd) return;
isTyping = true;
@@ -263,7 +263,12 @@ function onTyping(e: KeyboardEvent) {
// 检查下一个单词是否存在
if (wordIndex + 1 < currentSentence.words.length) {
wordIndex++;
emit('nextWord', currentWord);
currentWord = currentSentence.words[wordIndex]
if ([PracticeArticleWordType.Symbol,PracticeArticleWordType.Number].includes(currentWord.type) && settingStore.ignoreSymbol){
next()
}else {
emit('nextWord', currentWord);
}
} else {
nextSentence()
}
@@ -273,12 +278,16 @@ function onTyping(e: KeyboardEvent) {
if (e.code === 'Space') {
next()
} else {
wrong = ' '
playBeep()
setTimeout(() => {
wrong = ''
wrong = input = ''
}, 500)
// 如果在第一个单词的最后一位上, 不按空格的直接输入下一个字母的话
next()
isTyping = false
onTyping(e)
// wrong = ' '
// playBeep()
// setTimeout(() => {
// wrong = ''
// wrong = input = ''
// }, 500)
}
} else {
//如果是首句首词

View File

@@ -557,7 +557,7 @@ function importOldData() {
<div class="line"></div>
<SettingItem mainTitle="自动切换"/>
<SettingItem title="自动切换下一个单词"
desc="未开启自动切换时,当输入完成后请使用 **空格键** 切换下一个"
desc="仅在 **跟写** 时生效,听写、辨认、默写均不会自动切换,需要手动按 **空格键** 切换"
>
<Switch v-model="settingStore.autoNextWord"/>
</SettingItem>
@@ -621,8 +621,12 @@ function importOldData() {
<Slider v-model="settingStore.articleSoundSpeed" :step="0.1" :min="0.5" :max="3"/>
<span class="w-10 pl-5">{{ settingStore.articleSoundSpeed }}</span>
</SettingItem>
</div>
<div class="line"></div>
<SettingItem title="输入时忽略符号/数字">
<Switch v-model="settingStore.ignoreSymbol"/>
</SettingItem>
</div>
<div class="body" v-if="tabIndex === 3">
<div class="row">
@@ -682,6 +686,22 @@ function importOldData() {
</div>
<div v-if="tabIndex === 5">
<div class="log-item">
<div class="mb-2">
<div>
<div>更新日期2025/11/14</div>
<div>更新内容新增文章练习时可跳过空格如果在单词的最后一位上不按空格直接输入下一个字母的话自动跳下一个单词 按空格也自动跳下一个单词</div>
</div>
</div>
</div>
<div class="log-item">
<div class="mb-2">
<div>
<div>更新日期2025/11/13</div>
<div>更新内容新增文章练习时输入时忽略符号/数字选项</div>
</div>
</div>
</div>
<div class="log-item">
<div class="mb-2">
<div>

View File

@@ -206,19 +206,24 @@ watch(() => settingStore.wordPracticeType, (n) => {
}
}, {immediate: true})
const groupSize = 7
function wordLoop() {
// return data.index++
let d = Math.floor(data.index / 6) - 1
if (data.index > 0 && data.index % 6 === (d < 0 ? 0 : d)) {
if (settingStore.wordPracticeType === WordPracticeType.FollowWrite) {
// 学习模式
if (settingStore.wordPracticeType === WordPracticeType.FollowWrite) {
data.index++
// 到达一个组末尾,就切换到拼写模式
if (data.index % groupSize === 0) {
settingStore.wordPracticeType = WordPracticeType.Spell
data.index -= 6
} else {
settingStore.wordPracticeType = WordPracticeType.FollowWrite
data.index++
data.index -= groupSize // 回到刚学单词开头
}
} else {
// 拼写模式
data.index++
// 拼写走完一组,切回跟写模式
if (data.index % groupSize === 0) {
settingStore.wordPracticeType = WordPracticeType.FollowWrite
}
}
}
@@ -268,19 +273,8 @@ async function next(isTyping: boolean = true) {
if (data.index === data.words.length - 1) {
if (statStore.step === 0 || isTypingWrongWord.value) {
if (settingStore.wordPracticeType !== WordPracticeType.Spell) {
let i = data.index
i--
let d = Math.floor(i / 6) - 1
while (i % 6 !== (d < 0 ? 0 : d)) {
i--
d = Math.floor(i / 6) - 1
}
console.log('i', i)
if (i <= 0) i = -1
if (i + 1 == data.index) {
data.index = 0
}
data.index = i + 1
//回到最后一组的开始位置
data.index = Math.floor(data.index / groupSize) * groupSize
emitter.emit(EventKey.resetWord)
settingStore.wordPracticeType = WordPracticeType.Spell
return

View File

@@ -86,6 +86,8 @@ function startPractice() {
complete: store.sdict.complete,
wordPracticeMode: settingStore.wordPracticeMode
})
//把是否是第一次设置为false
settingStore.first = false
nav('practice-words/' + store.sdict.id, {}, {taskWords: currentStudy})
} else {
window.umami?.track('no-dict')

View File

@@ -1,9 +1,9 @@
import { defineStore } from "pinia"
import { checkAndUpgradeSaveSetting, cloneDeep } from "@/utils";
import {defineStore} from "pinia"
import {checkAndUpgradeSaveSetting, cloneDeep} from "@/utils";
import {DefaultShortcutKeyMap, WordPracticeMode, WordPracticeType} from "@/types/types.ts";
import { get } from "idb-keyval";
import { CAN_REQUEST, SAVE_SETTING_KEY } from "@/config/env.ts";
import { getSetting } from "@/apis";
import {get} from "idb-keyval";
import {CAN_REQUEST, SAVE_SETTING_KEY} from "@/config/env.ts";
import {getSetting} from "@/apis";
export interface SettingState {
soundType: string,
@@ -53,6 +53,7 @@ export interface SettingState {
disableShowPracticeSettingDialog: boolean // 不默认显示练习设置弹框
autoNextWord: boolean //自动切换下一个单词
inputWrongClear: boolean //单词输入错误,清空已输入内容
ignoreSymbol: boolean //过滤符号
}
export const getDefaultSettingState = (): SettingState => ({
@@ -103,6 +104,7 @@ export const getDefaultSettingState = (): SettingState => ({
disableShowPracticeSettingDialog: false,
autoNextWord: true,
inputWrongClear: false,
ignoreSymbol: true
})
export const useSettingStore = defineStore('setting', {
@@ -115,13 +117,7 @@ export const useSettingStore = defineStore('setting', {
},
init() {
return new Promise(async resolve => {
//TODO 后面记得删除了
let configStr = localStorage.getItem(SAVE_SETTING_KEY.key)
let configStr2 = await get(SAVE_SETTING_KEY.key)
if (configStr2) {
//兼容localStorage.getItem
configStr = configStr2
}
let configStr = await get(SAVE_SETTING_KEY.key)
let data = checkAndUpgradeSaveSetting(configStr)
if (CAN_REQUEST) {
let res = await getSetting()