fix:move components,parse sentences using regular expressions

This commit is contained in:
zyronon
2025-09-19 23:37:02 +08:00
parent 9113d772a3
commit ff1c4f4afc
81 changed files with 337 additions and 413 deletions

39
components.d.ts vendored
View File

@@ -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']
}
}

View File

@@ -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": [],

View File

@@ -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,

View File

@@ -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,

View File

@@ -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')

View File

@@ -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>;

View File

@@ -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)

View File

@@ -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,

View File

@@ -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)

View File

@@ -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,

View File

@@ -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

View File

@@ -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";

View File

@@ -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<{

View File

@@ -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";

View File

@@ -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,

View File

@@ -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>[],

View File

@@ -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";

View File

@@ -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[],

View File

@@ -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)
})

View File

@@ -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');
}
/***

View File

@@ -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('没有文章可学习!')

View File

@@ -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";

View File

@@ -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">

View File

@@ -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";

View File

@@ -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()

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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";

View File

@@ -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";

View File

@@ -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>

View File

@@ -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";

View File

@@ -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>

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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[],

View File

@@ -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);

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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";

View File

@@ -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
})

View File

@@ -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(

View File

@@ -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";