Merge branch 'refs/heads/master' into dev
This commit is contained in:
@@ -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 |
@@ -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},
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 {
|
||||
//如果是首句首词
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user