chore: change

This commit is contained in:
zyronon
2023-09-13 18:57:00 +08:00
parent 75635ec22c
commit 107e6b54fd
12 changed files with 507 additions and 60 deletions

1
components.d.ts vendored
View File

@@ -7,6 +7,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
AddArticle: typeof import('./src/components/Practice/AddArticle.vue')['default']
Backgorund: typeof import('./src/components/Backgorund.vue')['default']
BaseButton: typeof import('./src/components/BaseButton.vue')['default']
ChapterDetail: typeof import('./src/components/ChapterDetail.vue')['default']

View File

@@ -17,6 +17,7 @@
"@opentranslate/baidu": "^1.4.2",
"@opentranslate/translator": "^1.4.2",
"axios": "^1.5.0",
"copy-to-clipboard": "^3.3.3",
"element-plus": "^2.3.9",
"hover.css": "^2.3.2",
"localforage": "^1.10.0",
@@ -28,7 +29,6 @@
"vue": "^3.3.4"
},
"devDependencies": {
"tslib": "^2.6.2",
"@iconify/vue": "^4.1.1",
"@types/lodash-es": "^4.17.9",
"@vitejs/plugin-vue": "^4.2.3",
@@ -39,6 +39,7 @@
"husky": "^8.0.3",
"rollup-plugin-visualizer": "^5.9.2",
"sass": "^1.64.2",
"tslib": "^2.6.2",
"typescript": "^5.2.0",
"unplugin-auto-import": "^0.16.6",
"unplugin-vue-components": "^0.25.2",

13
pnpm-lock.yaml generated
View File

@@ -14,6 +14,9 @@ dependencies:
axios:
specifier: ^1.5.0
version: 1.5.0
copy-to-clipboard:
specifier: ^3.3.3
version: 3.3.3
element-plus:
specifier: ^2.3.9
version: 2.3.9(vue@3.3.4)
@@ -1406,6 +1409,12 @@ packages:
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
dev: true
/copy-to-clipboard@3.3.3:
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
dependencies:
toggle-selection: 1.0.6
dev: false
/cosmiconfig-typescript-loader@4.4.0(@types/node@20.4.7)(cosmiconfig@8.3.5)(ts-node@10.9.1)(typescript@5.2.2):
resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==}
engines: {node: '>=v14.21.3'}
@@ -2796,6 +2805,10 @@ packages:
is-number: 7.0.0
dev: true
/toggle-selection@1.0.6:
resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==}
dev: false
/tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: false

View File

