Compare commits
28 Commits
save-mobli
...
v1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ba825a6e4 | ||
|
|
0c0b4eec6f | ||
|
|
54e411310d | ||
|
|
2827bcaa17 | ||
|
|
c35e8d3f45 | ||
|
|
6c32ecdaff | ||
|
|
e8a89b8fb3 | ||
|
|
627107d930 | ||
|
|
a179710ba2 | ||
|
|
84bf0a05a9 | ||
|
|
a0ef147b10 | ||
|
|
6e8b5bb807 | ||
|
|
aee56efdf5 | ||
|
|
b4a26b2c97 | ||
|
|
75cd9d6aa3 | ||
|
|
d5b88ea982 | ||
|
|
f54c8d168b | ||
|
|
2904bda8ef | ||
|
|
64f1bd6161 | ||
|
|
10f9e21da1 | ||
|
|
0237db6273 | ||
|
|
d2753d04b1 | ||
|
|
6b06a9174f | ||
|
|
95a63465c5 | ||
|
|
4464dde128 | ||
|
|
5cad026983 | ||
|
|
9edb27d119 | ||
|
|
8739176f0f |
20
.github/ISSUE_TEMPLATE/功能请求---feature-request.md
vendored
20
.github/ISSUE_TEMPLATE/功能请求---feature-request.md
vendored
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: 功能请求 | Feature request
|
||||
about: 创建一个功能请求 | Create a feature request
|
||||
title: 功能请求 | Feature request
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
1、描述
|
||||
请尽可能详细描述您需要的特性。
|
||||
|
||||
2、这个功能解决了什么问题?
|
||||
请尽可能详尽地说明这个需求的用例和场景
|
||||
|
||||
1. Description
|
||||
Please provide as detailed a description as possible of the features you need.
|
||||
|
||||
2. What problem does this feature solve?
|
||||
Please provide as detailed a description of the use cases and scenarios for this requirement as possible
|
||||
33
.github/ISSUE_TEMPLATE/单词错误---word-error.md
vendored
33
.github/ISSUE_TEMPLATE/单词错误---word-error.md
vendored
@@ -1,33 +0,0 @@
|
||||
---
|
||||
name: 单词错误 | Word error
|
||||
about: 创建一个单词释义错误、音标错误的报告 | Create a report of incorrect word definitions and phonetic
|
||||
errors
|
||||
title: 单词错误 | Word error
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
1、词典名字
|
||||
在这里填写词典名字
|
||||
|
||||
2、单词
|
||||
在这里填写单词
|
||||
|
||||
3、错误内容
|
||||
在这里填写错误内容
|
||||
|
||||
4、截图
|
||||
可以直接按Ctrl + V 复制在这里(复制成功后会显示一串地址)
|
||||
|
||||
1. Dictionary name
|
||||
Fill in the dictionary name here
|
||||
|
||||
2. Words
|
||||
Fill in the words here
|
||||
|
||||
3. Error content
|
||||
Fill in the incorrect content here
|
||||
|
||||
4. Screenshot
|
||||
You can directly press Ctrl+V to copy here (a string of addresses will be displayed after successful copying)
|
||||
24
.github/ISSUE_TEMPLATE/问题报告---bug-report-.md
vendored
24
.github/ISSUE_TEMPLATE/问题报告---bug-report-.md
vendored
@@ -1,24 +0,0 @@
|
||||
---
|
||||
name: '问题报告 | Bug report '
|
||||
about: '创建一个问题报告 | Create a bug report '
|
||||
title: '问题报告 | Bug report '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### 注意:请确认问题可以在浏览器的 无痕模式 下复现,而不是自己安装的其他插件或脚本导致的
|
||||
|
||||
1、描述
|
||||
在这里填写问题描述
|
||||
|
||||
2、截图
|
||||
可以直接按Ctrl + V 复制在这里(复制成功后会显示一串地址)
|
||||
|
||||
### Note: Please confirm that the problem can be reproduced in the browser's traceless mode, rather than being caused by other plugins or scripts installed by yourself
|
||||
|
||||
1. Description
|
||||
Fill in the problem description here
|
||||
|
||||
2. Screenshot
|
||||
You can directly press Ctrl+V to copy here (a string of addresses will be displayed after successful copying)
|
||||
16
.github/workflows/deploy-pages.yml
vendored
16
.github/workflows/deploy-pages.yml
vendored
@@ -29,15 +29,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
@@ -47,13 +47,17 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v3
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
# Upload dist repository
|
||||
path: './dist'
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
uses: actions/deploy-pages@v4
|
||||
|
||||
|
||||
6
Dockerfile
Normal file
6
Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
||||
FROM node
|
||||
COPY . /root/typing-word
|
||||
WORKDIR /root/typing-word
|
||||
EXPOSE 3000
|
||||
RUN npm install
|
||||
CMD ["npm", "start"]
|
||||
24
README.md
24
README.md
@@ -10,13 +10,16 @@
|
||||
<a href="https://github.com/zyronon/type-word/blob/master/LICENSE"><img src="https://img.shields.io/github/license/zyronon/type-word" alt="License"></a>
|
||||
<a><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg"/></a>
|
||||
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
|
||||
<a href="https://hellogithub.com/repository/eb70616d65604458908fc1736e7d41fc" target="_blank"><img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=eb70616d65604458908fc1736e7d41fc&claim_uid=k5e4ZAqRjJEGzCW&theme=small" alt="Featured|HelloGitHub" /></a>
|
||||
</p>
|
||||
|
||||
<div align=center>
|
||||
<a href="https://trendshift.io/repositories/14139" target="_blank" class="trendshift-badge"><img src="https://trendshift.io/api/badge/repositories/14139" alt="TypeWords | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
</div>
|
||||
|
||||
## 📸 在线访问
|
||||
|
||||
Github Pages: <https://typing-word.ttentau.top>(国内推荐访问这个)
|
||||
|
||||
Netlify: <https://typing-words.netlify.app/>(需要翻墙)
|
||||
Github Pages: <https://2study.top>
|
||||
|
||||
## 🛠 功能列表
|
||||
|
||||
@@ -57,22 +60,9 @@ API 等词库。 尽可能满足大部分用户对背单词的需求,也非常
|
||||
- 王陆雅思王听力语料库
|
||||
- 日语常见词、N1 ~ N5
|
||||
|
||||
## 📗 API 词库
|
||||
|
||||
- JavaScript API、Node.js API、Java API、Linux Command、C#: List API
|
||||
|
||||
词库均来源于(除文章以外):[qwerty-learner](https://github.com/RealKai42/qwerty-learner/)
|
||||
|
||||
如果您需要背诵其他词库,欢迎在 Issue 中提出
|
||||
|
||||
## 🎙 功能与建议
|
||||
|
||||
目前项目处于开发初期,新功能正在持续添加中,如果你对软件有任何功能与建议,欢迎在 Issues 中提出
|
||||
如果你也喜欢本软件的设计思想,欢迎提交 pr,非常感谢你对我们的支持!
|
||||
|
||||
### 灵感来源
|
||||
|
||||
[qwerty-learner](https://github.com/RealKai42/qwerty-learner/) 很喜欢作者的这个项目,但是它没有背单词所必备的 **生词本、错词本、简单词** 的功能,可能是作者反复强调和提醒这个项目是“**为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件**”而不是一个“**背单词**”的软件吧,尽管绝大多数用户都是用它来背单词😂😂😂。
|
||||
|
||||
本项目参考其思路使用 Vue 重写了,并添加了 **生词本、错词本、简单词** 、 **文章练习** 等功能
|
||||
|
||||
|
||||
|
||||
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -44,6 +44,7 @@ declare module 'vue' {
|
||||
Empty: typeof import('./src/components/Empty.vue')['default']
|
||||
FeedbackModal: typeof import('./src/components/toolbar/FeedbackModal.vue')['default']
|
||||
Fireworks: typeof import('./src/components/Fireworks.vue')['default']
|
||||
HostNotice: typeof import('./src/components/HostNotice.vue')['default']
|
||||
IconWrapper: typeof import('./src/components/IconWrapper.vue')['default']
|
||||
Input: typeof import('./src/components/Input.vue')['default']
|
||||
List: typeof import('./src/components/list/List.vue')['default']
|
||||
|
||||
26
index.html
26
index.html
@@ -29,19 +29,19 @@
|
||||
|
||||
</script>
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
if (location.href.includes('netlify.app')) {
|
||||
hm.src = "https://hm.baidu.com/hm.js?d77525f1ad23698a2f34f54ff69c7750";
|
||||
} else if (location.href.includes('github.io')) {
|
||||
hm.src = "https://hm.baidu.com/hm.js?d77525f1ad23698a2f34f54ff69c7750";
|
||||
} else {
|
||||
hm.src = "https://hm.baidu.com/hm.js?c558fd8cc39d4cc233a9db44ff5b6e3f";
|
||||
}
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
if (!location.href.includes('localhost')
|
||||
&& !location.href.includes('192.168')
|
||||
&& !location.href.includes('172.16')
|
||||
&& !location.href.includes('10.0')
|
||||
) {
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?3dae52fcd5375a19905462e4ad3eb54e";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
80
package.json
80
package.json
@@ -17,51 +17,51 @@
|
||||
"i18n:write": "gulp i18nwrite"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentranslate/baidu": "^1.4.2",
|
||||
"@opentranslate/translator": "^1.4.2",
|
||||
"axios": "^1.5.0",
|
||||
"compromise": "^14.10.0",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"element-plus": "^2.3.9",
|
||||
"file-saver": "^2.0.5",
|
||||
"git-last-commit": "^1.0.1",
|
||||
"hover.css": "^2.3.2",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"nanoid": "^5.0.3",
|
||||
"pinia": "^2.1.6",
|
||||
"sentence-splitter": "^4.2.1",
|
||||
"tesseract.js": "^4.1.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-activity-calendar": "^1.2.2",
|
||||
"@opentranslate/baidu": "1.4.2",
|
||||
"@opentranslate/translator": "1.4.2",
|
||||
"axios": "1.5.0",
|
||||
"compromise": "14.10.0",
|
||||
"copy-to-clipboard": "3.3.3",
|
||||
"element-plus": "2.3.9",
|
||||
"file-saver": "2.0.5",
|
||||
"git-last-commit": "1.0.1",
|
||||
"hover.css": "2.3.2",
|
||||
"localforage": "1.10.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"mitt": "3.0.1",
|
||||
"nanoid": "5.0.3",
|
||||
"pinia": "2.1.6",
|
||||
"sentence-splitter": "4.2.1",
|
||||
"tesseract.js": "4.1.1",
|
||||
"vue": "3.3.13",
|
||||
"vue-activity-calendar": "1.2.2",
|
||||
"vue-i18n": "9",
|
||||
"vue-router": "4",
|
||||
"vue-virtual-scroller": "2.0.0-beta.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/uuid": "^9.0.4",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||
"@vue/compiler-sfc": "^3.3.4",
|
||||
"commitizen": "^4.3.0",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"esm": "^3.2.25",
|
||||
"gulp": "^4.0.2",
|
||||
"husky": "^8.0.3",
|
||||
"push-dir": "^0.4.1",
|
||||
"rollup-plugin-visualizer": "^5.9.2",
|
||||
"sass": "^1.64.2",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.2.0",
|
||||
"unplugin-auto-import": "^0.16.6",
|
||||
"unplugin-vue-components": "^0.25.2",
|
||||
"vite": "^4.4.5",
|
||||
"vue-tsc": "^1.8.5",
|
||||
"xlsx": "^0.18.5"
|
||||
"@iconify/vue": "4.1.1",
|
||||
"@types/file-saver": "2.0.5",
|
||||
"@types/lodash-es": "4.17.9",
|
||||
"@types/uuid": "9.0.4",
|
||||
"@vitejs/plugin-vue": "4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "3.0.1",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
"commitizen": "4.3.0",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"esm": "3.2.25",
|
||||
"gulp": "4.0.2",
|
||||
"husky": "8.0.3",
|
||||
"push-dir": "0.4.1",
|
||||
"rollup-plugin-visualizer": "5.9.2",
|
||||
"sass": "1.64.2",
|
||||
"tslib": "2.6.2",
|
||||
"typescript": "5.4.5",
|
||||
"unplugin-auto-import": "0.16.6",
|
||||
"unplugin-vue-components": "0.25.2",
|
||||
"vite": "4.4.5",
|
||||
"vue-tsc": "1.8.5",
|
||||
"xlsx": "0.18.5"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
||||
7784
pnpm-lock.yaml
generated
7784
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,7 @@ import CollectNotice from "@/components/CollectNotice.vue";
|
||||
import {SAVE_SETTING_KEY, SAVE_DICT_KEY} from "@/utils/const.ts";
|
||||
import {shakeCommonDict} from "@/utils";
|
||||
import router from "@/router.ts";
|
||||
import HostNotice from "@/components/HostNotice.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
@@ -83,6 +84,7 @@ onMounted(() => {
|
||||
<Backgorund/>
|
||||
<router-view/>
|
||||
<CollectNotice/>
|
||||
<HostNotice/>
|
||||
<ArticleContentDialog/>
|
||||
<SettingDialog/>
|
||||
</template>
|
||||
|
||||
@@ -84,7 +84,7 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
drawMoon()
|
||||
// drawMoon()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
@@ -49,7 +49,7 @@ const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
|
||||
<div class="collect" v-if="showNotice">
|
||||
<div class="href-wrapper">
|
||||
<div class="round">
|
||||
<div class="href">typing-word.ttentau.top</div>
|
||||
<div class="href">2study.top</div>
|
||||
<Icon
|
||||
width="22"
|
||||
icon="mdi:star-outline"/>
|
||||
@@ -179,4 +179,4 @@ const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
140
src/components/HostNotice.vue
Normal file
140
src/components/HostNotice.vue
Normal file
@@ -0,0 +1,140 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
|
||||
let settingStore = useSettingStore()
|
||||
let show = $ref(false)
|
||||
|
||||
function toggleNotice() {
|
||||
show = false
|
||||
}
|
||||
|
||||
watch(() => settingStore.load, (n) => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
if (params.get('from') === 'redirect') {
|
||||
show = true
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<transition name="right">
|
||||
<div class="HostNotice" v-if="show">
|
||||
<div class="notice">
|
||||
<div>检查到您是通过老域名 typing-word.ttentau.top 访问的本网站,特此弹窗提示!</div>
|
||||
<p>老域名已不再续费,7天后过期将无法访问,请更换为新域名 <span class="active"><a href="https://2study.top">2study.top</a></span>
|
||||
访问</p>
|
||||
</div>
|
||||
<div class="wrapper">
|
||||
<BaseButton size="large" @click="toggleNotice">关闭</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.right-enter-active,
|
||||
.right-leave-active {
|
||||
transition: all .5s ease;
|
||||
}
|
||||
|
||||
.right-enter-from,
|
||||
.right-leave-to {
|
||||
transform: translateX(110%);
|
||||
}
|
||||
|
||||
.HostNotice {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 2;
|
||||
font-size: 20rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: var(--color-second-bg);
|
||||
padding: 30rem;
|
||||
border-radius: 12rem;
|
||||
width: 500rem;
|
||||
color: var(--color-font-1);
|
||||
line-height: 1.5;
|
||||
border: 1px solid var(--color-item-border);
|
||||
box-shadow: var(--shadow);
|
||||
|
||||
.notice {
|
||||
margin-top: 30rem;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: var(--color-main-active);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
.collect {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.href-wrapper {
|
||||
display: flex;
|
||||
font-size: 16rem;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
|
||||
.round {
|
||||
color: var(--color-font-1);
|
||||
border-radius: 50rem;
|
||||
padding: 10rem 10rem;
|
||||
padding-left: 20rem;
|
||||
gap: 30rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: var(--color-main-bg);
|
||||
|
||||
.href {
|
||||
font-size: 14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.star {
|
||||
color: var(--color-main-active);
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.collect-keyboard {
|
||||
margin-top: 20rem;
|
||||
font-size: 16rem;
|
||||
|
||||
span {
|
||||
margin-left: 10rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close-wrapper {
|
||||
right: var(--space);
|
||||
top: var(--space);
|
||||
position: absolute;
|
||||
font-size: 14rem;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
color: var(--color-font-1);
|
||||
gap: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,20 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import {Icon} from '@iconify/vue';
|
||||
import {ref, watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {getAudioFileUrl, useChangeAllSound, usePlayAudio, useWatchAllSound} from "@/hooks/sound.ts";
|
||||
import {getShortcutKey, useDisableEventListener, useEventListener} from "@/hooks/event.ts";
|
||||
import {$computed, $ref} from "vue/macros";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {DefaultShortcutKeyMap, Dict, DictType, ShortcutKey} from "@/types.ts";
|
||||
import { Icon } from '@iconify/vue';
|
||||
import { ref, watch } from "vue";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { getAudioFileUrl, useChangeAllSound, usePlayAudio, useWatchAllSound } from "@/hooks/sound.ts";
|
||||
import { getShortcutKey, useDisableEventListener, useEventListener } from "@/hooks/event.ts";
|
||||
import { $computed, $ref } from "vue/macros";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { DefaultShortcutKeyMap, Dict, DictType, ShortcutKey } from "@/types.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {APP_NAME, EXPORT_DATA_KEY, SAVE_DICT_KEY, SAVE_SETTING_KEY, SoundFileOptions} from "@/utils/const.ts";
|
||||
import { APP_NAME, EXPORT_DATA_KEY, SAVE_DICT_KEY, SAVE_SETTING_KEY, SoundFileOptions } from "@/utils/const.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {BaseState, useBaseStore} from "@/stores/base.ts";
|
||||
import { BaseState, useBaseStore } from "@/stores/base.ts";
|
||||
import * as copy from "copy-to-clipboard";
|
||||
import {saveAs} from "file-saver";
|
||||
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, shakeCommonDict} from "@/utils";
|
||||
import {dayjs} from "element-plus";
|
||||
import { saveAs } from "file-saver";
|
||||
import { checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, shakeCommonDict } from "@/utils";
|
||||
import { dayjs } from "element-plus";
|
||||
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -344,16 +344,42 @@ function importData(e) {
|
||||
<label class="item-title">其他设置</label>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="sub-title">切换下一个单词时间</label>
|
||||
<label class="sub-title">是否自动切换到下一个单词</label>
|
||||
<div class="wrapper">
|
||||
<el-switch v-model="settingStore.autoNext"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
关闭后,当完成单词输入时,需要再次按下空格键切换下一个
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="sub-title">自动切换下一个单词延迟</label>
|
||||
<div class="wrapper">
|
||||
<el-input-number v-model="settingStore.waitTimeForChangeWord"
|
||||
:min="6"
|
||||
:max="100"
|
||||
:min="0"
|
||||
type="number"
|
||||
/>
|
||||
<span>毫秒</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="sub-title">默写时是否显示单词长度</label>
|
||||
<div class="wrapper">
|
||||
<el-switch v-model="settingStore.dictationShowWordLength"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
默写时用下划线 _ 来显示每个字符。关闭后,用空格代替,用户将无法判断单词长度
|
||||
</div>
|
||||
</div>
|
||||
<div class="body" v-if="tabIndex === 2">
|
||||
<div class="row">
|
||||
|
||||
@@ -20,20 +20,11 @@ const emit = defineEmits([
|
||||
<p>or</p>
|
||||
<div class="github">
|
||||
<span>在<a :href="GITHUB" target="_blank">Github</a>上给我提一个
|
||||
<a :href="`${GITHUB}/issues`" target="_blank">Issue</a>
|
||||
</span>
|
||||
<div class="options">
|
||||
<BaseButton>
|
||||
<a :href="`${GITHUB}/issues/new?assignees=&labels=&projects=&template=%E5%8D%95%E8%AF%8D%E9%94%99%E8%AF%AF---word-error.md&title=%E5%8D%95%E8%AF%8D%E9%94%99%E8%AF%AF+%7C+Word+error`"
|
||||
target="_blank">词典错误?</a>
|
||||
</BaseButton>
|
||||
<BaseButton>
|
||||
<a :href="`${GITHUB}/issues/new?assignees=&labels=&projects=&template=问题报告---bug-report-.md&title=问题报告+%7C+Bug+report+`"
|
||||
target="_blank">反馈BUG?</a>
|
||||
</BaseButton>
|
||||
<BaseButton>
|
||||
<a :href="`${GITHUB}/issues/new?assignees=&labels=&projects=&template=功能请求---feature-request.md&title=功能请求+%7C+Feature+request`"
|
||||
target="_blank">功能请求?</a>
|
||||
<a :href="`${GITHUB}/issues/new`"
|
||||
target="_blank">Issue</a>
|
||||
</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
@@ -72,4 +63,4 @@ const emit = defineEmits([
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -67,7 +67,7 @@ watch(() => store.load, n => {
|
||||
<Tooltip
|
||||
:title="`词典详情(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.OpenDictDetail]})`">
|
||||
<div class="info hvr-grow" @click="emitter.emit(EventKey.openDictModal,'detail')">
|
||||
{{ store.currentDict.name }} {{ practiceStore.repeatNumber ? ' 复习错词' : '' }}
|
||||
{{ store.currentDict.name }}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<ChapterName v-if="store.currentDict.type === DictType.word"/>
|
||||
|
||||
@@ -275,9 +275,10 @@ function toChapterWordList() {
|
||||
)
|
||||
}
|
||||
|
||||
//同步到我的词典列表
|
||||
//同步到我的词典列表,更新词典单词总数
|
||||
function syncEditDict2MyDictList() {
|
||||
syncMyDictList(runtimeStore.editDict)
|
||||
runtimeStore.editDict.length = runtimeStore.editDict.words.length;
|
||||
syncMyDictList(runtimeStore.editDict);
|
||||
}
|
||||
|
||||
|
||||
@@ -486,9 +487,9 @@ function exportData(type: string) {
|
||||
}
|
||||
|
||||
function importData(e: any) {
|
||||
let file = e.target.files[0]
|
||||
if (!file) return
|
||||
// no()
|
||||
let file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
let reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
let data = e.target.result;
|
||||
@@ -505,32 +506,36 @@ function importData(e: any) {
|
||||
usphone: String(v['音标①'] ?? ''),
|
||||
ukphone: String(v['音标②'] ?? ''),
|
||||
trans: String(v['释义(一行一个释义)'] ?? '').split('\n')
|
||||
}
|
||||
return word
|
||||
};
|
||||
return word;
|
||||
}
|
||||
}).filter(v => v)
|
||||
}).filter(v => v);
|
||||
|
||||
checkRepeatWord(words, residueWordList, noRepeatWords => {
|
||||
residueWordList = residueWordList.concat(noRepeatWords)
|
||||
syncEditDict2MyDictList()
|
||||
setTimeout(residueWordListRef?.scrollToBottom, 100)
|
||||
residueWordList = residueWordList.concat(noRepeatWords);
|
||||
// 同步到editDict中的words和originWords
|
||||
runtimeStore.editDict.words = runtimeStore.editDict.words.concat(noRepeatWords);
|
||||
runtimeStore.editDict.originWords = runtimeStore.editDict.originWords.concat(noRepeatWords);
|
||||
syncEditDict2MyDictList();
|
||||
setTimeout(residueWordListRef?.scrollToBottom, 100);
|
||||
},
|
||||
repeatWords => {
|
||||
repeatWords.map(v => {
|
||||
residueWordList[v.index] = v
|
||||
delete residueWordList[v.index].index
|
||||
})
|
||||
syncEditDict2MyDictList()
|
||||
setTimeout(residueWordListRef?.scrollToBottom, 100)
|
||||
residueWordList[v.index] = v;
|
||||
delete residueWordList[v.index].index;
|
||||
});
|
||||
syncEditDict2MyDictList();
|
||||
setTimeout(residueWordListRef?.scrollToBottom, 100);
|
||||
},
|
||||
() => ElMessage.success('导入成功!'))
|
||||
() => ElMessage.success('导入成功!'));
|
||||
} else {
|
||||
ElMessage.warning('导入失败!原因:没有数据')
|
||||
ElMessage.warning('导入失败!原因:没有数据');
|
||||
}
|
||||
};
|
||||
reader.readAsBinaryString(file);
|
||||
}
|
||||
|
||||
|
||||
function editDict() {
|
||||
isEditDict = true
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import {DefaultWord, ShortcutKey, Word} from "@/types.ts";
|
||||
import { DefaultWord, ShortcutKey, Word } from "@/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {$computed, $ref} from "vue/macros";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio, useTTsPlayAudio} from "@/hooks/sound.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {onUnmounted, watch, onMounted} from "vue";
|
||||
import { $computed, $ref } from "vue/macros";
|
||||
import { useBaseStore } from "@/stores/base.ts";
|
||||
import { usePracticeStore } from "@/stores/practice.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio, useTTsPlayAudio } from "@/hooks/sound.ts";
|
||||
import { emitter, EventKey } from "@/utils/eventBus.ts";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
import { onUnmounted, watch, onMounted } from "vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
|
||||
interface IProps {
|
||||
@@ -27,6 +27,7 @@ const emit = defineEmits<{
|
||||
let input = $ref('')
|
||||
let wrong = $ref('')
|
||||
let showFullWord = $ref(false)
|
||||
let waitNext = $ref(false)
|
||||
//输入锁定,因为跳转到下一个单词有延时,如果重复在延时期间内重复输入,导致会跳转N次
|
||||
let inputLock = false
|
||||
let wordRepeatCount = 0
|
||||
@@ -47,7 +48,7 @@ let displayWord = $computed(() => {
|
||||
watch(() => props.word, () => {
|
||||
wrong = input = ''
|
||||
wordRepeatCount = 0
|
||||
inputLock = false
|
||||
waitNext = inputLock = false
|
||||
if (settingStore.wordSound) {
|
||||
volumeIconRef?.play(400, true)
|
||||
}
|
||||
@@ -79,6 +80,13 @@ function repeat() {
|
||||
}
|
||||
|
||||
async function onTyping(e: KeyboardEvent) {
|
||||
if (waitNext) {
|
||||
if (e.code === 'Space') {
|
||||
emit('next')
|
||||
waitNext = false
|
||||
}
|
||||
return
|
||||
}
|
||||
if (inputLock) return
|
||||
inputLock = true
|
||||
let letter = e.key
|
||||
@@ -110,13 +118,23 @@ async function onTyping(e: KeyboardEvent) {
|
||||
playCorrect()
|
||||
if (settingStore.repeatCount == 100) {
|
||||
if (settingStore.repeatCustomCount <= wordRepeatCount + 1) {
|
||||
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
|
||||
if (settingStore.autoNext) {
|
||||
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
|
||||
} else {
|
||||
waitNext = true
|
||||
inputLock = false
|
||||
}
|
||||
} else {
|
||||
repeat()
|
||||
}
|
||||
} else {
|
||||
if (settingStore.repeatCount <= wordRepeatCount + 1) {
|
||||
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
|
||||
if (settingStore.autoNext) {
|
||||
setTimeout(() => emit('next'), settingStore.waitTimeForChangeWord)
|
||||
} else {
|
||||
waitNext = true
|
||||
inputLock = false
|
||||
}
|
||||
} else {
|
||||
repeat()
|
||||
}
|
||||
@@ -139,6 +157,8 @@ function del() {
|
||||
function showWord() {
|
||||
if (settingStore.allowWordTip) {
|
||||
showFullWord = true
|
||||
//如果默写情况下,看了提示也视为输入错误
|
||||
emit('wrong')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,17 +183,17 @@ defineExpose({del, showWord, hideWord, play})
|
||||
>
|
||||
<div class="translate-item" v-for="(v,i) in word.trans">
|
||||
<span>{{ v }}</span>
|
||||
<!-- <div class="volumeIcon">-->
|
||||
<!-- <Tooltip-->
|
||||
<!-- v-if="i === word.trans.length - 1"-->
|
||||
<!-- :title="`发音(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.PlayTranslatePronunciation]})`"-->
|
||||
<!-- >-->
|
||||
<!-- <VolumeIcon-->
|
||||
<!-- ref="volumeTranslateIconRef"-->
|
||||
<!-- :simple="true"-->
|
||||
<!-- :cb="()=>ttsPlayAudio(word.trans.join(';'))"/>-->
|
||||
<!-- </Tooltip>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="volumeIcon">-->
|
||||
<!-- <Tooltip-->
|
||||
<!-- v-if="i === word.trans.length - 1"-->
|
||||
<!-- :title="`发音(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.PlayTranslatePronunciation]})`"-->
|
||||
<!-- >-->
|
||||
<!-- <VolumeIcon-->
|
||||
<!-- ref="volumeTranslateIconRef"-->
|
||||
<!-- :simple="true"-->
|
||||
<!-- :cb="()=>ttsPlayAudio(word.trans.join(';'))"/>-->
|
||||
<!-- </Tooltip>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="word-wrapper">
|
||||
@@ -185,10 +205,10 @@ defineExpose({del, showWord, hideWord, play})
|
||||
<span class="wrong" v-if="wrong">{{ wrong }}</span>
|
||||
<template v-if="settingStore.dictation">
|
||||
<span class="letter" v-if="!showFullWord"
|
||||
@mouseenter="settingStore.allowWordTip && (showFullWord = true)">{{
|
||||
displayWord.split('').map(() => '_').join('')
|
||||
@mouseenter="showWord">{{
|
||||
displayWord.split('').map(() => settingStore.dictationShowWordLength ? '_' : ' ').join('')
|
||||
}}</span>
|
||||
<span class="letter" v-else @mouseleave="showFullWord = false">{{ displayWord }}</span>
|
||||
<span class="letter" v-else @mouseleave="hideWord">{{ displayWord }}</span>
|
||||
</template>
|
||||
<span class="letter" v-else>{{ displayWord }}</span>
|
||||
</div>
|
||||
@@ -198,7 +218,7 @@ defineExpose({del, showWord, hideWord, play})
|
||||
<VolumeIcon ref="volumeIconRef" :simple="true" :cb="() => playWordAudio(word.name)"/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="phonetic" v-if="settingStore.wordSoundType === 'us' && word.usphone">[{{ word.usphone}}]</div>
|
||||
<div class="phonetic" v-if="settingStore.wordSoundType === 'us' && word.usphone">[{{ word.usphone }}]</div>
|
||||
<div class="phonetic" v-if="settingStore.wordSoundType === 'uk' && word.ukphone">[{{ word.ukphone }}]</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, onUnmounted, watch} from "vue"
|
||||
import {$computed, $ref} from "vue/macros"
|
||||
import {useBaseStore} from "@/stores/base.ts"
|
||||
import {DefaultDisplayStatistics, DictType, ShortcutKey, Sort, Word} from "../../../types.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts"
|
||||
import {cloneDeep, reverse, shuffle} from "lodash-es"
|
||||
import {usePracticeStore} from "@/stores/practice.ts"
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useOnKeyboardEventListener, useWindowClick} from "@/hooks/event.ts";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import { onMounted, onUnmounted, watch } from "vue"
|
||||
import { $computed, $ref } from "vue/macros"
|
||||
import { useBaseStore } from "@/stores/base.ts"
|
||||
import { DefaultDisplayStatistics, DictType, ShortcutKey, Sort, Word } from "../../../types.ts";
|
||||
import { emitter, EventKey } from "@/utils/eventBus.ts"
|
||||
import { cloneDeep, reverse, shuffle } from "lodash-es"
|
||||
import { usePracticeStore } from "@/stores/practice.ts"
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import { useOnKeyboardEventListener, useWindowClick } from "@/hooks/event.ts";
|
||||
import { Icon } from "@iconify/vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
import Options from "@/pages/practice/Options.vue";
|
||||
import Typing from "@/pages/practice/practice-word/Typing.vue";
|
||||
import Panel from "@/pages/practice/Panel.vue";
|
||||
import IconWrapper from "@/components/IconWrapper.vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {syncMyDictList, useWordOptions} from "@/hooks/dict.ts";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
import { syncMyDictList, useWordOptions } from "@/hooks/dict.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import WordList from "@/components/list/WordList.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
@@ -99,7 +99,6 @@ const nextWord: Word = $computed(() => {
|
||||
|
||||
function next(isTyping: boolean = true) {
|
||||
if (data.index === data.words.length - 1) {
|
||||
|
||||
//复制当前错词,因为第一遍错词是最多的,后续的练习都是从错词中练习
|
||||
if (stat.total === -1) {
|
||||
let now = Date.now()
|
||||
@@ -140,8 +139,7 @@ function next(isTyping: boolean = true) {
|
||||
data.index++
|
||||
isTyping && practiceStore.inputWordNumber++
|
||||
console.log('这个词完了')
|
||||
if ([DictType.word].includes(store.currentDict.type)
|
||||
&& store.skipWordNames.includes(word.name.toLowerCase())) {
|
||||
if (store.skipWordNames.includes(word.name.toLowerCase())) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,100 +9,100 @@ import {SAVE_DICT_KEY, SAVE_SETTING_KEY} from "@/utils/const.ts";
|
||||
import {checkAndUpgradeSaveDict} from "@/utils";
|
||||
|
||||
export interface BaseState {
|
||||
myDictList: Dict[],
|
||||
collectDictIds: string[],
|
||||
current: {
|
||||
index: number,
|
||||
practiceType: DictType,//练习类型,目前仅词典为collect时判断是练单词还是文章使用
|
||||
},
|
||||
simpleWords: string[],
|
||||
load: boolean
|
||||
myDictList: Dict[],
|
||||
collectDictIds: string[],
|
||||
current: {
|
||||
index: number,
|
||||
practiceType: DictType,//练习类型,目前仅词典为collect时判断是练单词还是文章使用
|
||||
},
|
||||
simpleWords: string[],
|
||||
load: boolean
|
||||
}
|
||||
|
||||
export const DefaultBaseState = (): BaseState => ({
|
||||
myDictList: [
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'collect',
|
||||
name: '收藏',
|
||||
type: DictType.collect,
|
||||
category: '自带字典',
|
||||
tags: ['自带'],
|
||||
isCustom: true,
|
||||
},
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'skip',
|
||||
name: '简单词',
|
||||
type: DictType.simple,
|
||||
category: '自带字典',
|
||||
isCustom: true,
|
||||
},
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'wrong',
|
||||
name: '错词本',
|
||||
type: DictType.wrong,
|
||||
category: '自带字典',
|
||||
isCustom: true,
|
||||
},
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'cet4',
|
||||
name: 'CET-4',
|
||||
description: '大学英语四级词库',
|
||||
category: '中国考试',
|
||||
tags: ['大学英语'],
|
||||
url: 'CET4_T.json',
|
||||
length: 2607,
|
||||
translateLanguage: 'common',
|
||||
language: 'en',
|
||||
type: DictType.word
|
||||
},
|
||||
// {
|
||||
// ...cloneDeep(DefaultDict),
|
||||
// id: 'article_nce2',
|
||||
// name: "新概念英语2-课文",
|
||||
// description: '新概念英语2-课文',
|
||||
// category: '英语学习',
|
||||
// tags: ['新概念英语'],
|
||||
// url: 'NCE_2.json',
|
||||
// translateLanguage: 'common',
|
||||
// language: 'en',
|
||||
// type: DictType.article,
|
||||
// resourceId: 'article_nce2',
|
||||
// length: 96
|
||||
// },
|
||||
// {
|
||||
// ...cloneDeep(DefaultDict),
|
||||
// id: 'nce-new-2',
|
||||
// name: '新概念英语(新版)-2',
|
||||
// description: '新概念英语新版第二册',
|
||||
// category: '青少年英语',
|
||||
// tags: ['新概念英语'],
|
||||
// url: 'nce-new-2.json',
|
||||
// translateLanguage: 'common',
|
||||
// language: 'en',
|
||||
// type: DictType.word,
|
||||
// resourceId: 'nce-new-2',
|
||||
// length: 862
|
||||
// },
|
||||
],
|
||||
collectDictIds: [],
|
||||
current: {
|
||||
index: 3,
|
||||
// dictType: DictType.article,
|
||||
// index: 0,
|
||||
practiceType: DictType.word,
|
||||
myDictList: [
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'collect',
|
||||
name: '收藏',
|
||||
type: DictType.collect,
|
||||
category: '自带字典',
|
||||
tags: ['自带'],
|
||||
isCustom: true,
|
||||
},
|
||||
simpleWords: [
|
||||
'a', 'an',
|
||||
'i', 'my', 'you', 'your', 'me', 'it',
|
||||
'what', 'who', 'where', 'how', 'when', 'which',
|
||||
'be', 'am', 'is', 'do', 'are', 'did', 'were', 'was', 'can', 'could', 'will', 'would',
|
||||
'the', 'that', 'this', 'to', 'of', 'for', 'and', 'at', 'not', 'no', 'yes',
|
||||
],
|
||||
load: false
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'skip',
|
||||
name: '简单词',
|
||||
type: DictType.simple,
|
||||
category: '自带字典',
|
||||
isCustom: true,
|
||||
},
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'wrong',
|
||||
name: '错词本',
|
||||
type: DictType.wrong,
|
||||
category: '自带字典',
|
||||
isCustom: true,
|
||||
},
|
||||
{
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'cet4',
|
||||
name: 'CET-4',
|
||||
description: '大学英语四级词库',
|
||||
category: '中国考试',
|
||||
tags: ['大学英语'],
|
||||
url: 'CET4_T.json',
|
||||
length: 2607,
|
||||
translateLanguage: 'common',
|
||||
language: 'en',
|
||||
type: DictType.word
|
||||
},
|
||||
// {
|
||||
// ...cloneDeep(DefaultDict),
|
||||
// id: 'article_nce2',
|
||||
// name: "新概念英语2-课文",
|
||||
// description: '新概念英语2-课文',
|
||||
// category: '英语学习',
|
||||
// tags: ['新概念英语'],
|
||||
// url: 'NCE_2.json',
|
||||
// translateLanguage: 'common',
|
||||
// language: 'en',
|
||||
// type: DictType.article,
|
||||
// resourceId: 'article_nce2',
|
||||
// length: 96
|
||||
// },
|
||||
// {
|
||||
// ...cloneDeep(DefaultDict),
|
||||
// id: 'nce-new-2',
|
||||
// name: '新概念英语(新版)-2',
|
||||
// description: '新概念英语新版第二册',
|
||||
// category: '青少年英语',
|
||||
// tags: ['新概念英语'],
|
||||
// url: 'nce-new-2.json',
|
||||
// translateLanguage: 'common',
|
||||
// language: 'en',
|
||||
// type: DictType.word,
|
||||
// resourceId: 'nce-new-2',
|
||||
// length: 862
|
||||
// },
|
||||
],
|
||||
collectDictIds: [],
|
||||
current: {
|
||||
index: 3,
|
||||
// dictType: DictType.article,
|
||||
// index: 0,
|
||||
practiceType: DictType.word,
|
||||
},
|
||||
simpleWords: [
|
||||
'a', 'an',
|
||||
'i', 'my', 'you', 'your', 'me', 'it',
|
||||
'what', 'who', 'where', 'how', 'when', 'which',
|
||||
'be', 'am', 'is', 'do', 'are', 'did', 'were', 'was', 'can', 'could', 'will', 'would',
|
||||
'the', 'that', 'this', 'to', 'of', 'for', 'and', 'at', 'not', 'no', 'yes',
|
||||
],
|
||||
load: false
|
||||
})
|
||||
|
||||
// words: [
|
||||
@@ -151,206 +151,206 @@ export const DefaultBaseState = (): BaseState => ({
|
||||
// ],
|
||||
|
||||
export const useBaseStore = defineStore('base', {
|
||||
state: (): BaseState => {
|
||||
return DefaultBaseState()
|
||||
state: (): BaseState => {
|
||||
return DefaultBaseState()
|
||||
},
|
||||
getters: {
|
||||
collect(): Dict {
|
||||
return this.myDictList[0]
|
||||
},
|
||||
getters: {
|
||||
collect(): Dict {
|
||||
return this.myDictList[0]
|
||||
},
|
||||
simple(): Dict {
|
||||
return this.myDictList[1]
|
||||
},
|
||||
wrong(): Dict {
|
||||
return this.myDictList[2]
|
||||
},
|
||||
skipWordNames() {
|
||||
return this.simple.originWords.map(v => v.name.toLowerCase())
|
||||
},
|
||||
skipWordNamesWithSimpleWords() {
|
||||
return this.simple.originWords.map(v => v.name.toLowerCase()).concat(this.simpleWords)
|
||||
},
|
||||
isArticle(state: BaseState): boolean {
|
||||
//如果是收藏时,特殊判断
|
||||
if (this.currentDict.type === DictType.collect) {
|
||||
return state.current.practiceType === DictType.article
|
||||
}
|
||||
return [
|
||||
DictType.article,
|
||||
].includes(this.currentDict.type)
|
||||
},
|
||||
currentDict(): Dict {
|
||||
return this.myDictList[this.current.index]
|
||||
},
|
||||
chapter(state: BaseState): Word[] {
|
||||
return this.currentDict.chapterWords[this.currentDict.chapterIndex] ?? []
|
||||
},
|
||||
chapterName(state: BaseState) {
|
||||
let title = ''
|
||||
switch (this.currentDict.type) {
|
||||
case DictType.collect:
|
||||
if (state.current.practiceType === DictType.article) {
|
||||
return `第${this.currentDict.chapterIndex + 1}章`
|
||||
}
|
||||
case DictType.wrong:
|
||||
case DictType.simple:
|
||||
return this.currentDict.name
|
||||
case DictType.word:
|
||||
return `第${this.currentDict.chapterIndex + 1}章`
|
||||
}
|
||||
return title
|
||||
simple(): Dict {
|
||||
return this.myDictList[1]
|
||||
},
|
||||
wrong(): Dict {
|
||||
return this.myDictList[2]
|
||||
},
|
||||
skipWordNames() {
|
||||
return this.simple.originWords.map(v => v.name.toLowerCase())
|
||||
},
|
||||
skipWordNamesWithSimpleWords() {
|
||||
return this.simple.originWords.map(v => v.name.toLowerCase()).concat(this.simpleWords)
|
||||
},
|
||||
isArticle(state: BaseState): boolean {
|
||||
//如果是收藏时,特殊判断
|
||||
if (this.currentDict.type === DictType.collect) {
|
||||
return state.current.practiceType === DictType.article
|
||||
}
|
||||
return [
|
||||
DictType.article,
|
||||
].includes(this.currentDict.type)
|
||||
},
|
||||
currentDict(): Dict {
|
||||
return this.myDictList[this.current.index]
|
||||
},
|
||||
chapter(state: BaseState): Word[] {
|
||||
return this.currentDict.chapterWords[this.currentDict.chapterIndex] ?? []
|
||||
},
|
||||
chapterName(state: BaseState) {
|
||||
let title = ''
|
||||
switch (this.currentDict.type) {
|
||||
case DictType.collect:
|
||||
if (state.current.practiceType === DictType.article) {
|
||||
return `第${this.currentDict.chapterIndex + 1}章`
|
||||
}
|
||||
case DictType.wrong:
|
||||
case DictType.simple:
|
||||
return this.currentDict.name
|
||||
case DictType.word:
|
||||
return `第${this.currentDict.chapterIndex + 1}章`
|
||||
}
|
||||
return title
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
//这样不会丢失watch的值的引用
|
||||
merge(this, obj)
|
||||
},
|
||||
async init(outData?: any) {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
if (outData) {
|
||||
this.setState(outData)
|
||||
} else {
|
||||
let configStr: string = await localforage.getItem(SAVE_DICT_KEY.key)
|
||||
let data = checkAndUpgradeSaveDict(configStr)
|
||||
this.setState(data)
|
||||
}
|
||||
localforage.setItem(SAVE_DICT_KEY.key, JSON.stringify({val: this.$state, version: SAVE_DICT_KEY.version}))
|
||||
} catch (e) {
|
||||
console.error('读取本地dict数据失败', e)
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
//这样不会丢失watch的值的引用
|
||||
merge(this, obj)
|
||||
},
|
||||
async init(outData?: any) {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
if (outData) {
|
||||
this.setState(outData)
|
||||
} else {
|
||||
let configStr: string = await localforage.getItem(SAVE_DICT_KEY.key)
|
||||
let data = checkAndUpgradeSaveDict(configStr)
|
||||
this.setState(data)
|
||||
}
|
||||
localforage.setItem(SAVE_DICT_KEY.key, JSON.stringify({val: this.$state, version: SAVE_DICT_KEY.version}))
|
||||
} catch (e) {
|
||||
console.error('读取本地dict数据失败', e)
|
||||
}
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
|
||||
if (location.href.includes('?mode=article')) {
|
||||
console.log('文章')
|
||||
let dict = {
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'article_nce2',
|
||||
name: "新概念英语2-课文",
|
||||
description: '新概念英语2-课文',
|
||||
category: '英语学习',
|
||||
tags: ['新概念英语'],
|
||||
url: 'NCE_2.json',
|
||||
translateLanguage: 'common',
|
||||
language: 'en',
|
||||
type: DictType.article,
|
||||
resourceId: 'article_nce2',
|
||||
length: 96
|
||||
}
|
||||
let rIndex = this.myDictList.findIndex((v: Dict) => v.id === dict.id)
|
||||
if (rIndex > -1) {
|
||||
this.myDictList[rIndex] = dict
|
||||
this.current.index = rIndex
|
||||
} else {
|
||||
this.myDictList.push(cloneDeep(dict))
|
||||
this.current.index = this.myDictList.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
if (this.current.index < 3) {
|
||||
store.currentDict.words = cloneDeep(n)
|
||||
store.currentDict.chapterWords = [store.currentDict.words]
|
||||
} else {
|
||||
//自定义的词典,文章只删除了sections,单词并未做删除,所以这里不需要处理
|
||||
if (this.currentDict.isCustom) {
|
||||
|
||||
} else {
|
||||
//处理非自定义的情况。
|
||||
let dictResourceUrl = `./dicts/${this.currentDict.language}/${this.currentDict.type}/${this.currentDict.translateLanguage}/${this.currentDict.url}`;
|
||||
if ([DictType.word].includes(this.currentDict.type)) {
|
||||
if (!this.currentDict.originWords.length) {
|
||||
let r = await fetch(dictResourceUrl)
|
||||
let v = await r.json()
|
||||
v.map(s => {
|
||||
s.id = nanoid(6)
|
||||
})
|
||||
if (this.currentDict.translateLanguage === 'common') {
|
||||
let r2 = await fetch('./translate/en2zh_CN-min.json')
|
||||
// fetch('http://sc.ttentau.top/en2zh_CN-min.json').then(r2 => {
|
||||
let list: Word[] = await r2.json()
|
||||
if (list && list.length) {
|
||||
runtimeStore.translateWordList = list
|
||||
}
|
||||
}
|
||||
this.currentDict.originWords = cloneDeep(v)
|
||||
this.currentDict.words = cloneDeep(v)
|
||||
this.currentDict.chapterWords = chunk(this.currentDict.words, this.currentDict.chapterWordNumber)
|
||||
}
|
||||
}
|
||||
|
||||
if ([DictType.article].includes(this.currentDict.type)) {
|
||||
if (!this.currentDict.articles.length) {
|
||||
let r = await fetch(dictResourceUrl)
|
||||
let s: any[] = await r.json()
|
||||
this.currentDict.articles = cloneDeep(s.map(v => {
|
||||
v.id = nanoid(6)
|
||||
return v
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO 先这样,默认加载
|
||||
if (!runtimeStore.translateWordList.length) {
|
||||
setTimeout(async () => {
|
||||
let r2 = await fetch('./translate/en2zh_CN-min.json')
|
||||
// fetch('http://sc.ttentau.top/en2zh_CN-min.json').then(r2 => {
|
||||
let list: Word[] = await r2.json()
|
||||
if (list && list.length) {
|
||||
runtimeStore.translateWordList = list
|
||||
}
|
||||
})
|
||||
}
|
||||
emitter.emit(EventKey.changeDict)
|
||||
resolve(true)
|
||||
})
|
||||
},
|
||||
saveStatistics(statistics: DisplayStatistics) {
|
||||
if (statistics.spend > 1000 * 10) {
|
||||
delete statistics.wrongWords
|
||||
this.currentDict.statistics.push(statistics)
|
||||
}
|
||||
},
|
||||
async changeDict(dict: Dict, practiceType?: DictType, chapterIndex?: number, wordIndex?: number) {
|
||||
//TODO 保存统计
|
||||
// this.saveStatistics()
|
||||
console.log('changeDict', cloneDeep(dict), chapterIndex, wordIndex)
|
||||
if (chapterIndex === undefined) chapterIndex = dict.chapterIndex
|
||||
if (wordIndex === undefined) wordIndex = dict.wordIndex
|
||||
if (practiceType === undefined) this.current.practiceType = practiceType
|
||||
if ([DictType.collect,
|
||||
DictType.simple,
|
||||
DictType.wrong].includes(dict.type)) {
|
||||
dict.chapterIndex = 0
|
||||
dict.wordIndex = wordIndex
|
||||
dict.chapterWordNumber = dict.words.length
|
||||
dict.chapterWords = [dict.words]
|
||||
} else {
|
||||
if (dict.type === DictType.article) {
|
||||
if (chapterIndex > dict.articles.length) {
|
||||
dict.chapterIndex = 0
|
||||
dict.wordIndex = 0
|
||||
}
|
||||
} else {
|
||||
if (chapterIndex > dict.chapterWords.length) {
|
||||
dict.chapterIndex = 0
|
||||
dict.wordIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// await checkDictHasTranslate(dict)
|
||||
let rIndex = this.myDictList.findIndex((v: Dict) => v.id === dict.id)
|
||||
if (rIndex > -1) {
|
||||
this.myDictList[rIndex] = dict
|
||||
this.current.index = rIndex
|
||||
} else {
|
||||
this.myDictList.push(cloneDeep(dict))
|
||||
this.current.index = this.myDictList.length - 1
|
||||
}
|
||||
|
||||
emitter.emit(EventKey.changeDict)
|
||||
if (location.href.includes('?mode=article')) {
|
||||
console.log('文章')
|
||||
let dict = {
|
||||
...cloneDeep(DefaultDict),
|
||||
id: 'article_nce2',
|
||||
name: "新概念英语2-课文",
|
||||
description: '新概念英语2-课文',
|
||||
category: '英语学习',
|
||||
tags: ['新概念英语'],
|
||||
url: 'NCE_2.json',
|
||||
translateLanguage: 'common',
|
||||
language: 'en',
|
||||
type: DictType.article,
|
||||
resourceId: 'article_nce2',
|
||||
length: 96
|
||||
}
|
||||
let rIndex = this.myDictList.findIndex((v: Dict) => v.id === dict.id)
|
||||
if (rIndex > -1) {
|
||||
this.myDictList[rIndex] = dict
|
||||
this.current.index = rIndex
|
||||
} else {
|
||||
this.myDictList.push(cloneDeep(dict))
|
||||
this.current.index = this.myDictList.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
if (this.current.index < 3) {
|
||||
// this.currentDict.words = cloneDeep(n)
|
||||
// this.currentDict.chapterWords = [this.currentDict.words]
|
||||
} else {
|
||||
//自定义的词典,文章只删除了sections,单词并未做删除,所以这里不需要处理
|
||||
if (this.currentDict.isCustom) {
|
||||
|
||||
} else {
|
||||
//处理非自定义的情况。
|
||||
let dictResourceUrl = `./dicts/${this.currentDict.language}/${this.currentDict.type}/${this.currentDict.translateLanguage}/${this.currentDict.url}`;
|
||||
if ([DictType.word].includes(this.currentDict.type)) {
|
||||
if (!this.currentDict.originWords.length) {
|
||||
let r = await fetch(dictResourceUrl)
|
||||
let v = await r.json()
|
||||
v.map(s => {
|
||||
s.id = nanoid(6)
|
||||
})
|
||||
if (this.currentDict.translateLanguage === 'common') {
|
||||
let r2 = await fetch('./translate/en2zh_CN-min.json')
|
||||
// fetch('http://sc.ttentau.top/en2zh_CN-min.json').then(r2 => {
|
||||
let list: Word[] = await r2.json()
|
||||
if (list && list.length) {
|
||||
runtimeStore.translateWordList = list
|
||||
}
|
||||
}
|
||||
this.currentDict.originWords = cloneDeep(v)
|
||||
this.currentDict.words = cloneDeep(v)
|
||||
this.currentDict.chapterWords = chunk(this.currentDict.words, this.currentDict.chapterWordNumber)
|
||||
}
|
||||
}
|
||||
|
||||
if ([DictType.article].includes(this.currentDict.type)) {
|
||||
if (!this.currentDict.articles.length) {
|
||||
let r = await fetch(dictResourceUrl)
|
||||
let s: any[] = await r.json()
|
||||
this.currentDict.articles = cloneDeep(s.map(v => {
|
||||
v.id = nanoid(6)
|
||||
return v
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO 先这样,默认加载
|
||||
if (!runtimeStore.translateWordList.length) {
|
||||
setTimeout(async () => {
|
||||
let r2 = await fetch('./translate/en2zh_CN-min.json')
|
||||
// fetch('http://sc.ttentau.top/en2zh_CN-min.json').then(r2 => {
|
||||
let list: Word[] = await r2.json()
|
||||
if (list && list.length) {
|
||||
runtimeStore.translateWordList = list
|
||||
}
|
||||
})
|
||||
}
|
||||
emitter.emit(EventKey.changeDict)
|
||||
resolve(true)
|
||||
})
|
||||
},
|
||||
saveStatistics(statistics: DisplayStatistics) {
|
||||
if (statistics.spend > 1000 * 10) {
|
||||
delete statistics.wrongWords
|
||||
this.currentDict.statistics.push(statistics)
|
||||
}
|
||||
},
|
||||
async changeDict(dict: Dict, practiceType?: DictType, chapterIndex?: number, wordIndex?: number) {
|
||||
//TODO 保存统计
|
||||
// this.saveStatistics()
|
||||
console.log('changeDict', cloneDeep(dict), chapterIndex, wordIndex)
|
||||
if (chapterIndex === undefined) chapterIndex = dict.chapterIndex
|
||||
if (wordIndex === undefined) wordIndex = dict.wordIndex
|
||||
if (practiceType === undefined) this.current.practiceType = practiceType
|
||||
if ([DictType.collect,
|
||||
DictType.simple,
|
||||
DictType.wrong].includes(dict.type)) {
|
||||
dict.chapterIndex = 0
|
||||
dict.wordIndex = wordIndex
|
||||
dict.chapterWordNumber = dict.words.length
|
||||
dict.chapterWords = [dict.words]
|
||||
} else {
|
||||
if (dict.type === DictType.article) {
|
||||
if (chapterIndex > dict.articles.length) {
|
||||
dict.chapterIndex = 0
|
||||
dict.wordIndex = 0
|
||||
}
|
||||
} else {
|
||||
if (chapterIndex > dict.chapterWords.length) {
|
||||
dict.chapterIndex = 0
|
||||
dict.wordIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
// await checkDictHasTranslate(dict)
|
||||
let rIndex = this.myDictList.findIndex((v: Dict) => v.id === dict.id)
|
||||
if (rIndex > -1) {
|
||||
this.myDictList[rIndex] = dict
|
||||
this.current.index = rIndex
|
||||
} else {
|
||||
this.myDictList.push(cloneDeep(dict))
|
||||
this.current.index = this.myDictList.length - 1
|
||||
}
|
||||
|
||||
emitter.emit(EventKey.changeDict)
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -1,108 +1,114 @@
|
||||
import {defineStore} from "pinia"
|
||||
import {cloneDeep, merge} from "lodash-es";
|
||||
import {DefaultShortcutKeyMap} from "@/types.ts";
|
||||
import {SAVE_SETTING_KEY} from "@/utils/const.ts";
|
||||
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting} from "@/utils";
|
||||
import { defineStore } from "pinia"
|
||||
import { cloneDeep, merge } from "lodash-es";
|
||||
import { DefaultShortcutKeyMap } from "@/types.ts";
|
||||
import { SAVE_SETTING_KEY } from "@/utils/const.ts";
|
||||
import { checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting } from "@/utils";
|
||||
|
||||
export interface SettingState {
|
||||
showToolbar: boolean,
|
||||
show: boolean,
|
||||
showToolbar: boolean,
|
||||
show: boolean,
|
||||
|
||||
allSound: boolean,
|
||||
wordSound: boolean,
|
||||
wordSoundVolume: number,
|
||||
wordSoundSpeed: number,
|
||||
wordSoundType: string,
|
||||
keyboardSound: boolean,
|
||||
keyboardSoundVolume: number,
|
||||
keyboardSoundFile: string,
|
||||
translateSound: boolean,
|
||||
translateSoundVolume: number,
|
||||
effectSound: boolean,
|
||||
effectSoundVolume: number,
|
||||
repeatCount: number,
|
||||
repeatCustomCount?: number,
|
||||
dictation: boolean,
|
||||
translate: boolean,
|
||||
showNearWord: boolean
|
||||
ignoreCase: boolean
|
||||
allowWordTip: boolean
|
||||
waitTimeForChangeWord: number
|
||||
fontSize: {
|
||||
articleForeignFontSize: number,
|
||||
articleTranslateFontSize: number,
|
||||
wordForeignFontSize: number,
|
||||
wordTranslateFontSize: number,
|
||||
},
|
||||
showPanel: boolean,
|
||||
theme: string,
|
||||
collapse: boolean,
|
||||
chapterWordNumber: number,
|
||||
shortcutKeyMap: Record<string, string>,
|
||||
first: boolean
|
||||
load: boolean
|
||||
allSound: boolean,
|
||||
wordSound: boolean,
|
||||
wordSoundVolume: number,
|
||||
wordSoundSpeed: number,
|
||||
wordSoundType: string,
|
||||
keyboardSound: boolean,
|
||||
keyboardSoundVolume: number,
|
||||
keyboardSoundFile: string,
|
||||
translateSound: boolean,
|
||||
translateSoundVolume: number,
|
||||
effectSound: boolean,
|
||||
effectSoundVolume: number,
|
||||
repeatCount: number,
|
||||
repeatCustomCount?: number,
|
||||
dictation: boolean,
|
||||
translate: boolean,
|
||||
showNearWord: boolean
|
||||
ignoreCase: boolean
|
||||
allowWordTip: boolean
|
||||
waitTimeForChangeWord: number
|
||||
autoNext: boolean
|
||||
dictationShowWordLength: boolean//默写时显示单词长度,即用下划线 _ 来显示每个字符
|
||||
fontSize: {
|
||||
articleForeignFontSize: number,
|
||||
articleTranslateFontSize: number,
|
||||
wordForeignFontSize: number,
|
||||
wordTranslateFontSize: number,
|
||||
},
|
||||
showPanel: boolean,
|
||||
theme: string,
|
||||
collapse: boolean,
|
||||
chapterWordNumber: number,
|
||||
shortcutKeyMap: Record<string, string>,
|
||||
first: boolean
|
||||
load: boolean
|
||||
}
|
||||
|
||||
export const DefaultSettingState = (): SettingState => ({
|
||||
showToolbar: true,
|
||||
show: false,
|
||||
showPanel: true,
|
||||
showToolbar: true,
|
||||
show: false,
|
||||
showPanel: true,
|
||||
|
||||
allSound: true,
|
||||
wordSound: true,
|
||||
wordSoundVolume: 100,
|
||||
wordSoundSpeed: 1,
|
||||
wordSoundType: 'us',
|
||||
keyboardSound: true,
|
||||
keyboardSoundVolume: 100,
|
||||
keyboardSoundFile: '机械键盘2',
|
||||
translateSound: true,
|
||||
translateSoundVolume: 100,
|
||||
effectSound: true,
|
||||
effectSoundVolume: 100,
|
||||
repeatCount: 1,
|
||||
repeatCustomCount: null,
|
||||
dictation: false,
|
||||
translate: true,
|
||||
allSound: true,
|
||||
wordSound: true,
|
||||
wordSoundVolume: 100,
|
||||
wordSoundSpeed: 1,
|
||||
wordSoundType: 'us',
|
||||
keyboardSound: true,
|
||||
keyboardSoundVolume: 100,
|
||||
keyboardSoundFile: '机械键盘2',
|
||||
translateSound: true,
|
||||
translateSoundVolume: 100,
|
||||
effectSound: true,
|
||||
effectSoundVolume: 100,
|
||||
repeatCount: 1,
|
||||
repeatCustomCount: null,
|
||||
dictation: false,
|
||||
translate: true,
|
||||
|
||||
showNearWord: true,
|
||||
ignoreCase: true,
|
||||
allowWordTip: true,
|
||||
fontSize: {
|
||||
articleForeignFontSize: 48,
|
||||
articleTranslateFontSize: 20,
|
||||
wordForeignFontSize: 48,
|
||||
wordTranslateFontSize: 20,
|
||||
},
|
||||
waitTimeForChangeWord: 300,
|
||||
|
||||
theme: 'auto',
|
||||
collapse: false,
|
||||
chapterWordNumber: DefaultChapterWordNumber,
|
||||
shortcutKeyMap: cloneDeep(DefaultShortcutKeyMap),
|
||||
first: true,
|
||||
load: false
|
||||
showNearWord: true,
|
||||
ignoreCase: true,
|
||||
allowWordTip: true,
|
||||
fontSize: {
|
||||
articleForeignFontSize: 48,
|
||||
articleTranslateFontSize: 20,
|
||||
wordForeignFontSize: 48,
|
||||
wordTranslateFontSize: 20,
|
||||
},
|
||||
waitTimeForChangeWord: 300,
|
||||
autoNext: true,
|
||||
dictationShowWordLength: true,
|
||||
theme: 'auto',
|
||||
collapse: false,
|
||||
chapterWordNumber: DefaultChapterWordNumber,
|
||||
shortcutKeyMap: cloneDeep(DefaultShortcutKeyMap),
|
||||
first: true,
|
||||
load: false
|
||||
})
|
||||
export const DefaultChapterWordNumber = 30
|
||||
export const useSettingStore = defineStore('setting', {
|
||||
state: (): SettingState => {
|
||||
return DefaultSettingState()
|
||||
state: (): SettingState => {
|
||||
return DefaultSettingState()
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
//这样不会丢失watch的值的引用
|
||||
merge(this, obj)
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
//这样不会丢失watch的值的引用
|
||||
merge(this, obj)
|
||||
},
|
||||
init() {
|
||||
return new Promise(resolve => {
|
||||
let configStr = localStorage.getItem(SAVE_SETTING_KEY.key)
|
||||
if (!configStr) configStr = localStorage.getItem(SAVE_SETTING_KEY.oldKey)
|
||||
let data = checkAndUpgradeSaveSetting(configStr)
|
||||
this.setState(data)
|
||||
localStorage.setItem(SAVE_SETTING_KEY.key, JSON.stringify({val: this.$state, version: SAVE_SETTING_KEY.version}))
|
||||
this.load = true
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
init() {
|
||||
return new Promise(resolve => {
|
||||
let configStr = localStorage.getItem(SAVE_SETTING_KEY.key)
|
||||
if (!configStr) configStr = localStorage.getItem(SAVE_SETTING_KEY.oldKey)
|
||||
let data = checkAndUpgradeSaveSetting(configStr)
|
||||
this.setState(data)
|
||||
localStorage.setItem(SAVE_SETTING_KEY.key, JSON.stringify({
|
||||
val: this.$state,
|
||||
version: SAVE_SETTING_KEY.version
|
||||
}))
|
||||
this.load = true
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user