save
This commit is contained in:
@@ -6,6 +6,7 @@ defineProps<{
|
||||
keyboard?: string,
|
||||
active?: boolean
|
||||
disabled?: boolean
|
||||
loading?: boolean
|
||||
size?: string
|
||||
}>()
|
||||
|
||||
@@ -19,14 +20,20 @@ function click() {
|
||||
<template>
|
||||
<Tooltip :disabled="!keyboard" :title="`快捷键: ${keyboard}`">
|
||||
<div class="my-button"
|
||||
@click="!disabled && $emit('click')"
|
||||
@click="(!disabled && !loading) && $emit('click')"
|
||||
:class="[
|
||||
active && 'active',
|
||||
size,
|
||||
disabled && 'disabled',
|
||||
(disabled||loading) && 'disabled',
|
||||
!disabled && 'hvr-grow'
|
||||
]">
|
||||
<span><slot></slot></span>
|
||||
<span :style="{opacity:loading?0:1}"><slot></slot></span>
|
||||
<Icon v-if="loading"
|
||||
class="loading"
|
||||
icon="eos-icons:loading"
|
||||
width="18"
|
||||
color="#ffffff"
|
||||
/>
|
||||
<div class="key-notice" v-if="keyboard">
|
||||
<Icon icon="bi:keyboard" width="14" color="#ffffff"/>
|
||||
<span class="key">{{ keyboard }}</span>
|
||||
@@ -52,6 +59,11 @@ function click() {
|
||||
//background: var(--color-second-bg);
|
||||
height: 36rem;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: .6;
|
||||
|
||||
@@ -10,39 +10,12 @@ import {
|
||||
updateLocalSentenceTranslate
|
||||
} from "@/hooks/translate.ts";
|
||||
import * as copy from "copy-to-clipboard";
|
||||
import {getSplitTranslateText, splitArticle} from "@/hooks/article.ts";
|
||||
import {getSplitTranslateText, splitEnArticle} from "@/hooks/article.ts";
|
||||
import EditAbleText from "@/components/EditAbleText.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useDisableEventListener, useEsc} from "@/hooks/event.ts";
|
||||
|
||||
let article1 = `How does the older investor differ in his approach to investment from the younger investor?
|
||||
There is no shortage of tipsters around offering 'get-rich-quick' opportunities. But if you are a serious private investor, leave the Las Vegas mentality to those with money to fritter. The serious investor needs a proper 'portfolio' -- a well-planned selection of investments, with a definite structure and a clear aim. But exactly how does a newcomer to the stock market go about achieving that?
|
||||
Well, if you go to five reputable stock brokers and ask them what you should do with your money, you're likely to get five different answers, -- even if you give all the relevant information about your age age, family, finances and what you want from your investments. Moral? There is no one 'right' way to structure a portfolio. However, there are undoubtedly some wrong ways, and you can be sure that none of our five advisers would have suggested sinking all (or perhaps any) of your money into Periwigs*.
|
||||
So what should you do? We'll assume that you have sorted out the basics -- like mortgages, pensions, insurance and access to sufficient cash reserves. You should then establish your own individual aims. These are partly a matter of personal circumstances, partly a matter of psychology.
|
||||
For instance, if you are older you have less time to recover from any major losses, and you may well wish to boost your pension income. So preserving your capital and generating extra income are your main priorities. In this case, you'd probably construct a portfolio with some shares (but not high risk ones), along with gilts, cash deposits, and perhaps convertibles or the income shares of split capital investment trusts.
|
||||
If you are younger, and in a solid financial position, you may decide to take an aggressive approach -- but only if you're blessed with a sanguine disposition and won't suffer sleepless nights over share prices. If portfolio, alongside your more pedestrian in vestments. Once you have decided on your investment aims, you can then decide where to put your money. The golden rule here is spread your risk -- if you put all of your money into Periwigs International, you're setting yourself up as a hostage to fortune.
|
||||
*'Periwigs' is the name of a fictitious company.
|
||||
INVESTOR'S CHRONICLE, March 23 1990`
|
||||
|
||||
article1 = `How does the older investor differ in his approach to investment from the younger investor?`
|
||||
article1 = `Last week I went to the theatre. I had a very good seat. The play was very interesting. I did not enjoy it. A young man and a young woman were sitting behind me. They were talking loudly. I got very angry. I could not hear the actors. I turned round. I looked at the man and the woman angrily. They did not pay any attention. In the end, I could not bear it. I turned round again. ‘I can't hear a word!’ I said angrily.
|
||||
‘It's none of your business, ’ the young man said rudely. ‘This is a private conversation!’`
|
||||
// article1 = `‘It's none of your business, ’ the young man said rudely. ‘This is a private conversation!’`
|
||||
|
||||
let article2 = `What is one of the features of modern camping where nationality is concerned?
|
||||
Economy is one powerful motive for camping, since after the initial outlay upon equipment, or through hiring it, the total expense can be far less than the cost of hotels. But, contrary to a popular assumption, it is far from being the only one, or even the greatest. The man who manoeuvres carelessly into his twenty pounds' worth of space at one of Europe's myriad permanent sites may find himself bumping a Bentley. More likely, Ford Escort will be hub to hub with Renault or Mercedes, but rarely with bicycles made for two.
|
||||
That the equipment of modern camping becomes yearly more sophisticated is an entertaining paradox for the cynic, a brighter promise for the hopeful traveler who has sworn to get away from it all. It also provides-and some student sociologist might care to base his thesis upon the phenomenon -- an escape of another kind. The modern traveller is often a man who dislikes the Splendide and the Bellavista, not because he cannot afford, or shuns their material comforts. but because he is afford of them. Affluent he may be, but he is by no means sure what to tip the doorman or the chambermaid. Master in his own house, he has little idea of when to say boo to a maitre d'hotel.
|
||||
From all such fears camping releases him. Granted, a snobbery of camping itself, based upon equipment and techniques, already exists; but it is of a kind that, if he meets it, he can readily understand and deal with. There is no superior 'they' in the shape of managements and hotel hierarchies to darken his holiday days.
|
||||
To such motives, yet another must be added. The contemporary phenomenon of car worship is to be explained not least by the sense of independence and freedom that ownership entails. To this pleasure camping gives an exquisite refinement.
|
||||
From one's own front door to home or foreign hills or sands and back again, everything is to hand. Not only are the means of arriving at the holiday paradise entirely within one's own command and keeping, but the means of escape from holiday hel (if the beach proves too crowded, the local weather too inclement) are there, outside -- or, as likely, part of -- the tent.
|
||||
Idealists have objected to the package tour, that the traveller abroad thereby denies himself the opportunity of getting to know the people of the country visited. Insularity and self-containment, it is argued, go hand in hand. The opinion does not survive experience of a popular Continental camping place. Holiday hotels tend to cater for one nationality of visitors especially, sometimes exclusively. Camping sites, by contrast, are highly cosmopolitan. Granted, a preponderance of Germans is a characteristic that seems common to most Mediterranean sites; but as yet there is no overwhelmingly specialized patronage. Notices forbidding the open-air drying of clothes, or the use of water points for car washing, or those inviting 'our camping friends' to a dance or a boat trip are printed not only in French or Italian or Spanish, but also in English, German and Dutch. At meal times the odour of sauerkraut vies with that of garlic. The Frenchman's breakfast coffee competes with the Englishman's bacon and eggs.
|
||||
Whether the remarkable growth of organized camping means the eventual death of the more independent kind is hard to say. Municipalities naturally want to secure the campers' site fees and other custom. Police are wary of itinerants who cannot be traced to a recognized camp boundary or to four walls. But most probably it will all depend upon campers themselves: how many heath fires they cause; how much litter they leave; in short, whether or not they wholly alienate landowners and those who live in the countryside. Only good scouting is likely to preserve the freedoms so dear to the heart of the eternal Boy Scout.
|
||||
NIGEL BUXTON The Great Escape from The Weekend Telegraph`
|
||||
|
||||
// article2 = `Economy is one powerful motive for camping? since after the initial outlay upon equipment, or through hiring it, the total expense can be far less than the cost of hotels. But, contrary to a popular assumption, it is far from being the only one, or even the greatest. The man who manoeuvres carelessly into his twenty pounds' worth of space at one of Europe's myriad permanent sites may find himself bumping a Bentley. More likely, Ford Escort will be hub to hub with Renault or Mercedes, but rarely with bicycles made for two.`
|
||||
|
||||
interface IProps {
|
||||
article?: Article
|
||||
}
|
||||
@@ -58,7 +31,7 @@ const TranslateEngineOptions = [
|
||||
{value: 'baidu', label: '百度'},
|
||||
{value: 'youdao', label: '有道'},
|
||||
]
|
||||
const emit = defineEmits(['close'])
|
||||
const emit = defineEmits(['close', 'save'])
|
||||
|
||||
useDisableEventListener()
|
||||
useEsc(() => {
|
||||
@@ -70,7 +43,9 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
function updateSections() {
|
||||
article.sections = splitArticle(article.article)
|
||||
let {text, sections} = splitEnArticle(article.article)
|
||||
article.article = text
|
||||
article.sections = sections
|
||||
}
|
||||
|
||||
async function startNetworkTranslate() {
|
||||
@@ -155,6 +130,46 @@ function onFocus() {
|
||||
function save() {
|
||||
console.log('article', article)
|
||||
copy(JSON.stringify(article))
|
||||
|
||||
if (!article.title.trim()) {
|
||||
return ElMessage.error('请填写标题!')
|
||||
}
|
||||
if (!article.article.trim()) {
|
||||
return ElMessage.error('请填写正文!')
|
||||
}
|
||||
|
||||
const saveTemp = ()=>{
|
||||
article.translateSplit = true
|
||||
emit('close')
|
||||
emit('save', cloneDeep(article))
|
||||
}
|
||||
|
||||
if (article.translateType === TranslateType.network) {
|
||||
if (!article.networkTranslate.trim()) {
|
||||
return ElMessageBox.confirm('您选择了“网络翻译”,但译文内容却为空白,是否修改为“不需要翻译”并保存?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
article.translateType = TranslateType.none
|
||||
saveTemp()
|
||||
}).catch(() => void 0)
|
||||
}
|
||||
}
|
||||
|
||||
if (article.translateType === TranslateType.custom) {
|
||||
if (!article.customTranslate.trim()) {
|
||||
return ElMessageBox.confirm('您选择了“本地翻译”,但译文内容却为空白,是否修改为“不需要翻译”并保存?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
article.translateType = TranslateType.none
|
||||
saveTemp()
|
||||
}).catch(() => void 0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
watch(() => article.customTranslate, (str: string) => {
|
||||
@@ -222,6 +237,7 @@ watch(() => article.translateType, () => {
|
||||
<el-radio-group v-model="article.translateType">
|
||||
<el-radio-button :label="TranslateType.custom">本地翻译</el-radio-button>
|
||||
<el-radio-button :label="TranslateType.network">网络翻译</el-radio-button>
|
||||
<el-radio-button :label="TranslateType.none">不需要翻译</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<textarea
|
||||
@@ -254,7 +270,9 @@ watch(() => article.translateType, () => {
|
||||
</el-select>
|
||||
<BaseButton
|
||||
size="small"
|
||||
@click="startNetworkTranslate">开始翻译
|
||||
@click="startNetworkTranslate"
|
||||
:loading="progress!==0 && progress !== 100"
|
||||
>开始翻译
|
||||
</BaseButton>
|
||||
|
||||
</div>
|
||||
@@ -271,7 +289,7 @@ watch(() => article.translateType, () => {
|
||||
>
|
||||
</textarea>
|
||||
<textarea
|
||||
v-else
|
||||
v-if="article.translateType === TranslateType.network"
|
||||
v-model="article.networkTranslate"
|
||||
@blur="onBlur"
|
||||
@focus="onFocus"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import {computed, nextTick, watchEffect} from "vue"
|
||||
import {$ref} from "vue/macros";
|
||||
import {Article, ArticleWord, ShortKeyMap, Word} from "@/types";
|
||||
import {Article, ArticleWord, DefaultArticle, ShortKeyMap, Word} from "@/types";
|
||||
import {useBaseStore} from "@/stores/base";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import TypeWord from "@/components/Practice/TypeWord.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {usePlayBeep, usePlayCorrect, usePlayKeyboardAudio, usePlayWordAudio} from "@/hooks/sound.ts";
|
||||
import {useEventListener, useOnKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import {cloneDeep} from "lodash-es";
|
||||
|
||||
let article1 = `How does the older investor differ in his approach to investment from the younger investor?
|
||||
There is no shortage of tipsters around offering 'get-rich-quick' opportunities. But if you are a serious private investor, leave the Las Vegas mentality to those with money to fritter. The serious investor needs a proper 'portfolio' -- a well-planned selection of investments, with a definite structure and a clear aim. But exactly how does a newcomer to the stock market go about achieving that?
|
||||
@@ -60,18 +61,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<IProps>(), {
|
||||
article: {
|
||||
"title": "",
|
||||
"titleTranslate": "",
|
||||
article: '',
|
||||
"customTranslate": "",
|
||||
networkTranslate: '',
|
||||
"isTranslated": false,
|
||||
"newWords": [],
|
||||
"articleAllWords": [],
|
||||
"sections": [],
|
||||
"translateType": 0
|
||||
},
|
||||
article: () => cloneDeep(DefaultArticle),
|
||||
sectionIndex: 0,
|
||||
sentenceIndex: 0,
|
||||
wordIndex: 0,
|
||||
@@ -149,6 +139,7 @@ const currentIndex = computed(() => {
|
||||
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
if (tabIndex !== 0) return
|
||||
if (!props.article.sections.length) return
|
||||
// console.log('keyDown', e.key, e.code, e.keyCode)
|
||||
wrong = ''
|
||||
let currentSection = props.article.sections[sectionIndex]
|
||||
|
||||
@@ -27,8 +27,10 @@ export const EnKeyboardMap: KeyboardMap = {
|
||||
QuoteRight: '"',
|
||||
}
|
||||
|
||||
|
||||
export function splitArticle(article: string, lang: string = 'en', keyboardMap: KeyboardMap = EnKeyboardMap): Sentence[][] {
|
||||
export function splitEnArticle(text: string, lang: string = 'en', keyboardMap: KeyboardMap = EnKeyboardMap): {
|
||||
sections: Sentence[][],
|
||||
text: string
|
||||
} {
|
||||
let sections: Sentence[][] = []
|
||||
let section: Sentence[] = []
|
||||
let sentence: Sentence = {
|
||||
@@ -40,17 +42,18 @@ export function splitArticle(article: string, lang: string = 'en', keyboardMap:
|
||||
sections.push(section)
|
||||
let word = cloneDeep({...DefaultArticleWord, name: '', nextSpace: true});
|
||||
//加\n用于添加最后一段
|
||||
article += '\n'
|
||||
if (lang === 'en') {
|
||||
article = article.replaceAll(`‘`, '"')
|
||||
article = article.replaceAll(`’`, '"')
|
||||
article = article.replaceAll(`“`, '"')
|
||||
article = article.replaceAll(`”`, '"')
|
||||
}
|
||||
text += '\n'
|
||||
text = text.replaceAll(`‘`, '"')
|
||||
text = text.replaceAll(`’`, '"')
|
||||
text = text.replaceAll(`“`, '"')
|
||||
text = text.replaceAll(`”`, '"')
|
||||
//替换所有单引号为双引号
|
||||
text = text.replaceAll(`'`, '"')
|
||||
//将缩写词的双引号替换回单引号
|
||||
text = text.replaceAll(`"t`, `'t`)
|
||||
text = text.replaceAll(`"s`, `'s`)
|
||||
|
||||
// console.log('articles', articles)
|
||||
|
||||
article.split('').map((v, i, arr) => {
|
||||
text.split('').map((v, i, arr) => {
|
||||
switch (v) {
|
||||
case ' ':
|
||||
if (word.name) {
|
||||
@@ -165,7 +168,10 @@ export function splitArticle(article: string, lang: string = 'en', keyboardMap:
|
||||
}, '')
|
||||
})
|
||||
})
|
||||
return sections
|
||||
return {
|
||||
text,
|
||||
sections
|
||||
}
|
||||
}
|
||||
|
||||
export function splitCNArticle(article: string, lang: string = 'cn', keyboardMap: KeyboardMap = CnKeyboardMap): Sentence[][] {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {Article, Sentence, TranslateEngine, TranslateType} from "@/types.ts";
|
||||
import Baidu from "@opentranslate/baidu";
|
||||
import {axiosInstance} from "@/utils/http.ts";
|
||||
import {getSplitTranslateText, splitArticle} from "@/hooks/article.ts";
|
||||
import {getSplitTranslateText, splitEnArticle} from "@/hooks/article.ts";
|
||||
import {Translator} from "@opentranslate/translator/src/translator.ts";
|
||||
|
||||
export function updateLocalSentenceTranslate(article: Article, translate: string) {
|
||||
@@ -191,7 +191,7 @@ export async function getNetworkTranslate(
|
||||
}
|
||||
|
||||
export function test(article: Article) {
|
||||
if (article?.isTranslated) {
|
||||
if (article?.translateSplit) {
|
||||
if (!article.sections?.length) {
|
||||
|
||||
}
|
||||
@@ -203,7 +203,7 @@ export function test(article: Article) {
|
||||
updateLocalSentenceTranslate(article, article.networkTranslate)
|
||||
}
|
||||
} else {
|
||||
article.sections = splitArticle(article.article)
|
||||
// article.sections = splitEnArticle(article.article)
|
||||
if (article.customTranslate) {
|
||||
article.customTranslate = getSplitTranslateText(article.customTranslate)
|
||||
updateLocalSentenceTranslate(article, article.customTranslate)
|
||||
|
||||
285
src/types.ts
285
src/types.ts
@@ -1,15 +1,15 @@
|
||||
export type Word = {
|
||||
"name": string,
|
||||
"usphone": string,
|
||||
"ukphone": string,
|
||||
"trans": string[]
|
||||
"name": string,
|
||||
"usphone": string,
|
||||
"ukphone": string,
|
||||
"trans": string[]
|
||||
}
|
||||
|
||||
export const DefaultWord: Word = {
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
trans: []
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
trans: []
|
||||
}
|
||||
|
||||
export const SaveKey = 'type-word-config'
|
||||
@@ -23,201 +23,202 @@ export type LanguageCategoryType = 'en' | 'ja' | 'de' | 'code'
|
||||
|
||||
|
||||
export type DictionaryResource = {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
tags: string[]
|
||||
url: string
|
||||
length: number
|
||||
language: LanguageType
|
||||
languageCategory: LanguageCategoryType
|
||||
//override default pronunciation when not undefined
|
||||
defaultPronIndex?: number
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
tags: string[]
|
||||
url: string
|
||||
length: number
|
||||
language: LanguageType
|
||||
languageCategory: LanguageCategoryType
|
||||
//override default pronunciation when not undefined
|
||||
defaultPronIndex?: number
|
||||
}
|
||||
|
||||
export type Dictionary = {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
tags: string[]
|
||||
url: string
|
||||
length: number
|
||||
language: LanguageType
|
||||
languageCategory: LanguageCategoryType
|
||||
// calculated in the store
|
||||
chapterCount: number
|
||||
//override default pronunciation when not undefined
|
||||
defaultPronIndex?: number
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
category: string
|
||||
tags: string[]
|
||||
url: string
|
||||
length: number
|
||||
language: LanguageType
|
||||
languageCategory: LanguageCategoryType
|
||||
// calculated in the store
|
||||
chapterCount: number
|
||||
//override default pronunciation when not undefined
|
||||
defaultPronIndex?: number
|
||||
}
|
||||
|
||||
export type PronunciationConfig = {
|
||||
name: string
|
||||
pron: PronunciationType
|
||||
name: string
|
||||
pron: PronunciationType
|
||||
}
|
||||
|
||||
export type LanguagePronunciationMapConfig = {
|
||||
defaultPronIndex: number
|
||||
pronunciation: PronunciationConfig[]
|
||||
defaultPronIndex: number
|
||||
pronunciation: PronunciationConfig[]
|
||||
}
|
||||
|
||||
export type LanguagePronunciationMap = {
|
||||
[key in LanguageType]: LanguagePronunciationMapConfig
|
||||
[key in LanguageType]: LanguagePronunciationMapConfig
|
||||
}
|
||||
|
||||
export type SoundResource = {
|
||||
key: string
|
||||
name: string
|
||||
filename: string
|
||||
key: string
|
||||
name: string
|
||||
filename: string
|
||||
}
|
||||
|
||||
export interface DictJson {
|
||||
description: string,
|
||||
category: string,
|
||||
tags: string[],
|
||||
url: string,
|
||||
length: number,
|
||||
language: string,
|
||||
languageCategory: string,
|
||||
description: string,
|
||||
category: string,
|
||||
tags: string[],
|
||||
url: string,
|
||||
length: number,
|
||||
language: string,
|
||||
languageCategory: string,
|
||||
}
|
||||
|
||||
export enum DictType {
|
||||
newDict = 'newDict',
|
||||
skipDict = 'skipDict',
|
||||
wrongDict = 'wrongDict',
|
||||
publicDict = 'publicDict',
|
||||
customDict = 'customDict',
|
||||
publicArticle = 'publicArticle',
|
||||
customArticle = 'customArticle'
|
||||
newDict = 'newDict',
|
||||
skipDict = 'skipDict',
|
||||
wrongDict = 'wrongDict',
|
||||
publicDict = 'publicDict',
|
||||
customDict = 'customDict',
|
||||
publicArticle = 'publicArticle',
|
||||
customArticle = 'customArticle'
|
||||
}
|
||||
|
||||
export const DefaultArticleWord: ArticleWord = {
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
trans: [],
|
||||
nextSpace: true,
|
||||
isSymbol: false,
|
||||
symbolPosition: ''
|
||||
name: '',
|
||||
usphone: '',
|
||||
ukphone: '',
|
||||
trans: [],
|
||||
nextSpace: true,
|
||||
isSymbol: false,
|
||||
symbolPosition: ''
|
||||
}
|
||||
|
||||
export interface ArticleWord extends Word {
|
||||
nextSpace: boolean,
|
||||
isSymbol: boolean,
|
||||
symbolPosition: 'start' | 'end' | '',
|
||||
nextSpace: boolean,
|
||||
isSymbol: boolean,
|
||||
symbolPosition: 'start' | 'end' | '',
|
||||
}
|
||||
|
||||
export interface Sentence {
|
||||
text: string,
|
||||
translate: string,
|
||||
words: ArticleWord[]
|
||||
text: string,
|
||||
translate: string,
|
||||
words: ArticleWord[]
|
||||
}
|
||||
|
||||
export enum TranslateType {
|
||||
custom = 0,
|
||||
network = 1
|
||||
custom = 0,
|
||||
network = 1,
|
||||
none = 2
|
||||
}
|
||||
|
||||
export interface Article {
|
||||
title: string,
|
||||
titleTranslate: string,
|
||||
article: string,
|
||||
customTranslate: string,
|
||||
networkTranslate: string,
|
||||
isTranslated: boolean,
|
||||
newWords: Word[],
|
||||
articleAllWords: string[],
|
||||
sections: Sentence[][],
|
||||
translateType: TranslateType
|
||||
title: string,
|
||||
titleTranslate: string,
|
||||
article: string,
|
||||
customTranslate: string,
|
||||
networkTranslate: string,
|
||||
translateSplit: boolean,//翻译是否分割
|
||||
newWords: Word[],
|
||||
articleAllWords: string[],
|
||||
sections: Sentence[][],
|
||||
translateType: TranslateType
|
||||
}
|
||||
|
||||
export const DefaultArticle: Article = {
|
||||
title: '',
|
||||
titleTranslate: '',
|
||||
article: '',
|
||||
customTranslate: '',
|
||||
networkTranslate: '',
|
||||
isTranslated: false,
|
||||
newWords: [],
|
||||
articleAllWords: [],
|
||||
sections: [],
|
||||
translateType: TranslateType.network
|
||||
title: '',
|
||||
titleTranslate: '',
|
||||
article: '',
|
||||
customTranslate: '',
|
||||
networkTranslate: '',
|
||||
translateSplit: false,
|
||||
newWords: [],
|
||||
articleAllWords: [],
|
||||
sections: [],
|
||||
translateType: TranslateType.network
|
||||
}
|
||||
|
||||
export interface Dict {
|
||||
name: string,
|
||||
sort: Sort,
|
||||
type: DictType,
|
||||
originWords: Word[],//原始单词
|
||||
words: Word[],
|
||||
chapterWordNumber: number,//章节单词数量
|
||||
chapterWords: Word[][],
|
||||
articles: Article[],
|
||||
chapterIndex: number,
|
||||
chapterWordIndex: number,
|
||||
statistics: Statistics[],
|
||||
url: string,
|
||||
name: string,
|
||||
sort: Sort,
|
||||
type: DictType,
|
||||
originWords: Word[],//原始单词
|
||||
words: Word[],
|
||||
chapterWordNumber: number,//章节单词数量
|
||||
chapterWords: Word[][],
|
||||
articles: Article[],
|
||||
chapterIndex: number,
|
||||
chapterWordIndex: number,
|
||||
statistics: Statistics[],
|
||||
url: string,
|
||||
}
|
||||
|
||||
export interface Statistics {
|
||||
startDate: number,//开始日期
|
||||
endDate: number//结束日期
|
||||
spend: number,//花费时间
|
||||
total: number//单词数量
|
||||
wrongWordNumber: number//错误数
|
||||
correctRate: number//正确率
|
||||
startDate: number,//开始日期
|
||||
endDate: number//结束日期
|
||||
spend: number,//花费时间
|
||||
total: number//单词数量
|
||||
wrongWordNumber: number//错误数
|
||||
correctRate: number//正确率
|
||||
}
|
||||
|
||||
export interface DisplayStatistics extends Statistics {
|
||||
wrongWords: Word[]
|
||||
wrongWords: Word[]
|
||||
}
|
||||
|
||||
export const DefaultDisplayStatistics: DisplayStatistics = {
|
||||
startDate: Date.now(),
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
total: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
wrongWords: [],
|
||||
startDate: Date.now(),
|
||||
endDate: -1,
|
||||
spend: -1,
|
||||
total: -1,
|
||||
correctRate: -1,
|
||||
wrongWordNumber: -1,
|
||||
wrongWords: [],
|
||||
}
|
||||
|
||||
export enum Sort {
|
||||
normal = 0,
|
||||
random = 1,
|
||||
reverse = 2
|
||||
normal = 0,
|
||||
random = 1,
|
||||
reverse = 2
|
||||
}
|
||||
|
||||
export interface State {
|
||||
newWordDict: Dict,
|
||||
skipWordDict: Dict,
|
||||
wrongWordDict: Dict,
|
||||
dict: Dict,
|
||||
oldDicts: Dict[],
|
||||
current: {
|
||||
dictType: DictType,
|
||||
words: Word[],
|
||||
index: number,
|
||||
wrongWords: Word[],
|
||||
originWrongWords: Word[],
|
||||
repeatNumber: number,
|
||||
statistics: Statistics
|
||||
},
|
||||
simpleWords: string[],
|
||||
sideIsOpen: boolean,
|
||||
isDictation: boolean,
|
||||
theme: string,
|
||||
load: boolean
|
||||
newWordDict: Dict,
|
||||
skipWordDict: Dict,
|
||||
wrongWordDict: Dict,
|
||||
dict: Dict,
|
||||
oldDicts: Dict[],
|
||||
current: {
|
||||
dictType: DictType,
|
||||
words: Word[],
|
||||
index: number,
|
||||
wrongWords: Word[],
|
||||
originWrongWords: Word[],
|
||||
repeatNumber: number,
|
||||
statistics: Statistics
|
||||
},
|
||||
simpleWords: string[],
|
||||
sideIsOpen: boolean,
|
||||
isDictation: boolean,
|
||||
theme: string,
|
||||
load: boolean
|
||||
}
|
||||
|
||||
export const ShortKeyMap = {
|
||||
Show: 'Escape',
|
||||
Ignore: 'Tab',
|
||||
Remove: '`',
|
||||
Collect: 'Enter',
|
||||
Show: 'Escape',
|
||||
Ignore: 'Tab',
|
||||
Remove: '`',
|
||||
Collect: 'Enter',
|
||||
}
|
||||
|
||||
export enum TranslateEngine {
|
||||
Baidu = 0,
|
||||
Baidu = 0,
|
||||
}
|
||||
Reference in New Issue
Block a user