@@ -5,6 +5,7 @@ import {onMounted, watch} from "vue";
import {useBaseStore} from "@/stores/base.ts";
import {SaveKey} from "@/types.ts"
import Practice from "@/components/Practice/Practice.vue"
import AddArticle from "@/components/Practice/AddArticle.vue";
const store = useBaseStore()
// 查询当前系统主题颜色
@@ -33,7 +34,8 @@ onMounted(() => {
<template>
<!-- <Backgorund/>-->
<div class="main-page">
<Practice/>
<!-- <Practice/>-->
<AddArticle/>
<!-- <Side/>-->
<Statistics></Statistics>
</div>

View File

@@ -5,20 +5,26 @@ import {Icon} from "@iconify/vue";
defineProps<{
keyboard?: string,
active?: boolean
disabled?: boolean
size?: string
}>()
defineEmits(['click'])
function click() {
}
</script>
<template>
<Tooltip :disabled="!keyboard" :title="`快捷键: ${keyboard}`">
<div class="my-button hvr-grow"
@click="$emit('click')"
<div class="my-button"
@click="!disabled && $emit('click')"
:class="[
active && 'active',
size,
disabled && 'disabled',
!disabled && 'hvr-grow'
]">
<span><slot></slot></span>
<div class="key-notice" v-if="keyboard">
@@ -44,9 +50,15 @@ defineEmits(['click'])
//background: #999;
//background: rgb(60, 63, 65);
//background: var(--color-second-bg);
height: 40rem;
height: 36rem;
line-height: 1;
&.disabled {
opacity: .6;
cursor: not-allowed;
user-select: none;
}
&.small {
height: 30rem;

View File

@@ -0,0 +1,338 @@
<script setup lang="ts">
import {reactive, watch} from "vue";
import {Article, Sentence, TranslateEngine} from "@/types.ts";
import BaseButton from "@/components/BaseButton.vue";
import {getCompleteTranslate, localTranslate, networkTranslate} from "@/hooks/translate.ts";
import * as copy from "copy-to-clipboard";
import {CnKeyboardMap, splitArticle, splitCNArticle} from "@/hooks/article.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 = `Last week I went to the theatre. I had a very good seat. The play was very interesting. I did not enjoy it.`
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.`
let article = reactive<Article>({
title: 'A private conversation!',
titleTranslate: '',
article: article1,
customTranslate: ``,
networkTranslate: '第一周我去了剧院。我坐得很好。这出戏很有趣。我不喜欢它。一个年轻男子和一个年轻女子坐在我身后。他们大声说话。我很生气。我听不见演员们的声音。我转过身来。我愤怒地看着那个男人和那个女人。他们没有理会。最后我无法忍受。我又转过身来。“我一个字也听不见!”我生气地说。\n' +
'“这不关你的事,”那个年轻人粗鲁地说。“这是私人谈话!”',
newWords: [],
articleAllWords: [],
sections: [],
sections2: [[{
"text": "Last week I went to the theatre. ", "translate": "上周我去了剧院。", "words": [{"name": "Last", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "week", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "went", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "to", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "the", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "theatre", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]
}, {"text": "I had a very good seat. ", "translate": "我坐得很好。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "had", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "a", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "very", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "good", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "seat", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "The play was very interesting. ", "translate": "这出戏很有趣。", "words": [{"name": "The", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "play", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "was", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "very", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "interesting", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "I did not enjoy it. ", "translate": "我不喜欢它。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "did", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "not", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "enjoy", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "it", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {
"text": "A young man and a young woman were sitting behind me. ", "translate": "一个年轻男子和一个年轻女子坐在我身后。", "words": [{"name": "A", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "young", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "man", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "and", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "a", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "young", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "woman", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "were", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "sitting", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "behind", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "me", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]
}, {"text": "They were talking loudly. ", "translate": "他们大声说话。", "words": [{"name": "They", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "were", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "talking", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "loudly", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "I got very angry. ", "translate": "我很生气。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "got", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "very", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "angry", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "I could not hear the actors. ", "translate": "我听不见演员们的声音。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "could", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "not", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "hear", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "the", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "actors", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "I turned round. ", "translate": "我转过身来。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "turned", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "round", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {
"text": "I looked at the man and the woman angrily. ", "translate": "我愤怒地看着那个男人和那个女人。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "looked", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "at", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "the", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "man", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "and", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "the", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "woman", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "angrily", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]
}, {"text": "They did not pay any attention. ", "translate": "他们没有理会。", "words": [{"name": "They", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "did", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "not", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "pay", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "any", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "attention", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "In the end, ", "translate": "最后", "words": [{"name": "In", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "the", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "end", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ",", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "I could not bear it. ", "translate": "我无法忍受。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "could", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "not", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "bear", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "it", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {"text": "I turned round again. ", "translate": "我又转过身来。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "turned", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "round", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "again", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {
"text": "\"I can't hear a word!\" ", "translate": "“我一个字也听不见!”", "words": [{"name": "\"", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": true, "symbolPosition": "start"}, {"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "can't", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "hear", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "a", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "word", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": "!", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": true, "symbolPosition": ""}, {"name": "\"", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": "end"}]
}, {"text": "I said angrily. ", "translate": "我生气地说。", "words": [{"name": "I", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "said", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "angrily", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}], [{
"text": "\"It's none of your business,\" ", "translate": "“这不关你的事,”", "words": [{"name": "\"", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": true, "symbolPosition": "start"}, {"name": "It's", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "none", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "of", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "your", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "business", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ",", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": true, "symbolPosition": ""}, {"name": "\"", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": "end"}]
}, {"text": "the young man said rudely. ", "translate": "那个年轻人粗鲁地说。", "words": [{"name": "the", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "young", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "man", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "said", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "rudely", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": ".", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": ""}]}, {
"text": "\"This is a private conversation!\" ", "translate": "“这是私人谈话!”", "words": [{"name": "\"", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": true, "symbolPosition": "start"}, {"name": "This", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "is", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "a", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "private", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": false, "symbolPosition": ""}, {"name": "conversation", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": false, "symbolPosition": ""}, {"name": "!", "usphone": "", "ukphone": "", "trans": [], "nextSpace": false, "isSymbol": true, "symbolPosition": ""}, {"name": "\"", "usphone": "", "ukphone": "", "trans": [], "nextSpace": true, "isSymbol": true, "symbolPosition": "end"}]
}]],
isTranslated: false,
})
let translateType = $ref(0)
let networkTranslateEngine = $ref('baidu')
let progress = $ref(0)
let editTranslateStr = $ref('')
const TranslateEngineOptions = [
{value: 'baidu', label: '百度'},
{value: 'youdao', label: '有道'},
]
async function startTranslate() {
if (!article.sections.length) {
article.sections = splitArticle(article.article)
article.sections.map((v: Sentence[]) => {
v.map((w: Sentence) => {
w.edit = false
})
})
}
article.networkTranslate = ''
await networkTranslate(article, TranslateEngine.Baidu, true, (v: number) => {
progress = v
})
copy(JSON.stringify(article.sections))
}
function editTranslate(sentence: Sentence) {
article.sections.map((v: Sentence[]) => {
v.map((w: Sentence) => {
w.edit = false
})
})
sentence.edit = true
editTranslateStr = sentence.translate
}
function save(sentence: Sentence) {
sentence.translate = editTranslateStr
sentence.edit = false
if (translateType) {
article.customTranslate = getCompleteTranslate(article)
} else {
article.networkTranslate = getCompleteTranslate(article)
}
}
function changeArticleTranslate(e: string) {
console.log('e', e)
localTranslate(article, e)
}
function changeArticle() {
if (!article.article.trim()) return
article.sections = splitArticle(article.article)
article.sections.map((v: Sentence[]) => {
v.map((w: Sentence) => {
w.edit = false
})
})
if (translateType) {
localTranslate(article, article.customTranslate)
} else {
localTranslate(article, article.networkTranslate)
}
}
</script>
<template>
<div class="add-article">
<div class="content">
<div class="row">
<div class="title">原文</div>
<div class="item">
<div class="label">标题</div>
<el-input
v-model="article.title"
:rows="2"
type="textarea"
placeholder="请填写原文标题"
input-style="color:black;font-size:18rem;"
/>
</div>
<div class="item">
<div class="label">正文</div>
<el-input
v-model="article.article"
@input="changeArticle"
:rows="23"
type="textarea"
placeholder="请填写原文正文"
input-style="color:black;font-size:18rem;"
/>
</div>
</div>
<div class="row">
<div class="title">译文</div>
<div class="item">
<div class="label">翻译类型</div>
<el-radio-group v-model="translateType">
<el-radio-button :label="1">本地翻译</el-radio-button>
<el-radio-button :label="0">网络翻译</el-radio-button>
</el-radio-group>
</div>
<div class="translate" v-if="!translateType">
<BaseButton @click="startTranslate" :disabled="!article.article.trim()">开始翻译</BaseButton>
<el-select v-model="networkTranslateEngine"
style="width: 80rem;"
>
<el-option
v-for="item in TranslateEngineOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-progress :percentage="progress"
:duration="30"
:striped="progress !== 100"
:striped-flow="progress !== 100"
:stroke-width="8"
:show-text="true"/>
</div>
<div class="item">
<div class="label">标题</div>
<el-input
v-model="article.titleTranslate"
:rows="2"
type="textarea"
placeholder="请填写翻译标题"
input-style="color:black;font-size:16rem;"
/>
</div>
<div class="item">
<div class="label">正文</div>
<el-input
v-if="translateType"
v-model="article.customTranslate"
@input="changeArticleTranslate"
:rows="20"
type="textarea"
placeholder="请填定翻译正文"
input-style="color:black;font-size:16rem;"
/>
<el-input
v-else
v-model="article.networkTranslate"
@input="changeArticleTranslate"
:rows="20"
type="textarea"
placeholder="请填定翻译正文"
input-style="color:black;font-size:16rem;"
/>
</div>
</div>
<div class="row">
<div class="title">译文对照</div>
<div class="article-translate">
<div class="section" v-for="(item,indexI) in article.sections">
<div class="sentence" v-for="(sentence,indexJ) in item">
<div class="text">{{ sentence.text }}</div>
<div class="edit-translate" v-if="sentence.edit">
<el-input
v-model="editTranslateStr"
autosize
type="textarea"
input-style="color:black;"
/>
<div class="options">
<BaseButton @click="sentence.edit = false">取消</BaseButton>
<BaseButton @click="save(sentence)">保存</BaseButton>
</div>
</div>
<div class="text-translate" v-else @click="editTranslate(sentence)">
{{ sentence.translate }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/style.scss";
.add-article {
width: 100vw;
height: 100vh;
padding: $space;
box-sizing: border-box;
color: black;
.content {
width: 100%;
height: 100%;
display: flex;
gap: $space * 2;
}
.row {
width: 33%;
height: 100%;
display: flex;
flex-direction: column;
//opacity: 0;
&:last-child {
opacity: 1;
}
.title {
font-size: 22rem;
text-align: center;
}
.item {
margin-bottom: 10rem;
.label {
margin-bottom: 10rem;
}
}
.translate {
display: flex;
align-items: center;
gap: $space;
margin-bottom: 10rem;
.el-progress {
flex: 1;
}
}
.article-translate {
margin-top: 10rem;
flex: 1;
overflow: auto;
.section {
background: white;
margin-bottom: 20rem;
padding: $space;
.sentence {
margin-bottom: 20rem;
.text {
font-size: 18rem;
}
.text-translate {
font-size: 16rem;
min-height: 18rem;
}
.edit-translate {
margin-top: 10rem;
color: black;
.options {
margin-top: 10rem;
gap: 10rem;
display: flex;
justify-content: flex-end;
}
}
}
}
}
}
}
</style>

View File

@@ -14,7 +14,6 @@ import 机械3 from '../..//assets/sound/key-sounds/jixie/机械3.mp3'
import beep from '../..//assets/sound/beep.wav'
import correct from '../..//assets/sound/correct.wav'
import {useSound} from "@/hooks/useSound.ts"
import {CnKeyboardMap, useSplitArticle, useSplitCNArticle} from "@/hooks/useSplitArticle";
import {$computed, $ref} from "vue/macros";
import {
Article,
@@ -31,10 +30,11 @@ import {useBaseStore} from "@/stores/base";
import {usePracticeStore} from "@/components/Practice/usePracticeStore.ts";
import {useEventListener} from "@/hooks/useEvent.ts";
import TypeWord from "@/components/Practice/TypeWord.vue";
import {useLocalTranslate, useNetworkTranslate} from "@/hooks/translate.ts";
import {localTranslate, networkTranslate} from "@/hooks/translate.ts";
import IconWrapper from "@/components/IconWrapper.vue";
import Tooltip from "@/components/Tooltip.vue";
import MiniModal from "@/components/MiniModal.vue";
import {splitArticle} from "@/hooks/article.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?
@@ -94,6 +94,8 @@ let wordData = $ref({
})
let article = reactive<Article>({
title: 'A private conversation!',
titleTranslate: '',
article: article1,
customTranslate: `上星期我去看戏。我的座位很好,戏很有意思,但我却无法欣赏。一青年男子与一青年女子坐在我的身后,大声地说着话。我非常生气,因为我听不见演员在说什么。我回过头去,怒视着那一男一女,他们却毫不理会。最后,我忍不住了,又一次回过头去,生气地说,“我一个字也听不见了!”
“不关你的事,”那男的毫不客气地说,“这是私人间的谈话!”`,
@@ -106,7 +108,7 @@ let article = reactive<Article>({
onMounted(async () => {
if (!article.sections.length) {
article.sections = useSplitArticle(article.article)
article.sections = splitArticle(article.article)
}
practiceStore.total = 0
@@ -124,7 +126,7 @@ onMounted(async () => {
console.time()
// await useNetworkTranslate(article, TranslateEngine.Baidu, true)
useLocalTranslate(article, article.customTranslate)
localTranslate(article, article.customTranslate)
console.timeEnd()
// console.log(cloneDeep(article))
})
@@ -202,7 +204,7 @@ function onKeyDown(e: KeyboardEvent) {
if (store.setting.dictation) {
calcTranslateLocation()
}
playAudio(currentSection[sentenceIndex].sentence)
playAudio(currentSection[sentenceIndex].text)
}
}
}
@@ -407,7 +409,7 @@ function otherWord(word: ArticleWord, i: number, i2: number, i3: number) {
]"
@mouseenter="store.setting.allowWordTip && (hoverIndex = {sectionIndex : indexI,sentenceIndex :indexJ})"
@mouseleave="hoverIndex = {sectionIndex : -1,sentenceIndex :-1}"
@click="playAudio(sentence.sentence)"
@click="playAudio(sentence.text)"
v-for="(sentence,indexJ) in section">
<span
v-for="(word,indexW) in sentence.words"

View File

@@ -8,9 +8,11 @@ import {useBaseStore} from "@/stores/base.ts";
import {useWindowClick} from "@/hooks/event.ts";
import {emitter, EventKey} from "@/utils/eventBus.ts";
import BaseButton from "@/components/BaseButton.vue";
import Modal from "@/components/Modal/Modal.vue";
const store = useBaseStore()
let show = $ref(false)
let showCustomTranslateModal = $ref(false)
useWindowClick(() => show = false)
@@ -26,9 +28,11 @@ const TranslateEngine = [
{value: 'youdao', label: '有道'},
]
function save(){
function save() {
}
</script>
<template>
@@ -66,9 +70,13 @@ function save(){
<div class="mini-row" v-if="translateType">
<label class="item-title">本地翻译</label>
<div class="wrapper">
<Icon icon="mingcute:edit-line"
@click="toggle"
/>
<Tooltip title="开关释义显示">
<IconWrapper>
<Icon icon="mingcute:edit-line"
@click="toggle"
/>
</IconWrapper>
</Tooltip>
</div>
</div>
<div class="mini-row" v-else>
@@ -89,6 +97,10 @@ function save(){
<BaseButton size="small" @click="save">确定</BaseButton>
</div>
</MiniModal>
<Modal
title="A private Conversation!"
v-model="showCustomTranslateModal">
</Modal>
</div>
</template>

View File

@@ -39,6 +39,16 @@ function toggle() {
/>
</div>
</div>
<div class="mini-row">
<label class="item-title">释义发音</label>
<div class="wrapper">
<el-switch v-model="store.setting.translateSound"
inline-prompt
active-text=""
inactive-text=""
/>
</div>
</div>
<div class="mini-row">
<label class="item-title">按键音</label>
<div class="wrapper">

View File

@@ -28,11 +28,11 @@ export const EnKeyboardMap: KeyboardMap = {
}
export function useSplitArticle(article: string, lang: string = 'en', keyboardMap: KeyboardMap = EnKeyboardMap): Sentence[][] {
export function splitArticle(article: string, lang: string = 'en', keyboardMap: KeyboardMap = EnKeyboardMap): Sentence[][] {
let sections: Sentence[][] = []
let section: Sentence[] = []
let sentence: Sentence = {
sentence: '',
text: '',
translate: '',
words: []
}
@@ -66,7 +66,7 @@ export function useSplitArticle(article: string, lang: string = 'en', keyboardMa
sentence.words.push(word)
sentence.words.push(cloneDeep({...DefaultArticleWord, name: v, nextSpace: true, isSymbol: true}))
section.push({
sentence: '',
text: '',
translate: '',
words: []
})
@@ -137,7 +137,7 @@ export function useSplitArticle(article: string, lang: string = 'en', keyboardMa
sections.push([])
section = sections[sections.length - 1]
section.push({
sentence: '',
text: '',
translate: '',
words: []
})
@@ -152,7 +152,7 @@ export function useSplitArticle(article: string, lang: string = 'en', keyboardMa
})
sections.map((sectionItem, a) => {
sectionItem.map((sentenceItem, b) => {
sentenceItem.sentence = sentenceItem.words.reduce((previousValue: string, currentValue) => {
sentenceItem.text = sentenceItem.words.reduce((previousValue: string, currentValue) => {
previousValue += currentValue.name + (currentValue.nextSpace ? ' ' : '')
return previousValue
}, '')
@@ -165,11 +165,11 @@ export function useSplitArticle(article: string, lang: string = 'en', keyboardMa
return sections
}
export function useSplitCNArticle(article: string, lang: string = 'en', keyboardMap: KeyboardMap = CnKeyboardMap): Sentence[][] {
export function splitCNArticle(article: string, lang: string = 'en', keyboardMap: KeyboardMap = CnKeyboardMap): Sentence[][] {
let sections: Sentence[][] = []
let section: Sentence[] = []
let sentence: Sentence = {
sentence: '',
text: '',
translate: '',
words: []
}
@@ -196,7 +196,7 @@ export function useSplitCNArticle(article: string, lang: string = 'en', keyboard
sentence.words.push(word)
sentence.words.push(cloneDeep({...DefaultArticleWord, name: v, nextSpace: true}))
section.push({
sentence: '',
text: '',
translate: '',
words: []
})
@@ -271,7 +271,7 @@ export function useSplitCNArticle(article: string, lang: string = 'en', keyboard
sections.push([])
section = sections[sections.length - 1]
section.push({
sentence: '',
text: '',
translate: '',
words: []
})
@@ -286,7 +286,7 @@ export function useSplitCNArticle(article: string, lang: string = 'en', keyboard
})
sections.map((sectionItem, a) => {
sectionItem.map((sentenceItem, b) => {
sentenceItem.sentence = sentenceItem.words.reduce((previousValue: string, currentValue) => {
sentenceItem.text = sentenceItem.words.reduce((previousValue: string, currentValue) => {
previousValue += currentValue.name + (currentValue.nextSpace ? ' ' : '')
return previousValue
}, '')

View File

@@ -1,33 +1,53 @@
import {Article, Sentence, TranslateEngine} from "@/types.ts";
import Baidu from "@opentranslate/baidu";
import {axiosInstance} from "@/utils/http.ts";
import useSleep from "@/hooks/useSleep.ts";
import {CnKeyboardMap, useSplitCNArticle} from "@/hooks/useSplitArticle.ts";
import {CnKeyboardMap, splitCNArticle} from "@/hooks/article.ts";
import {Translator} from "@opentranslate/translator/src/translator.ts";
export function useLocalTranslate(article: Article, translate: string) {
if (translate) {
let articleTranslate = useSplitCNArticle(translate, 'cn', CnKeyboardMap)
export function localTranslate(article: Article, translate: string) {
if (translate.trim()) {
let articleTranslate = splitCNArticle(translate, 'cn', CnKeyboardMap)
console.log('articleTranslate',articleTranslate)
for (let i = 0; i < article.sections.length; i++) {
let v = article.sections[i]
for (let j = 0; j < v.length; j++) {
let sentence = v[j]
sentence.translate = articleTranslate[i][j].sentence
try {
sentence.translate = articleTranslate[i][j].text
}catch (e) {
console.log('没有对应的翻译',sentence.text)
}
}
}
}
}
export function getCompleteTranslate(article: Article) {
let str = ''
article.sections.map((v: Sentence[]) => {
v.map((w: Sentence, j, arr) => {
str += (w.translate ?? w.text) + (j === arr.length - 1 ? '\n' : '')
})
})
return str
}
/***
* @desc
* @param article 文章实体
* @param translateEngine 翻译引擎
* @param allShow 是否翻译完所有之后才显示
* @param progressCb 进度回调
* */
export async function useNetworkTranslate(article: Article, translateEngine: TranslateEngine, allShow: boolean = false) {
export async function networkTranslate(
article: Article,
translateEngine: TranslateEngine,
allShow: boolean = false,
progressCb?: (val: number) => void
) {
if (article.networkTranslate) {
useLocalTranslate(article, article.networkTranslate)
localTranslate(article, article.networkTranslate)
} else {
let translator: Translator
if (translateEngine === TranslateEngine.Baidu) {
@@ -40,18 +60,28 @@ export async function useNetworkTranslate(article: Article, translateEngine: Tra
}) as any
}
if (translator) {
if (!article.titleTranslate) {
translator.translate(article.title, 'en', 'zh-CN').then(r => {
article.titleTranslate = r.trans.paragraphs[0]
})
}
let promiseList = []
let retryCount = 0
let retryCountMap = new Map()
const translate = async (sentence: Sentence) => {
try {
let r = await translator.translate(sentence.sentence, 'en', 'zh-CN')
let r = await translator.translate(sentence.text, 'en', 'zh-CN')
if (r) {
const cb = () => {
sentence.translate = r.trans.paragraphs[0]
article.networkTranslate += sentence.translate
if (!allShow) {
//一次显示所有,顺序会乱
article.networkTranslate += sentence.translate
}
}
return Promise.resolve(cb)
} else {
@@ -74,48 +104,72 @@ export async function useNetworkTranslate(article: Article, translateEngine: Tra
if (allShow) {
promiseList.push(promise)
} else {
retryCountMap.set(sentence.sentence, 0)
retryCountMap.set(sentence.text, 0)
let errResult: any
let cb = await promise.catch(err => {
errResult = err
})
while (errResult) {
let count = retryCountMap.get(sentence.sentence)
let count = retryCountMap.get(sentence.text)
if (count > 2) break
cb = await errResult().catch(err => {
errResult = err
})
retryCountMap.set(sentence.sentence, count + 1)
retryCountMap.set(sentence.text, count + 1)
}
if (cb) cb()
index++
console.log(index, total)
if (progressCb) {
progressCb(Math.floor((index / total) * 100))
}
}
}
}
if (!promiseList.length) return
return new Promise(async resolve => {
let cbs = []
do {
if (retryCount > 2) {
return resolve(true)
}
let results = await Promise.allSettled(promiseList)
promiseList = []
results.map(results => {
if (results.status === 'fulfilled') {
cbs.push(results.value)
} else {
promiseList.push(results.reason())
if (promiseList.length) {
let timer = -1
let progress = 0
if (progressCb) {
timer = setInterval(() => {
progress++
if (progress > 90) {
return clearInterval(timer)
}
})
retryCount++
} while (promiseList.length)
cbs.map(v => v())
resolve(true)
})
progressCb(progress)
}, 100)
}
return new Promise(async resolve => {
let cbs = []
do {
if (retryCount > 2) {
return resolve(true)
}
let results = await Promise.allSettled(promiseList)
promiseList = []
results.map(results => {
if (results.status === 'fulfilled') {
cbs.push(results.value)
} else {
promiseList.push(results.reason())
}
})
retryCount++
} while (promiseList.length)
cbs.map(v => v())
article.networkTranslate = getCompleteTranslate(article)
if (progressCb) {
clearInterval(timer)
progress = 91
progressCb(100)
}
resolve(true)
})
} else {
article.networkTranslate = getCompleteTranslate(article)
}
}
}
}

View File

@@ -107,12 +107,14 @@ export interface ArticleWord extends Word {
}
export interface Sentence {
sentence: string,
text: string,
translate: string,
words: ArticleWord[]
}
export interface Article {
title: string,
titleTranslate: string,
article: string,
customTranslate: string,
networkTranslate: string,