fix:move components,parse sentences using regular expressions
This commit is contained in:
39
components.d.ts
vendored
39
components.d.ts
vendored
@@ -8,11 +8,28 @@ export {}
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
ArticleList: typeof import('./src/components/list/ArticleList.vue')['default']
|
||||
Audio: typeof import('./src/components/base/Audio.vue')['default']
|
||||
BackIcon: typeof import('./src/components/BackIcon.vue')['default']
|
||||
BaseButton: typeof import('./src/components/BaseButton.vue')['default']
|
||||
BaseIcon: typeof import('./src/components/BaseIcon.vue')['default']
|
||||
BaseInput: typeof import('./src/components/base/BaseInput.vue')['default']
|
||||
BaseList: typeof import('./src/components/list/BaseList.vue')['default']
|
||||
BasePage: typeof import('./src/components/BasePage.vue')['default']
|
||||
BaseTable: typeof import('./src/components/BaseTable.vue')['default']
|
||||
Book: typeof import('./src/components/Book.vue')['default']
|
||||
Checkbox: typeof import('./src/components/base/checkbox/Checkbox.vue')['default']
|
||||
Close: typeof import('./src/components/icon/Close.vue')['default']
|
||||
CollectNotice: typeof import('./src/components/CollectNotice.vue')['default']
|
||||
ConflictNotice: typeof import('./src/components/ConflictNotice.vue')['default']
|
||||
DeleteIcon: typeof import('./src/components/icon/DeleteIcon.vue')['default']
|
||||
Dialog: typeof import('./src/components/dialog/Dialog.vue')['default']
|
||||
DictGroup: typeof import('./src/components/list/DictGroup.vue')['default']
|
||||
DictList: typeof import('./src/components/list/DictList.vue')['default']
|
||||
EditAbleText: typeof import('./src/components/EditAbleText.vue')['default']
|
||||
Empty: typeof import('./src/components/Empty.vue')['default']
|
||||
Form: typeof import('./src/components/base/form/Form.vue')['default']
|
||||
FormItem: typeof import('./src/components/base/form/FormItem.vue')['default']
|
||||
IconBxVolume: typeof import('~icons/bx/volume')['default']
|
||||
IconBxVolumeFull: typeof import('~icons/bx/volume-full')['default']
|
||||
IconBxVolumeLow: typeof import('~icons/bx/volume-low')['default']
|
||||
@@ -78,10 +95,32 @@ declare module 'vue' {
|
||||
IconSimpleIconsWechat: typeof import('~icons/simple-icons/wechat')['default']
|
||||
IconSimpleIconsXiaohongshu: typeof import('~icons/simple-icons/xiaohongshu')['default']
|
||||
IconSystemUiconsImport: typeof import('~icons/system-uicons/import')['default']
|
||||
Input: typeof import('./src/components/Input.vue')['default']
|
||||
InputNumber: typeof import('./src/components/base/InputNumber.vue')['default']
|
||||
List: typeof import('./src/components/list/List.vue')['default']
|
||||
Logo: typeof import('./src/components/Logo.vue')['default']
|
||||
MiniDialog: typeof import('./src/components/dialog/MiniDialog.vue')['default']
|
||||
Option: typeof import('./src/components/base/select/Option.vue')['default']
|
||||
Pagination: typeof import('./src/components/base/Pagination.vue')['default']
|
||||
Panel: typeof import('./src/components/Panel.vue')['default']
|
||||
PopConfirm: typeof import('./src/components/PopConfirm.vue')['default']
|
||||
PracticeLayout: typeof import('./src/components/PracticeLayout.vue')['default']
|
||||
Progress: typeof import('./src/components/base/Progress.vue')['default']
|
||||
Radio: typeof import('./src/components/base/radio/Radio.vue')['default']
|
||||
RadioGroup: typeof import('./src/components/base/radio/RadioGroup.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
Select: typeof import('./src/components/base/select/Select.vue')['default']
|
||||
Slide: typeof import('./src/components/Slide.vue')['default']
|
||||
SlideHorizontal: typeof import('./src/components/slide/SlideHorizontal.vue')['default']
|
||||
SlideItem: typeof import('./src/components/slide/SlideItem.vue')['default']
|
||||
Slider: typeof import('./src/components/base/Slider.vue')['default']
|
||||
Switch: typeof import('./src/components/base/Switch.vue')['default']
|
||||
Textarea: typeof import('./src/components/base/Textarea.vue')['default']
|
||||
Toast: typeof import('./src/components/base/toast/Toast.vue')['default']
|
||||
Tooltip: typeof import('./src/components/base/Tooltip.vue')['default']
|
||||
VolumeIcon: typeof import('./src/components/icon/VolumeIcon.vue')['default']
|
||||
WordItem: typeof import('./src/components/WordItem.vue')['default']
|
||||
WordList: typeof import('./src/components/list/WordList.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,7 +878,7 @@
|
||||
"id": "O18euT",
|
||||
"title": "A clear conscience",
|
||||
"titleTranslate": "问心无愧",
|
||||
"text": "The whole village soon learnt that a large sum of money had been lost. \nSam Benton, the local butcher, had lost his wallet while taking his savings to the post office. \nSam was sure that the wallet must have been found by one of the villagers, \nbut it was not returned to him. \nThree months passed, and then one morning, Sam found his wallet outside his front door. \nIt had been wrapped up in newspaper and it contained half the money he had lost, together with a note which said:A thief, yes, but only 50 per cent a thief! \nTwo months later, some more money was sent to Sam with another note:Only 25 per cent a thief now! \nIn time, all Sams money was paid back in this way. \nThe last note said:I am 100 per cent honest now!",
|
||||
"text": "The whole village soon learnt that a large sum of money had been lost. \nSam Benton, the local butcher, had lost his wallet while taking his savings to the post office. \nSam was sure that the wallet must have been found by one of the villagers, \nbut it was not returned to him. \nThree months passed, and then one morning, Sam found his wallet outside his front door. \nIt had been wrapped up in newspaper and it contained half the money he had lost, together with a note which said: A thief, yes, but only 50 per cent a thief! \nTwo months later, some more money was sent to Sam with another note:Only 25 per cent a thief now! \nIn time, all Sams money was paid back in this way. \nThe last note said: I am 100 per cent honest now!",
|
||||
"textTranslate": "整个村子很快知道,有一大笔钱丢失了。 \n当地的屠户萨姆.本顿在把存款送往邮局的途中把钱包丢了。 \n萨姆确信那钱包一定是被某个村民捡到了, \n可是却不见有人来送还给他。 \n3个月过去了,后来在一天早晨,萨姆在自己的大门外发现了他的钱包。 \n钱包是用报纸包着的,里面有他丢失的钱的一半,而且还附着一张纸条,上面写着:“一个小偷,是的,但只是一个50%的小偷!” \n又过了两个月,又有一些钱送还给了萨姆,又附了一张字条:“这回只是25%的小偷了!” \n很快,萨姆全部的钱都用同样的方式还了回来。 \n最后的那张字条上写道:“我现在是一个100%的诚实人了!”",
|
||||
"newWords": [],
|
||||
"textAllWords": [],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
interface IProps {
|
||||
keyboard?: string,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
defineProps<{
|
||||
title?: string,
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
import {nextTick, useSlots} from "vue";
|
||||
import {Sort} from "@/types/types.ts";
|
||||
import MiniDialog from "@/pages/pc/components/dialog/MiniDialog.vue";
|
||||
import MiniDialog from "@/components/dialog/MiniDialog.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {cloneDeep, debounce, reverse, shuffle} from "@/utils";
|
||||
import Input from "@/pages/pc/components/Input.vue";
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import Input from "@/components/Input.vue";
|
||||
import PopConfirm from "@/components/PopConfirm.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import Pagination from '@/pages/pc/components/base/Pagination.vue'
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Checkbox from "@/pages/pc/components/base/checkbox/Checkbox.vue";
|
||||
import Pagination from '@/components/base/Pagination.vue'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import Checkbox from "@/components/base/checkbox/Checkbox.vue";
|
||||
import DeleteIcon from "@/components/icon/DeleteIcon.vue";
|
||||
import Dialog from "@/pages/pc/components/dialog/Dialog.vue";
|
||||
import Dialog from "@/components/dialog/Dialog.vue";
|
||||
|
||||
let list = defineModel('list')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import {Dict} from "@/types/types.ts";
|
||||
import Progress from '@/pages/pc/components/base/Progress.vue'
|
||||
import Checkbox from "@/pages/pc/components/base/checkbox/Checkbox.vue";
|
||||
import Progress from '@/components/base/Progress.vue'
|
||||
import Checkbox from "@/components/base/checkbox/Checkbox.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
item?: Partial<Dict>;
|
||||
@@ -3,7 +3,7 @@
|
||||
import {defineAsyncComponent, onMounted, watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
let settingStore = useSettingStore()
|
||||
let show = $ref(false)
|
||||
@@ -3,8 +3,8 @@
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
|
||||
import {watchEffect} from "vue";
|
||||
import Textarea from "@/pages/pc/components/base/Textarea.vue";
|
||||
import Toast from "@/pages/pc/components/base/toast/Toast.ts";
|
||||
import Textarea from "@/components/base/Textarea.vue";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
|
||||
interface IProps {
|
||||
value: string,
|
||||
@@ -3,7 +3,7 @@ import {computed, provide} from "vue"
|
||||
import {ShortcutKey} from "@/types/types.ts"
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Close from "@/components/icon/Close.vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
const settingStore = useSettingStore()
|
||||
let tabIndex = $ref(0)
|
||||
@@ -3,7 +3,7 @@
|
||||
import {Word} from "@/types/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
item: Word,
|
||||
@@ -1,6 +1,6 @@
|
||||
import {createVNode, render} from 'vue'
|
||||
import ToastComponent from '@/pages/pc/components/base/toast/Toast.vue'
|
||||
import type {ToastOptions, ToastInstance, ToastService} from '@/pages/pc/components/base/toast/type.ts'
|
||||
import ToastComponent from '@/components/base/toast/Toast.vue'
|
||||
import type {ToastOptions, ToastInstance, ToastService} from '@/components/base/toast/type.ts'
|
||||
|
||||
interface ToastContainer {
|
||||
id: string
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {onMounted, onUnmounted, watch} from "vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import {useEventListener} from "@/hooks/event.ts";
|
||||
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
defineEmits(['click'])
|
||||
defineProps<{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Input from "@/pages/pc/components/Input.vue";
|
||||
import Input from "@/components/Input.vue";
|
||||
import {Article} from "@/types/types.ts";
|
||||
import BaseList from "@/pages/pc/components/list/BaseList.vue";
|
||||
import BaseList from "@/components/list/BaseList.vue";
|
||||
import * as sea from "node:sea";
|
||||
import {watch, watchEffect} from "vue";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import {watch} from "vue";
|
||||
import {DictResource} from "@/types/types.ts";
|
||||
import DictList from "@/pages/pc/components/list/DictList.vue";
|
||||
import DictList from "@/components/list/DictList.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
category: string,
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {Dict} from "@/types/types.ts";
|
||||
import Book from "@/pages/pc/components/Book.vue";
|
||||
import Book from "@/components/Book.vue";
|
||||
|
||||
defineProps<{
|
||||
list?: Partial<Dict>[],
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts" generic="T extends {id:string}">
|
||||
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Input from "@/pages/pc/components/Input.vue";
|
||||
import Input from "@/components/Input.vue";
|
||||
import {cloneDeep, throttle} from "@/utils";
|
||||
import {Article} from "@/types/types.ts";
|
||||
import DeleteIcon from "@/components/icon/DeleteIcon.vue";
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import {Word} from "@/types/types.ts";
|
||||
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
|
||||
import BaseList from "@/pages/pc/components/list/BaseList.vue";
|
||||
import BaseList from "@/components/list/BaseList.vue";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
list: Word[],
|
||||
@@ -3,8 +3,9 @@ import {cloneDeep} from "@/utils";
|
||||
import nlp from "compromise/one";
|
||||
import {usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {getSentenceAllText, getSentenceAllTranslateText} from "@/hooks/translate.ts";
|
||||
import {getDefaultArticleWord} from "@/types/func.ts";
|
||||
import {getDefaultArticleWord, getDefaultWord} from "@/types/func.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
|
||||
interface KeyboardMap {
|
||||
Period: string,
|
||||
@@ -15,14 +16,6 @@ interface KeyboardMap {
|
||||
QuoteRight: string,
|
||||
}
|
||||
|
||||
export const CnKeyboardMap: KeyboardMap = {
|
||||
Period: '。',
|
||||
Comma: ',',
|
||||
Slash: '?',
|
||||
Exclamation: '!',
|
||||
QuoteLeft: '“',
|
||||
QuoteRight: '”',
|
||||
}
|
||||
export const EnKeyboardMap: KeyboardMap = {
|
||||
Period: '.',
|
||||
Comma: ',',
|
||||
@@ -33,198 +26,108 @@ export const EnKeyboardMap: KeyboardMap = {
|
||||
}
|
||||
|
||||
|
||||
function parseSentence(sentence: string) {
|
||||
// 先统一一些常见的“智能引号” -> 直引号,避免匹配问题
|
||||
sentence = sentence
|
||||
.replace(/[\u2018\u2019\u201A\u201B]/g, "'") // 各种单引号 → '
|
||||
.replace(/[\u201C\u201D\u201E\u201F]/g, '"'); // 各种双引号 → "
|
||||
|
||||
const len = sentence.length;
|
||||
const tokens = [];
|
||||
let i = 0;
|
||||
|
||||
while (i < len) {
|
||||
const ch = sentence[i];
|
||||
|
||||
// 跳过空白(但不把空白作为 token)
|
||||
if (/\s/.test(ch)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const rest = sentence.slice(i);
|
||||
|
||||
// 1) 货币 + 数字($1,000.50 或 ¥200 或 €100.5)
|
||||
let m = rest.match(/^[\$¥€£]\d{1,3}(?:,\d{3})*(?:\.\d+)?%?/);
|
||||
if (m) {
|
||||
tokens.push({word: m[0], start: i, end: i + m[0].length, isSymbol: false});
|
||||
i += m[0].length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2) 数字/小数/百分比(100% 3.14 1,000.00)
|
||||
m = rest.match(/^\d{1,3}(?:,\d{3})*(?:\.\d+)?%?/);
|
||||
if (m) {
|
||||
tokens.push({word: m[0], start: i, end: i + m[0].length, isSymbol: false});
|
||||
i += m[0].length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3) 带点缩写或多段缩写(U.S. U.S.A. e.g. i.e. Ph.D.)
|
||||
m = rest.match(/^[A-Za-z]+(?:\.[A-Za-z]+)+\.?/);
|
||||
if (m) {
|
||||
tokens.push({word: m[0], start: i, end: i + m[0].length, isSymbol: false});
|
||||
i += m[0].length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4) 单词(包含撇号/连字符,如 it's, o'clock, we'll, mother-in-law)
|
||||
m = rest.match(/^[A-Za-z0-9]+(?:[\'\-][A-Za-z0-9]+)*/);
|
||||
if (m) {
|
||||
tokens.push({word: m[0], start: i, end: i + m[0].length, isSymbol: false});
|
||||
i += m[0].length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 5) 其它可视符号(标点)——单字符处理(连续标点会被循环拆为单字符)
|
||||
// 包括:.,!?;:"'()-[]{}<>/\\@#%^&*~`等非单词非空白字符
|
||||
if (/[^\w\s]/.test(ch)) {
|
||||
tokens.push({word: ch, start: i, end: i + 1, isSymbol: true});
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 6) 回退方案:把当前字符当作一个 token(防止意外丢失)
|
||||
tokens.push({word: ch, start: i, end: i + 1, isSymbol: /[^\w\s]/.test(ch)});
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// 计算 nextSpace:查看当前 token 的 end 到下一个 token 的 start 之间是否含空白
|
||||
const result = tokens.map((t, idx) => {
|
||||
const next = tokens[idx + 1];
|
||||
const between = next ? sentence.slice(t.end, next.start) : sentence.slice(t.end);
|
||||
const nextSpace = /\s/.test(between);
|
||||
return getDefaultArticleWord({word: t.word, nextSpace, isSymbol: !!t.isSymbol});
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//生成文章段落数据
|
||||
export function genArticleSectionData(article: Article): number {
|
||||
let text = article.text.trim()
|
||||
|
||||
// console.log('genArticleSectionData',text)
|
||||
|
||||
let keyboardMap = EnKeyboardMap
|
||||
let sections: Sentence[][] = []
|
||||
let sectionTextList = text.split('\n\n')
|
||||
// console.log(sectionTextList);
|
||||
sectionTextList.filter(v => v).map((sectionText, i) => {
|
||||
text.split('\n\n').filter(Boolean).map((sectionText, i) => {
|
||||
let section: Sentence[] = []
|
||||
sections.push(section)
|
||||
sectionText = sectionText.trim()
|
||||
let sentenceNlpList = []
|
||||
sectionText.split('\n').map((rowSection, i) => {
|
||||
let doc = nlp(rowSection)
|
||||
let temp = {text: '', terms: []}
|
||||
doc.json().map(item => {
|
||||
temp.text += item.text
|
||||
temp.terms = temp.terms.concat(item.terms)
|
||||
})
|
||||
sentenceNlpList.push(temp)
|
||||
})
|
||||
|
||||
sentenceNlpList.map(item => {
|
||||
sectionText.trim().split('\n').filter(Boolean).map((item, i, arr) => {
|
||||
item = item.trim()
|
||||
//如果没有空格,导致修改一行一行的数据时,汇总时全没有空格了,库无法正常断句
|
||||
//所以要保证最后一个是空格,但防止用户打N个空格,就去掉再加上一个空格,只需要一个即可
|
||||
if (i < arr.length - 1) item += ' '
|
||||
let sentence: Sentence = cloneDeep({
|
||||
//他没有空格,导致修改一行一行的数据时,汇总时全没有空格了,库无法正常断句
|
||||
text: item.text + ' ',
|
||||
// text: '',
|
||||
text: item,
|
||||
translate: '',
|
||||
words: [],
|
||||
words: parseSentence(item),
|
||||
audioPosition: [0, 0],
|
||||
})
|
||||
section.push(sentence)
|
||||
|
||||
const checkQuote = (pre: string, index?: number) => {
|
||||
let nearSymbolPosition = null
|
||||
if (index === 0) {
|
||||
nearSymbolPosition = 'end'
|
||||
} else {
|
||||
//TODO 可以优化成for+break
|
||||
section.slice().reverse().map((sentenceItem, b) => {
|
||||
sentenceItem.words.slice().reverse().map((wordItem, c) => {
|
||||
if (wordItem.symbolPosition !== '' && nearSymbolPosition === null) {
|
||||
nearSymbolPosition = wordItem.symbolPosition
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let word3: ArticleWord = getDefaultArticleWord({
|
||||
word: pre,
|
||||
nextSpace: false,
|
||||
isSymbol: true,
|
||||
symbolPosition: ''
|
||||
});
|
||||
// console.log('rrr', item)
|
||||
// console.log('nearSymbolPosition', nearSymbolPosition)
|
||||
if (nearSymbolPosition === 'end' || nearSymbolPosition === null) {
|
||||
word3.symbolPosition = 'start'
|
||||
sentence.words.push(word3)
|
||||
} else {
|
||||
sentence.words[sentence.words.length - 1].nextSpace = false
|
||||
word3.symbolPosition = 'end'
|
||||
word3.nextSpace = true
|
||||
|
||||
let addCurrent = false
|
||||
sentence.words.slice().reverse().map((wordItem, c) => {
|
||||
if (wordItem.symbolPosition === 'start' && !addCurrent) {
|
||||
addCurrent = true
|
||||
}
|
||||
})
|
||||
if (addCurrent) {
|
||||
sentence.words.push(word3)
|
||||
} else {
|
||||
// 'Do you always get up so late? It'LICENSE one o'clock!' 会被断成两句
|
||||
let lastSentence = section[section.length - 2]
|
||||
lastSentence.words = lastSentence.words.concat(sentence.words)
|
||||
lastSentence.words.push(word3)
|
||||
sentence.words = []
|
||||
//这里还不能直接删除sentence,因为后面还有一个 sentence.words = sentence.words.filter(v => v.word !== 'placeholder') 的判断
|
||||
// section.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const checkSymbol = (post: string, nextSpace: boolean = true) => {
|
||||
switch (post) {
|
||||
case keyboardMap.Period:
|
||||
case keyboardMap.Comma:
|
||||
case keyboardMap.Slash:
|
||||
case keyboardMap.Exclamation:
|
||||
sentence.words[sentence.words.length - 1].nextSpace = false
|
||||
let word2 = getDefaultArticleWord({
|
||||
word: post,
|
||||
isSymbol: true,
|
||||
nextSpace
|
||||
});
|
||||
sentence.words.push(word2)
|
||||
break
|
||||
case keyboardMap.QuoteLeft:
|
||||
case ')':
|
||||
checkQuote(post)
|
||||
break
|
||||
case `.'`:
|
||||
case `!'`:
|
||||
case `?'`:
|
||||
case `,'`:
|
||||
case `*'`:
|
||||
post.split('').map(v => {
|
||||
checkSymbol(v, false)
|
||||
})
|
||||
break
|
||||
//类似于这种的“' -- ”的。需要保留空格,用了一个占位符才处理,因为每个符号都会把前面的那个字符的nextSpace改为false
|
||||
case ' ':
|
||||
// console.log('sentence', sentence)
|
||||
//遇到“The clock has stopped!' I looked at my watch.”
|
||||
//检测到stopped!' 的'时,如果前引号不在当前句,会把当前句的word合并到前一句。那么当前句的word就为空了,会报错
|
||||
//所以需要检测一下
|
||||
if (sentence.words.length) {
|
||||
sentence.words[sentence.words.length - 1].nextSpace = true
|
||||
let word3 = getDefaultArticleWord({
|
||||
word: 'placeholder',
|
||||
isSymbol: true,
|
||||
nextSpace: false,
|
||||
});
|
||||
sentence.words.push(word3)
|
||||
}
|
||||
break
|
||||
default:
|
||||
// console.log('post', post)
|
||||
//这里多半是一些奇怪的连接符之类的
|
||||
if (post.length > 1) {
|
||||
post.split('').map(v => {
|
||||
checkSymbol(v, false)
|
||||
})
|
||||
} else {
|
||||
sentence.words[sentence.words.length - 1].nextSpace = false
|
||||
let word3 = getDefaultArticleWord({
|
||||
word: post,
|
||||
isSymbol: true,
|
||||
nextSpace: false,
|
||||
});
|
||||
sentence.words.push(word3)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
item.terms.map((v, index: number) => {
|
||||
// console.log('v', v)
|
||||
if (v.text) {
|
||||
let pre: string = v.pre.trim()
|
||||
if (pre) {
|
||||
checkQuote(pre, index)
|
||||
}
|
||||
|
||||
let word = getDefaultArticleWord({word: v.text, nextSpace: true});
|
||||
sentence.words.push(word)
|
||||
|
||||
let post: string = v.post
|
||||
//判断是不是等于空,因为正常的词后面都会有个空格。这种不需要处理。
|
||||
if (post && post !== ' ') {
|
||||
checkSymbol(post.trim())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
//去除空格占位符
|
||||
sentence.words = sentence.words.filter(v => v.word !== 'placeholder')
|
||||
//如果是空的,直接去掉
|
||||
if (!sentence.words.length) {
|
||||
section.pop()
|
||||
}
|
||||
})
|
||||
|
||||
// console.log('section', section)
|
||||
})
|
||||
|
||||
sections = sections.filter(sectionItem => sectionItem.length)
|
||||
sections.map((sectionItem, a) => {
|
||||
sectionItem.map((sentenceItem, b) => {
|
||||
sentenceItem.text = sentenceItem.words.reduce((previousValue: string, currentValue) => {
|
||||
previousValue += currentValue.word + (currentValue.nextSpace ? ' ' : '')
|
||||
return previousValue
|
||||
}, '')
|
||||
})
|
||||
})
|
||||
|
||||
// console.log(sections)
|
||||
sections = sections.filter(v => v.length)
|
||||
article.sections = sections
|
||||
console.log(sections)
|
||||
|
||||
let failCount = 0
|
||||
let translateList = article.textTranslate?.split('\n\n') || []
|
||||
@@ -469,7 +372,6 @@ Its none of your business, the young man said rudely. This is a private conversa
|
||||
section.pop()
|
||||
}
|
||||
})
|
||||
|
||||
// console.log(sentenceNlpList)
|
||||
})
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ export function getSentenceAllTranslateText(article: Article) {
|
||||
}
|
||||
|
||||
export function getSentenceAllText(article: Article) {
|
||||
return article.sections.map(v => v.map(s => s.text.trim()).filter(v => v).join(' \n')).filter(v => v).join(' \n\n');
|
||||
return article.sections.map(v => v.map(s => s.text).filter(v => v).join('\n')).filter(v => v).join('\n\n');
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useRouter} from "vue-router";
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import {_getDictDataByUrl, useNav} from "@/utils";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import {_getDictDataByUrl, cloneDeep, useNav} from "@/utils";
|
||||
import {DictResource, DictType} from "@/types/types.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Book from "@/pages/pc/components/Book.vue";
|
||||
import Progress from '@/pages/pc/components/base/Progress.vue';
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Book from "@/components/Book.vue";
|
||||
import Progress from '@/components/base/Progress.vue';
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import PopConfirm from "@/components/PopConfirm.vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import {getDefaultDict} from "@/types/func.ts";
|
||||
import DeleteIcon from "@/components/icon/DeleteIcon.vue";
|
||||
import recommendBookList from "@/assets/book-list.json";
|
||||
import {genArticleSectionData} from "@/hooks/article.ts";
|
||||
|
||||
const {nav} = useNav()
|
||||
const base = useBaseStore()
|
||||
@@ -34,6 +35,9 @@ async function init() {
|
||||
}
|
||||
|
||||
function startStudy() {
|
||||
// console.log(store.sbook.articles[1])
|
||||
// genArticleSectionData(cloneDeep(store.sbook.articles[1]))
|
||||
// return
|
||||
if (base.sbook.id) {
|
||||
if (!base.sbook.articles.length) {
|
||||
return Toast.warning('没有文章可学习!')
|
||||
@@ -4,16 +4,16 @@ import BaseButton from "@/components/BaseButton.vue";
|
||||
import {_nextTick, cloneDeep, loadJsLib} from "@/utils";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
|
||||
import List from "@/pages/pc/components/list/List.vue";
|
||||
import List from "@/components/list/List.vue";
|
||||
import {useWindowClick} from "@/hooks/event.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {nanoid} from "nanoid";
|
||||
import EditArticle from "@/pages/pc/article/components/EditArticle.vue";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import EditArticle from "@/pages/article/components/EditArticle.vue";
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {getDefaultArticle} from "@/types/func.ts";
|
||||
import BackIcon from "@/pages/pc/components/BackIcon.vue";
|
||||
import MiniDialog from "@/pages/pc/components/dialog/MiniDialog.vue";
|
||||
import BackIcon from "@/components/BackIcon.vue";
|
||||
import MiniDialog from "@/components/dialog/MiniDialog.vue";
|
||||
import {onMounted} from "vue";
|
||||
import {Origin} from "@/config/ENV.ts";
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import BackIcon from "@/pages/pc/components/BackIcon.vue";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import BackIcon from "@/components/BackIcon.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import ArticleList from "@/pages/pc/components/list/ArticleList.vue";
|
||||
import ArticleList from "@/components/list/ArticleList.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {Article, Dict, DictId, DictType} from "@/types/types.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import EditBook from "@/pages/pc/article/components/EditBook.vue";
|
||||
import EditBook from "@/pages/article/components/EditBook.vue";
|
||||
import {computed, onMounted} from "vue";
|
||||
import {_dateFormat, _getDictDataByUrl, cloneDeep, msToHourMinute, total, useNav} from "@/utils";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {useArticleOptions} from "@/hooks/dict.ts";
|
||||
import {getDefaultArticle, getDefaultDict} from "@/types/func.ts";
|
||||
import Toast from "@/pages/pc/components/base/toast/Toast.ts";
|
||||
import ArticleAudio from "@/pages/pc/article/components/ArticleAudio.vue";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
import ArticleAudio from "@/pages/article/components/ArticleAudio.vue";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import book_list from "@/assets/book-list.json";
|
||||
|
||||
@@ -185,7 +185,7 @@ const totalSpend = $computed(() => {
|
||||
<div class="font-family text-base mb-4" v-if="currentPractice.length">
|
||||
<div>学习记录:{{ msToHourMinute(total(currentPractice, 'spend'))}}</div>
|
||||
<div class="item" v-for="i in currentPractice">
|
||||
{{_dateFormat(i.startDate,'YYYY-MM-DD HH-mm')}}: {{ msToHourMinute(i.spend) }}
|
||||
{{_dateFormat(i.startDate,'YYYY/MM/DD HH-mm')}}: {{ msToHourMinute(i.spend) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="en-article-family title text-xl">
|
||||
@@ -1,14 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import {useNav} from "@/utils";
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import {DictResource} from "@/types/types.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import Input from "@/pages/pc/components/Input.vue";
|
||||
import Input from "@/components/Input.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import DictList from "@/pages/pc/components/list/DictList.vue";
|
||||
import BackIcon from "@/pages/pc/components/BackIcon.vue";
|
||||
import DictList from "@/components/list/DictList.vue";
|
||||
import BackIcon from "@/components/BackIcon.vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import book_list from "@/assets/book-list.json";
|
||||
import {computed} from "vue";
|
||||
@@ -7,25 +7,25 @@ import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {Article, ArticleItem, ArticleWord, Dict, DictType, ShortcutKey, Statistics, Word} from "@/types/types.ts";
|
||||
import {useDisableEventListener, useOnKeyboardEventListener, useStartKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import useTheme from "@/hooks/theme.ts";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {_getDictDataByUrl, cloneDeep, msToHourMinute, msToMinute, total} from "@/utils";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {useArticleOptions} from "@/hooks/dict.ts";
|
||||
import {genArticleSectionData, usePlaySentenceAudio} from "@/hooks/article.ts";
|
||||
import {getDefaultArticle, getDefaultDict, getDefaultWord} from "@/types/func.ts";
|
||||
import TypingArticle from "@/pages/pc/article/components/TypingArticle.vue";
|
||||
import TypingArticle from "@/pages/article/components/TypingArticle.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Panel from "@/pages/pc/components/Panel.vue";
|
||||
import ArticleList from "@/pages/pc/components/list/ArticleList.vue";
|
||||
import EditSingleArticleModal from "@/pages/pc/article/components/EditSingleArticleModal.vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import ConflictNotice from "@/pages/pc/components/ConflictNotice.vue";
|
||||
import Panel from "@/components/Panel.vue";
|
||||
import ArticleList from "@/components/list/ArticleList.vue";
|
||||
import EditSingleArticleModal from "@/pages/article/components/EditSingleArticleModal.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import ConflictNotice from "@/components/ConflictNotice.vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import book_list from "@/assets/book-list.json";
|
||||
import PracticeLayout from "@/pages/pc/components/PracticeLayout.vue";
|
||||
import Switch from "@/pages/pc/components/base/Switch.vue";
|
||||
import Audio from "@/pages/pc/components/base/Audio.vue";
|
||||
import ArticleAudio from "@/pages/pc/article/components/ArticleAudio.vue";
|
||||
import PracticeLayout from "@/components/PracticeLayout.vue";
|
||||
import Switch from "@/components/base/Switch.vue";
|
||||
import Audio from "@/components/base/Audio.vue";
|
||||
import ArticleAudio from "@/pages/article/components/ArticleAudio.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
@@ -3,7 +3,7 @@ import {Article} from "@/types/types.ts";
|
||||
import {watch} from "vue";
|
||||
import {LOCAL_FILE_KEY} from "@/utils/const.ts";
|
||||
import {get} from "idb-keyval";
|
||||
import Audio from "@/pages/pc/components/base/Audio.vue";
|
||||
import Audio from "@/components/base/Audio.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
article: Article
|
||||
@@ -2,28 +2,28 @@
|
||||
|
||||
import {Article, Sentence, TranslateEngine} from "@/types/types.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import EditAbleText from "@/pages/pc/components/EditAbleText.vue";
|
||||
import EditAbleText from "@/components/EditAbleText.vue";
|
||||
import {getNetworkTranslate, getSentenceAllText, getSentenceAllTranslateText} from "@/hooks/translate.ts";
|
||||
import {genArticleSectionData, splitCNArticle2, splitEnArticle2, usePlaySentenceAudio} from "@/hooks/article.ts";
|
||||
import {_nextTick, _parseLRC, cloneDeep, last} from "@/utils";
|
||||
import {defineAsyncComponent, watch} from "vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import * as Comparison from "string-comparison"
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {getDefaultArticle} from "@/types/func.ts";
|
||||
import copy from "copy-to-clipboard";
|
||||
import {Option, Select} from "@/pages/pc/components/base/select";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import InputNumber from "@/pages/pc/components/base/InputNumber.vue";
|
||||
import {Option, Select} from "@/components/base/select";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import InputNumber from "@/components/base/InputNumber.vue";
|
||||
import {nanoid} from "nanoid";
|
||||
import {update} from "idb-keyval";
|
||||
import {LOCAL_FILE_KEY} from "@/utils/const.ts";
|
||||
import ArticleAudio from "@/pages/pc/article/components/ArticleAudio.vue";
|
||||
import BaseInput from "@/pages/pc/components/base/BaseInput.vue";
|
||||
import Textarea from "@/pages/pc/components/base/Textarea.vue";
|
||||
import ArticleAudio from "@/pages/article/components/ArticleAudio.vue";
|
||||
import BaseInput from "@/components/base/BaseInput.vue";
|
||||
import Textarea from "@/components/base/Textarea.vue";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
interface IProps {
|
||||
article?: Article,
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
import {Dict, DictId, DictType} from "@/types/types.ts";
|
||||
import {cloneDeep} from "@/utils";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {getDefaultDict} from "@/types/func.ts";
|
||||
import {Option, Select} from "@/pages/pc/components/base/select";
|
||||
import BaseInput from "@/pages/pc/components/base/BaseInput.vue";
|
||||
import Form from "@/pages/pc/components/base/form/Form.vue";
|
||||
import FormItem from "@/pages/pc/components/base/form/FormItem.vue";
|
||||
import {Option, Select} from "@/components/base/select";
|
||||
import BaseInput from "@/components/base/BaseInput.vue";
|
||||
import Form from "@/components/base/form/Form.vue";
|
||||
import FormItem from "@/components/base/form/FormItem.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
isAdd: boolean,
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import {Article} from "@/types/types.ts";
|
||||
import {useDisableEventListener} from "@/hooks/event.ts";
|
||||
import EditArticle from "@/pages/pc/article/components/EditArticle.vue";
|
||||
import EditArticle from "@/pages/article/components/EditArticle.vue";
|
||||
import {getDefaultArticle} from "@/types/func.ts";
|
||||
import {defineAsyncComponent} from "vue";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
interface IProps {
|
||||
article?: Article
|
||||
@@ -45,7 +45,7 @@
|
||||
<script setup lang="ts">
|
||||
import {ref, useTemplateRef} from 'vue'
|
||||
import QuestionItem from './QuestionItem.vue'
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
|
||||
interface IProps {
|
||||
questions: Array,
|
||||
@@ -10,11 +10,11 @@ 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/pc/article/components/QuestionForm.vue";
|
||||
import QuestionForm from "@/pages/article/components/QuestionForm.vue";
|
||||
import {getDefaultArticle, getDefaultWord} from "@/types/func.ts";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import TypingWord from "@/pages/pc/article/components/TypingWord.vue";
|
||||
import Space from "@/pages/pc/article/components/Space.vue";
|
||||
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 nlp from "compromise/three";
|
||||
import {nanoid} from "nanoid";
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="tsx">
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Space from "@/pages/pc/article/components/Space.vue";
|
||||
import Space from "@/pages/article/components/Space.vue";
|
||||
//引入这个编译就报错
|
||||
// import {ArticleWord} from "@/types/types.ts";
|
||||
|
||||
@@ -4,7 +4,7 @@ import BaseButton from "@/components/BaseButton.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {defineAsyncComponent} from "vue";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
let showWechatDialog = $ref(false)
|
||||
let showXhsDialog = $ref(false)
|
||||
</script>
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {ShortcutKey} from "@/types/types.ts";
|
||||
import Logo from "@/pages/pc/components/Logo.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useRouter} from "vue-router";
|
||||
import useTheme from "@/hooks/theme.ts";
|
||||
@@ -1,17 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import EditArticle from "@/pages/pc/article/components/EditArticle.vue";
|
||||
import BackIcon from "@/pages/pc/components/BackIcon.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-screen">
|
||||
<BackIcon/>
|
||||
<EditArticle class="vue"></EditArticle>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -20,17 +20,17 @@ import {useBaseStore} from "@/stores/base.ts";
|
||||
import {saveAs} from "file-saver";
|
||||
import {Origin} from "@/config/ENV.ts";
|
||||
import dayjs from "dayjs";
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import {Option, Select} from "@/pages/pc/components/base/select";
|
||||
import Switch from "@/pages/pc/components/base/Switch.vue";
|
||||
import Slider from "@/pages/pc/components/base/Slider.vue";
|
||||
import RadioGroup from "@/pages/pc/components/base/radio/RadioGroup.vue";
|
||||
import Radio from "@/pages/pc/components/base/radio/Radio.vue";
|
||||
import InputNumber from "@/pages/pc/components/base/InputNumber.vue";
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import Textarea from "@/pages/pc/components/base/Textarea.vue";
|
||||
import SettingItem from "@/pages/pc/setting/SettingItem.vue";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {Option, Select} from "@/components/base/select";
|
||||
import Switch from "@/components/base/Switch.vue";
|
||||
import Slider from "@/components/base/Slider.vue";
|
||||
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
|
||||
import Radio from "@/components/base/radio/Radio.vue";
|
||||
import InputNumber from "@/components/base/InputNumber.vue";
|
||||
import PopConfirm from "@/components/PopConfirm.vue";
|
||||
import Textarea from "@/components/base/Textarea.vue";
|
||||
import SettingItem from "@/pages/setting/SettingItem.vue";
|
||||
import {get, set} from "idb-keyval";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
<script setup lang="tsx">
|
||||
import {DictId} from "@/types/types.ts";
|
||||
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import {computed, onMounted, reactive, ref, shallowReactive} from "vue";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {_getDictDataByUrl, _nextTick, convertToWord, loadJsLib, useNav} from "@/utils";
|
||||
import {nanoid} from "nanoid";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import BaseTable from "@/pages/pc/components/BaseTable.vue";
|
||||
import WordItem from "@/pages/pc/components/WordItem.vue";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import BackIcon from "@/pages/pc/components/BackIcon.vue";
|
||||
import BaseTable from "@/components/BaseTable.vue";
|
||||
import WordItem from "@/components/WordItem.vue";
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import PopConfirm from "@/components/PopConfirm.vue";
|
||||
import BackIcon from "@/components/BackIcon.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import EditBook from "@/pages/pc/article/components/EditBook.vue";
|
||||
import EditBook from "@/pages/article/components/EditBook.vue";
|
||||
import {getDefaultDict} from "@/types/func.ts";
|
||||
import BaseInput from "@/pages/pc/components/base/BaseInput.vue";
|
||||
import Textarea from "@/pages/pc/components/base/Textarea.vue";
|
||||
import FormItem from "@/pages/pc/components/base/form/FormItem.vue";
|
||||
import Form from "@/pages/pc/components/base/form/Form.vue";
|
||||
import BaseInput from "@/components/base/BaseInput.vue";
|
||||
import Textarea from "@/components/base/Textarea.vue";
|
||||
import FormItem from "@/components/base/form/FormItem.vue";
|
||||
import Form from "@/components/base/form/Form.vue";
|
||||
import DeleteIcon from "@/components/icon/DeleteIcon.vue";
|
||||
import {getCurrentStudyWord} from "@/hooks/dict.ts";
|
||||
import PracticeSettingDialog from "@/pages/pc/word/components/PracticeSettingDialog.vue";
|
||||
import PracticeSettingDialog from "@/pages/word/components/PracticeSettingDialog.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import {Origin} from "@/config/ENV.ts";
|
||||
@@ -1,15 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import {groupBy, useNav} from "@/utils";
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import {DictResource} from "@/types/types.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import Input from "@/pages/pc/components/Input.vue";
|
||||
import Input from "@/components/Input.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import DictList from "@/pages/pc/components/list/DictList.vue";
|
||||
import BackIcon from "@/pages/pc/components/BackIcon.vue";
|
||||
import DictGroup from "@/pages/pc/components/list/DictGroup.vue";
|
||||
import DictList from "@/components/list/DictList.vue";
|
||||
import BackIcon from "@/components/BackIcon.vue";
|
||||
import DictGroup from "@/components/list/DictGroup.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useRouter} from "vue-router";
|
||||
import {computed} from "vue";
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {onMounted, provide, watch} from "vue";
|
||||
|
||||
import Statistics from "@/pages/pc/word/Statistics.vue";
|
||||
import Statistics from "@/pages/word/Statistics.vue";
|
||||
import {emitter, EventKey, useEvents} from "@/utils/eventBus.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
@@ -12,20 +12,20 @@ import useTheme from "@/hooks/theme.ts";
|
||||
import {getCurrentStudyWord, useWordOptions} from "@/hooks/dict.ts";
|
||||
import {_getDictDataByUrl, cloneDeep, shuffle} from "@/utils";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import Footer from "@/pages/pc/word/components/Footer.vue";
|
||||
import Panel from "@/pages/pc/components/Panel.vue";
|
||||
import Footer from "@/pages/word/components/Footer.vue";
|
||||
import Panel from "@/components/Panel.vue";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import WordList from "@/pages/pc/components/list/WordList.vue";
|
||||
import TypeWord from "@/pages/pc/word/components/TypeWord.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import WordList from "@/components/list/WordList.vue";
|
||||
import TypeWord from "@/pages/word/components/TypeWord.vue";
|
||||
import Empty from "@/components/Empty.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {getDefaultDict, getDefaultWord} from "@/types/func.ts";
|
||||
import ConflictNotice from "@/pages/pc/components/ConflictNotice.vue";
|
||||
import ConflictNotice from "@/components/ConflictNotice.vue";
|
||||
import dict_list from "@/assets/dict-list.json";
|
||||
import PracticeLayout from "@/pages/pc/components/PracticeLayout.vue";
|
||||
import PracticeLayout from "@/components/PracticeLayout.vue";
|
||||
|
||||
interface IProps {
|
||||
new: Word[],
|
||||
@@ -9,7 +9,7 @@ import dayjs from "dayjs";
|
||||
import isBetween from "dayjs/plugin/isBetween";
|
||||
import {defineAsyncComponent, watch} from "vue";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
dayjs.extend(isBetween);
|
||||
|
||||
@@ -3,23 +3,23 @@ import {useBaseStore} from "@/stores/base.ts";
|
||||
import {useRouter} from "vue-router";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {_getAccomplishDate, _getDictDataByUrl, useNav} from "@/utils";
|
||||
import BasePage from "@/pages/pc/components/BasePage.vue";
|
||||
import BasePage from "@/components/BasePage.vue";
|
||||
import {DictResource} from "@/types/types.ts";
|
||||
import {watch} from "vue";
|
||||
import {getCurrentStudyWord} from "@/hooks/dict.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import Book from "@/pages/pc/components/Book.vue";
|
||||
import PopConfirm from "@/pages/pc/components/PopConfirm.vue";
|
||||
import Progress from '@/pages/pc/components/base/Progress.vue';
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts';
|
||||
import Book from "@/components/Book.vue";
|
||||
import PopConfirm from "@/components/PopConfirm.vue";
|
||||
import Progress from '@/components/base/Progress.vue';
|
||||
import Toast from '@/components/base/toast/Toast.ts';
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {getDefaultDict} from "@/types/func.ts";
|
||||
import DeleteIcon from "@/components/icon/DeleteIcon.vue";
|
||||
import PracticeSettingDialog from "@/pages/pc/word/components/PracticeSettingDialog.vue";
|
||||
import ChangeLastPracticeIndexDialog from "@/pages/pc/word/components/ChangeLastPracticeIndexDialog.vue";
|
||||
import PracticeSettingDialog from "@/pages/word/components/PracticeSettingDialog.vue";
|
||||
import ChangeLastPracticeIndexDialog from "@/pages/word/components/ChangeLastPracticeIndexDialog.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import recommendDictList from "@/assets/recommend-dict-list.json";
|
||||
import CollectNotice from "@/pages/pc/components/CollectNotice.vue";
|
||||
import CollectNotice from "@/components/CollectNotice.vue";
|
||||
|
||||
|
||||
const store = useBaseStore()
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import BaseTable from "@/pages/pc/components/BaseTable.vue";
|
||||
import WordItem from "@/pages/pc/components/WordItem.vue";
|
||||
import BaseTable from "@/components/BaseTable.vue";
|
||||
import WordItem from "@/components/WordItem.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {defineAsyncComponent} from "vue";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
const model = defineModel()
|
||||
const store = useBaseStore()
|
||||
@@ -5,8 +5,8 @@ import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {ShortcutKey, StudyData} from "@/types/types.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Progress from '@/pages/pc/components/base/Progress.vue'
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import Progress from '@/components/base/Progress.vue'
|
||||
|
||||
const statisticsStore = usePracticeStore()
|
||||
const settingStore = useSettingStore()
|
||||
@@ -1,19 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {_getAccomplishDays} from "@/utils";
|
||||
import Radio from "@/pages/pc/components/base/radio/Radio.vue";
|
||||
import RadioGroup from "@/pages/pc/components/base/radio/RadioGroup.vue";
|
||||
import Radio from "@/components/base/radio/Radio.vue";
|
||||
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import Checkbox from "@/pages/pc/components/base/checkbox/Checkbox.vue";
|
||||
import Slider from "@/pages/pc/components/base/Slider.vue";
|
||||
import Checkbox from "@/components/base/checkbox/Checkbox.vue";
|
||||
import Slider from "@/components/base/Slider.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
import {defineAsyncComponent, watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import Toast from "@/pages/pc/components/base/toast/Toast.ts";
|
||||
import ChangeLastPracticeIndexDialog from "@/pages/pc/word/components/ChangeLastPracticeIndexDialog.vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
import ChangeLastPracticeIndexDialog from "@/pages/word/components/ChangeLastPracticeIndexDialog.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/pages/pc/components/dialog/Dialog.vue'))
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
const store = useBaseStore()
|
||||
const settings = useSettingStore()
|
||||
@@ -5,8 +5,8 @@ import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio, useTTsPlayAudio} from "@/hooks/sound.ts";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {nextTick, onMounted, onUnmounted, watch} from "vue";
|
||||
import Tooltip from "@/pages/pc/components/base/Tooltip.vue";
|
||||
import SentenceHightLightWord from "@/pages/pc/word/components/SentenceHightLightWord.vue";
|
||||
import Tooltip from "@/components/base/Tooltip.vue";
|
||||
import SentenceHightLightWord from "@/pages/word/components/SentenceHightLightWord.vue";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import {getDefaultWord} from "@/types/func.ts";
|
||||
import {sleep} from "@/utils";
|
||||
114
src/router.ts
114
src/router.ts
@@ -1,17 +1,16 @@
|
||||
import * as VueRouter from 'vue-router'
|
||||
import {RouteRecordRaw} from 'vue-router'
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import WordHomePage from "@/pages/pc/word/WordHomePage.vue";
|
||||
import PC from "@/pages/pc/index.vue";
|
||||
import ArticleHomePage from "@/pages/pc/article/ArticleHomePage.vue";
|
||||
import StudyArticle from "@/pages/pc/article/StudyArticle.vue";
|
||||
import DictDetail from "@/pages/pc/word/DictDetail.vue";
|
||||
import StudyWord from "@/pages/pc/word/StudyWord.vue";
|
||||
import BookDetail from "@/pages/pc/article/BookDetail.vue";
|
||||
import DictList from "@/pages/pc/word/DictList.vue";
|
||||
import BookList from "@/pages/pc/article/BookList.vue";
|
||||
import Setting from "@/pages/pc/setting/Setting.vue";
|
||||
import Home from "@/pages/pc/home/index.vue";
|
||||
import WordsPage from "@/pages/word/WordsPage.vue";
|
||||
import PC from "@/pages/index.vue";
|
||||
import ArticlesPage from "@/pages/article/ArticlesPage.vue";
|
||||
import PracticeArticles from "@/pages/article/PracticeArticles.vue";
|
||||
import DictDetail from "@/pages/word/DictDetail.vue";
|
||||
import PracticeWords from "@/pages/word/PracticeWords.vue";
|
||||
import BookDetail from "@/pages/article/BookDetail.vue";
|
||||
import DictList from "@/pages/word/DictList.vue";
|
||||
import BookList from "@/pages/article/BookList.vue";
|
||||
import Setting from "@/pages/setting/Setting.vue";
|
||||
import Home from "@/pages/home/index.vue";
|
||||
|
||||
export const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
@@ -20,25 +19,23 @@ export const routes: RouteRecordRaw[] = [
|
||||
redirect: '/',
|
||||
children: [
|
||||
{path: '/', component: Home},
|
||||
{path: 'words', component: WordHomePage},
|
||||
{path: 'words', component: WordsPage},
|
||||
{path: 'word', redirect: '/words'},
|
||||
{path: 'practice-words/:id', component: PracticeWords},
|
||||
{path: 'study-word', redirect: '/words'},
|
||||
{path: 'dict-list', component: DictList},
|
||||
{path: 'practice-words/:id', component: StudyWord},
|
||||
{path: 'study-word', redirect: '/word'},
|
||||
{path: 'dict-detail', component: DictDetail},
|
||||
|
||||
{path: 'articles', component: ArticleHomePage},
|
||||
{path: 'articles', component: ArticlesPage},
|
||||
{path: 'article', redirect: '/articles'},
|
||||
{path: 'practice-articles/:id', component: StudyArticle},
|
||||
{path: 'study-article', redirect: '/article'},
|
||||
{path: 'practice-articles/:id', component: PracticeArticles},
|
||||
{path: 'study-article', redirect: '/articles'},
|
||||
{path: 'book-detail', component: BookDetail},
|
||||
{path: 'book-list', component: BookList},
|
||||
{path: 'edit-article', component: () => import("@/pages/pc/article/EditArticlePage.vue")},
|
||||
|
||||
{path: 'setting', component: Setting},
|
||||
]
|
||||
},
|
||||
{path: '/batch-edit-article', component: () => import("@/pages/pc/article/BatchEditArticlePage.vue")},
|
||||
{path: '/batch-edit-article', component: () => import("@/pages/article/BatchEditArticlePage.vue")},
|
||||
{path: '/test', component: () => import("@/pages/test/test.vue")},
|
||||
{path: '/:pathMatch(.*)*', redirect: '/word'},
|
||||
]
|
||||
@@ -59,48 +56,47 @@ const router = VueRouter.createRouter({
|
||||
|
||||
router.beforeEach((to: any, from: any) => {
|
||||
return true
|
||||
|
||||
// console.log('beforeEach-to',to.path)
|
||||
// console.log('beforeEach-from',from.path)
|
||||
const runtimeStore = useRuntimeStore()
|
||||
|
||||
//footer下面的5个按钮,对跳不要用动画
|
||||
let noAnimation = [
|
||||
'/pc/practice',
|
||||
'/pc/dict',
|
||||
'/mobile',
|
||||
'/'
|
||||
]
|
||||
|
||||
if (noAnimation.indexOf(from.path) !== -1 && noAnimation.indexOf(to.path) !== -1) {
|
||||
return true
|
||||
}
|
||||
|
||||
const toDepth = routes.findIndex(v => v.path === to.path)
|
||||
const fromDepth = routes.findIndex(v => v.path === from.path)
|
||||
// const fromDepth = routeDeep.indexOf(from.path)
|
||||
|
||||
if (toDepth > fromDepth) {
|
||||
if (to.matched && to.matched.length) {
|
||||
let def = to.matched[0].components.default
|
||||
let toComponentName = def.name ?? def.__name
|
||||
runtimeStore.updateExcludeRoutes({type: 'remove', value: toComponentName})
|
||||
// console.log('删除', toComponentName)
|
||||
// console.log('前进')
|
||||
// console.log('删除', toComponentName)
|
||||
}
|
||||
} else {
|
||||
if (from.matched && from.matched.length) {
|
||||
let def = from.matched[0].components.default
|
||||
let fromComponentName = def.name ?? def.__name
|
||||
runtimeStore.updateExcludeRoutes({type: 'add', value: fromComponentName})
|
||||
// console.log('添加', fromComponentName)
|
||||
// console.log('后退')
|
||||
}
|
||||
}
|
||||
// const runtimeStore = useRuntimeStore()
|
||||
//
|
||||
// //footer下面的5个按钮,对跳不要用动画
|
||||
// let noAnimation = [
|
||||
// '/pc/practice',
|
||||
// '/pc/dict',
|
||||
// '/mobile',
|
||||
// '/'
|
||||
// ]
|
||||
//
|
||||
// if (noAnimation.indexOf(from.path) !== -1 && noAnimation.indexOf(to.path) !== -1) {
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// const toDepth = routes.findIndex(v => v.path === to.path)
|
||||
// const fromDepth = routes.findIndex(v => v.path === from.path)
|
||||
// // const fromDepth = routeDeep.indexOf(from.path)
|
||||
//
|
||||
// if (toDepth > fromDepth) {
|
||||
// if (to.matched && to.matched.length) {
|
||||
// let def = to.matched[0].components.default
|
||||
// let toComponentName = def.name ?? def.__name
|
||||
// runtimeStore.updateExcludeRoutes({type: 'remove', value: toComponentName})
|
||||
// // console.log('删除', toComponentName)
|
||||
// // console.log('前进')
|
||||
// // console.log('删除', toComponentName)
|
||||
// }
|
||||
// } else {
|
||||
// if (from.matched && from.matched.length) {
|
||||
// let def = from.matched[0].components.default
|
||||
// let fromComponentName = def.name ?? def.__name
|
||||
// runtimeStore.updateExcludeRoutes({type: 'add', value: fromComponentName})
|
||||
// // console.log('添加', fromComponentName)
|
||||
// // console.log('后退')
|
||||
// }
|
||||
// }
|
||||
// ...
|
||||
// 返回 false 以取消导航
|
||||
return true
|
||||
// return true
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {createVNode, render} from 'vue'
|
||||
import Dialog, {ModalProps} from "@/pages/pc/components/dialog/Dialog.vue";
|
||||
import Dialog, {ModalProps} from "@/components/dialog/Dialog.vue";
|
||||
|
||||
export class MessageBox {
|
||||
static confirm(
|
||||
|
||||
@@ -8,7 +8,7 @@ import dayjs from 'dayjs'
|
||||
import axios from "axios";
|
||||
import {env} from "@/config/ENV.ts";
|
||||
import {nextTick} from "vue";
|
||||
import Toast from '@/pages/pc/components/base/toast/Toast.ts'
|
||||
import Toast from '@/components/base/toast/Toast.ts'
|
||||
import {getDefaultArticle, getDefaultDict, getDefaultWord} from "@/types/func.ts";
|
||||
import {set} from "idb-keyval";
|
||||
import book_list from "@/assets/book-list.json";
|
||||
|
||||
Reference in New Issue
Block a user