From 5e4051c192e261463629fa20d6df55c5f4bb1157 Mon Sep 17 00:00:00 2001 From: zyronon Date: Thu, 28 Sep 2023 01:15:13 +0800 Subject: [PATCH] save --- package.json | 2 + pnpm-lock.yaml | 31 ++ src/assets/css/style.scss | 9 + src/components/Add/AddArticle2.vue | 65 ++-- src/components/List.vue | 2 +- src/stores/base.ts | 490 ++++++++++++++--------------- 6 files changed, 319 insertions(+), 280 deletions(-) diff --git a/package.json b/package.json index df5a2c51..020fe2bc 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,13 @@ "compromise": "^14.10.0", "copy-to-clipboard": "^3.3.3", "element-plus": "^2.3.9", + "file-saver": "^2.0.5", "hover.css": "^2.3.2", "localforage": "^1.10.0", "lodash-es": "^4.17.21", "mitt": "^3.0.1", "pinia": "^2.1.6", + "sentence-splitter": "^4.2.1", "swiper": "^10.1.0", "tesseract.js": "^4.1.1", "uuid": "^9.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 92de8dbe..9999ec05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: element-plus: specifier: ^2.3.9 version: 2.3.14(vue@3.3.4) + file-saver: + specifier: ^2.0.5 + version: 2.0.5 hover.css: specifier: ^2.3.2 version: 2.3.2 @@ -41,6 +44,9 @@ dependencies: pinia: specifier: ^2.1.6 version: 2.1.6(typescript@5.2.2)(vue@3.3.4) + sentence-splitter: + specifier: ^4.2.1 + version: 4.2.1 swiper: specifier: ^10.1.0 version: 10.3.0 @@ -819,6 +825,10 @@ packages: resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==} dev: false + /@textlint/ast-node-types@13.3.3: + resolution: {integrity: sha512-KCpJppfX3Km69twa6SmVEJ8mkyAZSrxw3XaaLQSlpc7PWnLUJSCHGPVECI1nSUDhiTd1r6zlRvWuyIAZJiov+A==} + dev: false + /@tsconfig/node10@1.0.9: resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} requiresBuild: true @@ -1201,6 +1211,10 @@ packages: resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} dev: false + /boundary@2.0.0: + resolution: {integrity: sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==} + dev: false + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1700,6 +1714,10 @@ packages: escape-string-regexp: 1.0.5 dev: true + /file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + dev: false + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -2684,6 +2702,13 @@ packages: lru-cache: 6.0.0 dev: true + /sentence-splitter@4.2.1: + resolution: {integrity: sha512-zn7awgCg40lyb+fe6N/fRJS3r+Ag3SmrmiYHZZSM9oQ2HTnwSMooUgQXSMLeQdi5HWMYOnhrovE2JZ3pyGU0dg==} + dependencies: + '@textlint/ast-node-types': 13.3.3 + structured-source: 4.0.0 + dev: false + /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -2743,6 +2768,12 @@ packages: acorn: 8.10.0 dev: true + /structured-source@4.0.0: + resolution: {integrity: sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==} + dependencies: + boundary: 2.0.0 + dev: false + /suffix-thumb@5.0.2: resolution: {integrity: sha512-I5PWXAFKx3FYnI9a+dQMWNqTxoRt6vdBdb0O+BJ1sxXCWtSoQCusc13E58f+9p4MYx/qCnEMkD5jac6K2j3dgA==} dev: false diff --git a/src/assets/css/style.scss b/src/assets/css/style.scss index bf809585..7317a8b2 100644 --- a/src/assets/css/style.scss +++ b/src/assets/css/style.scss @@ -99,6 +99,15 @@ a { border-radius: 10rem; } + +/* 火狐美化滚动条 */ +* { + scrollbar-color: $second #f3f4f9; + /* 滑块颜色 滚动条背景颜色 */ + scrollbar-width: thin; + /* 滚动条宽度有三种:thin、auto、none */ +} + footer { box-sizing: content-box; height: $footer-height; diff --git a/src/components/Add/AddArticle2.vue b/src/components/Add/AddArticle2.vue index 1eb4c50f..d1f2fbab 100644 --- a/src/components/Add/AddArticle2.vue +++ b/src/components/Add/AddArticle2.vue @@ -1,5 +1,5 @@ @@ -337,7 +333,7 @@ function add() { 标题: 本地翻译 网络翻译 @@ -490,6 +486,7 @@ function add() { display: flex; gap: $space; padding: $space; + padding-top: 10rem; //opacity: 0; } @@ -561,7 +558,7 @@ function add() { .sentence { margin-bottom: 20rem; - &:last-child{ + &:last-child { margin-bottom: 0; } diff --git a/src/components/List.vue b/src/components/List.vue index b9177e95..6c54a3c8 100644 --- a/src/components/List.vue +++ b/src/components/List.vue @@ -146,7 +146,7 @@ function delItem(item: T) { .list-wrapper { flex: 1; - overflow: auto; + overflow: overlay; padding-right: 5rem; .search { diff --git a/src/stores/base.ts b/src/stores/base.ts index fdbcd87f..0415a0ab 100644 --- a/src/stores/base.ts +++ b/src/stores/base.ts @@ -5,258 +5,258 @@ import {emitter, EventKey} from "@/utils/eventBus.ts" import {v4 as uuidv4} from 'uuid'; export interface State { - newWordDict: Dict, - skipWordDict: Dict, - wrongWordDict: Dict, - dict: Dict, - myDicts: Dict[], - current: { - dictType: DictType, - index: number, - editIndex: number, - repeatNumber: number, - }, - simpleWords: string[], - sideIsOpen: boolean, - load: boolean + newWordDict: Dict, + skipWordDict: Dict, + wrongWordDict: Dict, + dict: Dict, + myDicts: Dict[], + current: { + dictType: DictType, + index: number, + editIndex: number, + repeatNumber: number, + }, + simpleWords: string[], + sideIsOpen: boolean, + load: boolean } export const useBaseStore = defineStore('base', { - state: (): State => { - return { - newWordDict: { - name: '生词本', - sort: Sort.normal, - type: DictType.newDict, - originWords: [], - articles: [], - words: [], - chapterWordNumber: 15, - chapterWords: [], - chapterIndex: 0, - chapterWordIndex: 0, - statistics: [], - url: '', - }, - skipWordDict: { - name: '简单词', - sort: Sort.normal, - type: DictType.skipDict, - originWords: [], - articles: [], - words: [], - chapterWordNumber: 15, - chapterWords: [], - chapterIndex: 0, - chapterWordIndex: 0, - statistics: [], - url: '', - }, - wrongWordDict: { - name: '错词本', - sort: Sort.normal, - type: DictType.wrongDict, - originWords: [], - articles: [], - words: [], - chapterWordNumber: 15, - chapterWords: [], - chapterIndex: 0, - chapterWordIndex: 0, - statistics: [], - url: '', - }, - // dict: { - // name: '新概念英语-2', - // sort: Sort.normal, - // type: DictType.innerDict, - // originWords: [], - // articles: [], - // words: [], - // chapterWordNumber: 15, - // chapterWords: [], - // chapterIndex: 0, - // chapterWordIndex: 0, - // statistics: [], - // url: '/dicts/NCE_2.json', - // }, - dict: { - name: '新概念英语-2', - sort: Sort.normal, - type: DictType.publicArticle, - originWords: [], - articles: [], - words: [], - chapterWordNumber: 15, - chapterWords: [], - chapterIndex: 0, - chapterWordIndex: 0, - statistics: [], - url: '/articles/NCE_2.json', - }, - myDicts: [ - { - name: '新概念英语-2', - sort: Sort.normal, - type: DictType.publicArticle, - originWords: [], - articles: [], - words: [], - chapterWordNumber: 15, - chapterWords: [], - chapterIndex: 0, - chapterWordIndex: 0, - statistics: [], - url: '/articles/NCE_2.json', - } - ], - current: { - dictType: DictType.publicArticle, - index: 0, - editIndex: 0, - repeatNumber: 0, - }, - sideIsOpen: false, - simpleWords: [ - 'a', 'an', 'of', 'and', - 'i', 'my', 'you', 'your', - 'me', 'am', 'is', 'do', 'are', - 'what', 'who', 'where', 'how', 'no', 'yes', - 'not', 'did', 'were', 'can', 'could', 'it', - 'the', 'to' - ], - load: false + state: (): State => { + return { + newWordDict: { + name: '生词本', + sort: Sort.normal, + type: DictType.newDict, + originWords: [], + articles: [], + words: [], + chapterWordNumber: 15, + chapterWords: [], + chapterIndex: 0, + chapterWordIndex: 0, + statistics: [], + url: '', + }, + skipWordDict: { + name: '简单词', + sort: Sort.normal, + type: DictType.skipDict, + originWords: [], + articles: [], + words: [], + chapterWordNumber: 15, + chapterWords: [], + chapterIndex: 0, + chapterWordIndex: 0, + statistics: [], + url: '', + }, + wrongWordDict: { + name: '错词本', + sort: Sort.normal, + type: DictType.wrongDict, + originWords: [], + articles: [], + words: [], + chapterWordNumber: 15, + chapterWords: [], + chapterIndex: 0, + chapterWordIndex: 0, + statistics: [], + url: '', + }, + // dict: { + // name: '新概念英语-2', + // sort: Sort.normal, + // type: DictType.innerDict, + // originWords: [], + // articles: [], + // words: [], + // chapterWordNumber: 15, + // chapterWords: [], + // chapterIndex: 0, + // chapterWordIndex: 0, + // statistics: [], + // url: '/dicts/NCE_2.json', + // }, + dict: { + name: '新概念英语-2', + sort: Sort.normal, + type: DictType.publicArticle, + originWords: [], + articles: [], + words: [], + chapterWordNumber: 15, + chapterWords: [], + chapterIndex: 0, + chapterWordIndex: 0, + statistics: [], + url: '/articles/NCE_2.json', + }, + myDicts: [ + { + name: '新概念英语-2', + sort: Sort.normal, + type: DictType.publicArticle, + originWords: [], + articles: [], + words: [], + chapterWordNumber: 15, + chapterWords: [], + chapterIndex: 0, + chapterWordIndex: 0, + statistics: [], + url: '/articles/NCE_2.json', } + ], + current: { + dictType: DictType.publicArticle, + index: 0, + editIndex: 0, + repeatNumber: 0, + }, + sideIsOpen: false, + simpleWords: [ + 'a', 'an', 'of', 'and', + 'i', 'my', 'you', 'your', + 'me', 'am', 'is', 'do', 'are', + 'what', 'who', 'where', 'how', 'no', 'yes', + 'not', 'did', 'were', 'can', 'could', 'it', + 'the', 'to' + ], + load: false + } + }, + getters: { + skipWordNames: (state: State) => { + return state.skipWordDict.originWords.map(v => v.name.toLowerCase()) }, - getters: { - skipWordNames: (state: State) => { - return state.skipWordDict.originWords.map(v => v.name.toLowerCase()) - }, - skipWordNamesWithSimpleWords: (state: State) => { - return state.skipWordDict.originWords.map(v => v.name.toLowerCase()).concat(state.simpleWords) - }, - isArticle(state: State): boolean { - return [ - DictType.publicArticle, - DictType.customArticle - ].includes(state.current.dictType) - }, - currentDict(state: State): Dict { - switch (state.current.dictType) { - case DictType.newDict: - return state.newWordDict - case DictType.skipDict: - return state.skipWordDict - case DictType.wrongDict: - return state.wrongWordDict - case DictType.publicDict: - case DictType.publicArticle: - case DictType.customDict: - case DictType.customArticle: - return this.myDicts[this.current.index] - } - }, - currentEditDict(): Dict { - return this.myDicts[this.current.editIndex] - }, - wordIndex(state: State): number { - return this.currentDict.wordIndex - }, - chapter(state: State): Word[] { - return this.currentDict.chapterWords[this.currentDict.chapterIndex] ?? [] - }, - //TODO 废弃 - word(state: State): Word { - return {trans: [], name: '', usphone: '', ukphone: '',} - }, - dictTitle(state: State) { - let title = this.currentDict.name - if ([DictType.publicDict, DictType.customDict].includes(this.current.dictType)) { - title += ` 第${this.currentDict.chapterIndex + 1}章` - } - return title + skipWordNamesWithSimpleWords: (state: State) => { + return state.skipWordDict.originWords.map(v => v.name.toLowerCase()).concat(state.simpleWords) + }, + isArticle(state: State): boolean { + return [ + DictType.publicArticle, + DictType.customArticle + ].includes(state.current.dictType) + }, + currentDict(state: State): Dict { + switch (state.current.dictType) { + case DictType.newDict: + return state.newWordDict + case DictType.skipDict: + return state.skipWordDict + case DictType.wrongDict: + return state.wrongWordDict + case DictType.publicDict: + case DictType.publicArticle: + case DictType.customDict: + case DictType.customArticle: + return this.myDicts[this.current.index] + } + }, + currentEditDict(): Dict { + return this.myDicts[this.current.editIndex] + }, + wordIndex(state: State): number { + return this.currentDict.wordIndex + }, + chapter(state: State): Word[] { + return this.currentDict.chapterWords[this.currentDict.chapterIndex] ?? [] + }, + //TODO 废弃 + word(state: State): Word { + return {trans: [], name: '', usphone: '', ukphone: '',} + }, + dictTitle(state: State) { + let title = this.currentDict.name + if ([DictType.publicDict, DictType.customDict].includes(this.current.dictType)) { + title += ` 第${this.currentDict.chapterIndex + 1}章` + } + return title + } + }, + actions: { + setState(obj: any) { + for (const [key, value] of Object.entries(obj)) { + this[key] = value + } + // console.log('this/', this) + }, + async init() { + let configStr = localStorage.getItem(SaveDictKey) + if (configStr) { + let obj: State = JSON.parse(configStr) + // this.setState(obj) + } + + if ([ + DictType.newDict, + DictType.wrongDict, + DictType.skipDict, + ].includes(this.current.dictType)) { + + } else { + if ([ + DictType.publicDict, + DictType.customDict, + ].includes(this.current.dictType)) { + if (!this.currentDict.originWords.length) { + let r = await fetch(`${this.currentDict.url}`) + r.json().then(v => { + this.currentDict.originWords = cloneDeep(v) + this.currentDict.words = cloneDeep(v) + this.currentDict.chapterWords = chunk(this.dict.words, this.dict.chapterWordNumber) + this.load = true + }) + } } - }, - actions: { - setState(obj: any) { - for (const [key, value] of Object.entries(obj)) { - this[key] = value - } - // console.log('this/', this) - }, - async init() { - let configStr = localStorage.getItem(SaveDictKey) - if (configStr) { - let obj: State = JSON.parse(configStr) - // this.setState(obj) - } - if ([ - DictType.newDict, - DictType.wrongDict, - DictType.skipDict, - ].includes(this.current.dictType)) { - - } else { - if ([ - DictType.publicDict, - DictType.customDict, - ].includes(this.current.dictType)) { - if (!this.currentDict.originWords.length) { - let r = await fetch(`${this.currentDict.url}`) - r.json().then(v => { - this.currentDict.originWords = cloneDeep(v) - this.currentDict.words = cloneDeep(v) - this.currentDict.chapterWords = chunk(this.dict.words, this.dict.chapterWordNumber) - this.load = true - }) - } - } - - if ([ - DictType.publicArticle, - DictType.customArticle, - ].includes(this.current.dictType)) { - if (!this.currentDict.articles.length) { - let r = await fetch(`${this.currentDict.url}`) - r.json().then((v: any[]) => { - this.currentDict.articles = cloneDeep(v.map(v => { - v.id = uuidv4() - return v - })) - this.load = true - }) - } - } - } - }, - saveStatistics(statistics: Statistics) { - if (statistics.spend > 1000 * 10) { - this.currentDict.statistics.push(statistics) - } - }, - async changeDict(dict: Dict, chapterIndex: number = dict.chapterIndex, chapterWordIndex: number = dict.chapterWordNumber) { - this.saveStatistics() - console.log('changeDict', cloneDeep(dict), chapterIndex, chapterWordIndex) - this.current.dictType = dict.type - if ([DictType.newDict, - DictType.skipDict, - DictType.wrongDict].includes(dict.type)) { - this[dict.type].chapterIndex = chapterIndex - this[dict.type].chapterWordIndex = chapterWordIndex - } else { - this.dict = cloneDeep(dict) - if (dict.originWords.length) { - let r = await fetch(`/public/${this.dict.url}`) - let v = await r.json() - this.dict.originWords = cloneDeep(v) - this.dict.words = cloneDeep(v) - this.dict.chapters = chunk(this.dict.words, this.dict.chapterWordNumber) - } - this.dict.chapterIndex = chapterIndex - this.dict.chapterWordIndex = chapterWordIndex - } - emitter.emit(EventKey.resetWord) + if ([ + DictType.publicArticle, + DictType.customArticle, + ].includes(this.current.dictType)) { + if (!this.currentDict.articles.length) { + let r = await fetch(`${this.currentDict.url}`) + r.json().then((v: any[]) => { + this.currentDict.articles = cloneDeep(v.map(v => { + v.id = uuidv4() + return v + })) + this.load = true + }) + } } + } }, + saveStatistics(statistics: Statistics) { + if (statistics.spend > 1000 * 10) { + this.currentDict.statistics.push(statistics) + } + }, + async changeDict(dict: Dict, chapterIndex: number = dict.chapterIndex, chapterWordIndex: number = dict.chapterWordNumber) { + this.saveStatistics() + console.log('changeDict', cloneDeep(dict), chapterIndex, chapterWordIndex) + this.current.dictType = dict.type + if ([DictType.newDict, + DictType.skipDict, + DictType.wrongDict].includes(dict.type)) { + this[dict.type].chapterIndex = chapterIndex + this[dict.type].chapterWordIndex = chapterWordIndex + } else { + this.dict = cloneDeep(dict) + if (dict.originWords.length) { + let r = await fetch(`/public/${this.dict.url}`) + let v = await r.json() + this.dict.originWords = cloneDeep(v) + this.dict.words = cloneDeep(v) + this.dict.chapters = chunk(this.dict.words, this.dict.chapterWordNumber) + } + this.dict.chapterIndex = chapterIndex + this.dict.chapterWordIndex = chapterWordIndex + } + emitter.emit(EventKey.resetWord) + } + }, }) \ No newline at end of file