This commit is contained in:
zyronon
2024-06-19 02:37:02 +08:00
parent f359f44f5f
commit ca9c806457
7 changed files with 4035 additions and 3583 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,6 @@ let currentTag = $ref(props.item.tags[0])
let localList = $computed(() => {
return props.item.list.filter(v => v.tags.includes(currentTag))
})
</script>
<template>

View File

@@ -1,186 +0,0 @@
<script setup lang="ts">
import {getDefaultDict, Sort,} from "@/types.ts";
import {groupBy, uniq} from "lodash-es";
import {useBaseStore} from "@/stores/base.ts";
import DictGroup from "@/pages/pc/components/list/DictGroup.vue";
import enFlag from "@/assets/img/flags/en.png";
import jaFlag from "@/assets/img/flags/ja.png";
import deFlag from "@/assets/img/flags/de.png";
import codeFlag from "@/assets/img/flags/code.png";
import BaseIcon from "@/components/BaseIcon.vue";
import {useNav} from "@/utils";
import {onMounted} from "vue";
import dict from '@/assets/dict.json'
const store = useBaseStore()
const languageCategoryOptions = [
{id: 'en', name: '英语', flag: enFlag},
{id: 'ja', name: '日语', flag: jaFlag},
{id: 'de', name: '德语', flag: deFlag},
{id: 'code', name: 'Code', flag: codeFlag},
]
const {nav, back} = useNav()
function change(e) {
console.log('e', e.dict)
e.dict.sort = Sort.normal
store.changeWordDict(getDefaultDict(e.dict))
ElMessage.success('切换成功')
back()
}
let dictData = $ref({})
let currentTabIndex = $ref('0')
let currentTranslateLanguage2 = $ref(1)
const currentLangDictList = $computed(() => {
return dictData[currentTabIndex] ?? {}
})
const currentTranDictList = $computed(() => {
return currentLangDictList[currentTranslateLanguage2] ?? {}
})
onMounted(() => {
let d: any = groupBy(dict, 'langType')
for (let dKey in d) {
d[dKey] = groupBy(d[dKey], 'tranType')
for (const dKey2 in d[dKey]) {
d[dKey][dKey2] = groupBy(d[dKey][dKey2], 'category')
for (const dKey3 in d[dKey][dKey2]) {
d[dKey][dKey2][dKey3] = {
tags: uniq(d[dKey][dKey2][dKey3].sort((a, b) => a.id - b.id).map(v => v.tags).flat()),
list: d[dKey][dKey2][dKey3],
name: dKey3
}
}
}
}
dictData = d
console.log('dict', d)
})
function formatLangType(val) {
switch (Number(val)) {
case 0:
return '英语'
case 1:
return '汉语'
}
}
</script>
<template>
<div class="dict-list-panel">
<header class="flex justify-center pb-3">
<div class="container2 flex justify-between items-center">
<div class="flex items-center gap-5">
<BaseIcon icon="ion:chevron-back" title="返回" @click="back"/>
<div class="tabs">
<div class="tab"
:class="currentTabIndex === item && 'active'"
@click="currentTabIndex = item"
v-for="item in Object.keys(dictData)">
<span>{{ formatLangType(item) }}</span>
</div>
</div>
</div>
<BaseIcon icon="lucide:search"/>
</div>
</header>
<div class="page-content">
<div class="dict-list-wrapper">
<div class="translate ">
<span>释义</span>
<el-radio-group v-model="currentTranslateLanguage2">
<el-radio-button border v-for="i in Object.keys(currentLangDictList)" :value="i">{{
formatLangType(i)
}}
</el-radio-button>
</el-radio-group>
</div>
<DictGroup
v-for="item in currentTranDictList"
:select-id="store.currentDict.id"
@selectDict="change"
:item="item"
/>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/style";
.dict-list-panel {
width: 100%;
height: 100%;
$header-height: 4rem;
//padding: var(--space);
padding-top: 0;
box-sizing: border-box;
header {
position: fixed;
top: 0;
//left: var(--aside-width);
//width: calc(100vw - var(--aside-width));
left: 0;
width: 100vw;
z-index: 9;
background: var(--color-main-bg);
.tabs {
display: flex;
gap: 1.5rem;
.tab {
color: var(--color-font-1);
cursor: pointer;
padding: .3rem;
transition: all .5s;
border-bottom: 2px solid transparent;
display: flex;
align-items: center;
gap: 0.6rem;
&.active {
$main: rgb(64, 158, 255);
border-bottom: 2px solid $main;
}
img {
height: 2rem;
}
}
}
}
.page-content {
padding-top: 4rem;
display: flex;
.dict-list-wrapper {
flex: 1;
overflow: auto;
height: 100%;
.translate {
display: flex;
align-items: center;
color: var(--color-font-1);
margin-bottom: 1rem;
& > span {
font-size: 1.2rem;
}
}
}
}
}
</style>

View File

@@ -1,191 +0,0 @@
<script setup lang="ts">
import {DictResource, getDefaultDict, Sort,} from "@/types.ts";
import {dictionaryResources} from "@/assets/dictionary.ts";
import {groupBy} from "lodash-es";
import {useBaseStore} from "@/stores/base.ts";
import DictGroup from "@/pages/pc/components/list/DictGroup.vue";
import enFlag from "@/assets/img/flags/en.png";
import jaFlag from "@/assets/img/flags/ja.png";
import deFlag from "@/assets/img/flags/de.png";
import codeFlag from "@/assets/img/flags/code.png";
import BaseIcon from "@/components/BaseIcon.vue";
import {useRouter} from "vue-router";
import {useNav} from "@/utils";
const emit = defineEmits<{
add: [],
selectDict: [val: { dict: any, index: number }]
}>()
const store = useBaseStore()
let currentLanguage = $ref('en')
let currentTranslateLanguage = $ref('common')
let groupByLanguage = groupBy(dictionaryResources, 'language')
let translateLanguageList = $ref([])
function groupByDictTags(dictList: DictResource[]) {
return dictList.reduce<Record<string, DictResource[]>>((result, dict) => {
dict.tags.forEach((tag) => {
if (Object.prototype.hasOwnProperty.call(result, tag)) {
result[tag].push(dict)
} else {
result[tag] = [dict]
}
})
return result
}, {})
}
const groupByTranslateLanguage = $computed(() => {
let data = groupBy(groupByLanguage[currentLanguage], 'translateLanguage')
// console.log('groupByTranslateLanguage', data)
translateLanguageList = Object.keys(data)
currentTranslateLanguage = translateLanguageList[0]
return data
})
const groupedByCategoryAndTag = $computed(() => {
const currentTranslateLanguageDictList = groupByTranslateLanguage[currentTranslateLanguage]
const groupByCategory = groupBy(currentTranslateLanguageDictList, 'category')
let data = []
for (const [key, value] of Object.entries(groupByCategory)) {
data.push([key, groupByDictTags(value)])
}
// console.log('groupedByCategoryAndTag', data)
return data
})
function del(e) {
store.myDictList.splice(e.index, 1)
}
const languageCategoryOptions = [
{id: 'en', name: '英语', flag: enFlag},
{id: 'ja', name: '日语', flag: jaFlag},
{id: 'de', name: '德语', flag: deFlag},
{id: 'code', name: 'Code', flag: codeFlag},
]
const {nav, back} = useNav()
function change(e) {
console.log('e', e.dict)
e.dict.sort = Sort.normal
store.changeWordDict(getDefaultDict(e.dict))
ElMessage.success('切换成功')
back()
}
</script>
<template>
<div class="dict-list-panel">
<header class="flex justify-center pb-3">
<div class="container2 flex justify-between items-center">
<div class="flex items-center gap-5">
<BaseIcon icon="ion:chevron-back" title="返回" @click="back"/>
<div class="tabs">
<div class="tab"
:class="currentLanguage === item.id && 'active'"
@click="currentLanguage = item.id"
v-for="item in languageCategoryOptions">
<img :src='item.flag' alt=""/>
<span>{{ item.name }}</span>
</div>
</div>
</div>
<BaseIcon icon="lucide:search"/>
</div>
</header>
<div class="page-content">
<div class="dict-list-wrapper">
<div class="translate ">
<span>释义</span>
<el-radio-group v-model="currentTranslateLanguage">
<el-radio-button border v-for="i in translateLanguageList" :value="i">{{ $t(i) }}</el-radio-button>
</el-radio-group>
</div>
<DictGroup
v-for="item in groupedByCategoryAndTag"
:select-id="store.currentDict.id"
@selectDict="change"
:groupByTag="item[1]"
:category="item[0]"
/>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/style";
.dict-list-panel {
width: 100%;
height: 100%;
$header-height: 4rem;
//padding: var(--space);
padding-top: 0;
box-sizing: border-box;
header {
position: fixed;
top: 0;
//left: var(--aside-width);
//width: calc(100vw - var(--aside-width));
left: 0;
width: 100vw;
z-index: 9;
background: var(--color-main-bg);
.tabs {
display: flex;
gap: 1.5rem;
.tab {
color: var(--color-font-1);
cursor: pointer;
padding: .3rem;
transition: all .5s;
border-bottom: 2px solid transparent;
display: flex;
align-items: center;
gap: 0.6rem;
&.active {
$main: rgb(64, 158, 255);
border-bottom: 2px solid $main;
}
img {
height: 2rem;
}
}
}
}
.page-content {
padding-top: 4rem;
display: flex;
.dict-list-wrapper {
flex: 1;
overflow: auto;
height: 100%;
.translate {
display: flex;
align-items: center;
color: var(--color-font-1);
margin-bottom: 1rem;
& > span {
font-size: 1.2rem;
}
}
}
}
}
</style>

View File

@@ -1,20 +1,189 @@
<script setup lang="ts">
import {useBaseStore} from "@/stores/base.ts";
import DictListPanel2 from "./DictListPanel2.vue";
import {useRouter} from "vue-router";
import BasePage from "@/pages/pc/components/BasePage.vue";
import BaseIcon from "@/components/BaseIcon.vue";
import DictGroup from "@/pages/pc/components/list/DictGroup.vue";
import enFlag from "@/assets/img/flags/en.png";
import jaFlag from "@/assets/img/flags/ja.png";
import deFlag from "@/assets/img/flags/de.png";
import codeFlag from "@/assets/img/flags/code.png";
import {useNav} from "@/utils";
import {getDefaultDict, Sort} from "@/types.ts";
import {onMounted} from "vue";
import {groupBy, uniq} from "lodash-es";
import dict from "@/assets/dict.json";
const base = useBaseStore()
const router = useRouter()
const store = useBaseStore()
const languageCategoryOptions = [
{id: 'en', name: '英语', flag: enFlag},
{id: 'ja', name: '日语', flag: jaFlag},
{id: 'de', name: '德语', flag: deFlag},
{id: 'code', name: 'Code', flag: codeFlag},
]
const {nav, back} = useNav()
function change(e) {
console.log('e', e.dict)
store.changeWordDict(getDefaultDict(e.dict))
ElMessage.success('切换成功')
back()
}
let dictData = $ref({})
let currentTabIndex = $ref('0')
let currentTranslateLanguage2 = $ref(1)
const currentLangDictList = $computed(() => {
return dictData[currentTabIndex] ?? {}
})
const currentTranDictList = $computed(() => {
return currentLangDictList[currentTranslateLanguage2] ?? {}
})
onMounted(() => {
let d: any = groupBy(dict.data, 'langType')
for (let dKey in d) {
d[dKey] = groupBy(d[dKey], 'tranType')
for (const dKey2 in d[dKey]) {
d[dKey][dKey2] = groupBy(d[dKey][dKey2], 'category')
for (const dKey3 in d[dKey][dKey2]) {
d[dKey][dKey2][dKey3] = {
tags: uniq(d[dKey][dKey2][dKey3].sort((a, b) => a.id - b.id).map(v => v.tags).flat()),
list: d[dKey][dKey2][dKey3],
name: dKey3
}
}
}
}
dictData = d
console.log('dict', d)
})
function formatLangType(val) {
switch (Number(val)) {
case 0:
return '英语'
case 1:
return '汉语'
}
}
</script>
<template>
<BasePage>
<DictListPanel2
/>
<div class="dict-list-panel">
<header class="flex justify-center pb-3">
<div class="container2 flex justify-between items-center">
<div class="flex items-center gap-5">
<BaseIcon icon="ion:chevron-back" title="返回" @click="back"/>
<div class="tabs">
<div class="tab"
:class="currentTabIndex === item && 'active'"
@click="currentTabIndex = item"
v-for="item in Object.keys(dictData)">
<span>{{ formatLangType(item) }}</span>
</div>
</div>
</div>
<BaseIcon icon="lucide:search"/>
</div>
</header>
<div class="page-content">
<div class="dict-list-wrapper">
<div class="translate ">
<span>释义</span>
<el-radio-group v-model="currentTranslateLanguage2">
<el-radio-button border v-for="i in Object.keys(currentLangDictList)" :value="i">{{
formatLangType(i)
}}
</el-radio-button>
</el-radio-group>
</div>
<DictGroup
v-for="item in currentTranDictList"
:select-id="store.currentDict.id"
@selectDict="change"
:item="item"
/>
</div>
</div>
</div>
</BasePage>
</template>
<style scoped lang="scss">
@import "@/assets/css/style";
.dict-list-panel {
width: 100%;
height: 100%;
$header-height: 4rem;
//padding: var(--space);
padding-top: 0;
box-sizing: border-box;
header {
position: fixed;
top: 0;
//left: var(--aside-width);
//width: calc(100vw - var(--aside-width));
left: 0;
width: 100vw;
z-index: 9;
background: var(--color-main-bg);
.tabs {
display: flex;
gap: 1.5rem;
.tab {
color: var(--color-font-1);
cursor: pointer;
padding: .3rem;
transition: all .5s;
border-bottom: 2px solid transparent;
display: flex;
align-items: center;
gap: 0.6rem;
&.active {
$main: rgb(64, 158, 255);
border-bottom: 2px solid $main;
}
img {
height: 2rem;
}
}
}
}
.page-content {
padding-top: 4rem;
display: flex;
.dict-list-wrapper {
flex: 1;
overflow: auto;
height: 100%;
.translate {
display: flex;
align-items: center;
color: var(--color-font-1);
margin-bottom: 1rem;
& > span {
font-size: 1.2rem;
}
}
}
}
}
</style>

View File

@@ -232,7 +232,6 @@ export function getDefaultDict(val = {}): Dict {
lastLearnIndex: 0,
perDayStudyNumber: 20,
description: '',
sort: Sort.normal,
words: [],
articles: [],
statistics: [],
@@ -240,12 +239,13 @@ export function getDefaultDict(val = {}): Dict {
length: 0,
/*资源属性*/
resourceId: '',
url: '',
fileName: '',
category: '',
tags: [],
translateLanguage: 'common',
type: DictType.word,
language: 'en',
dictType: DictType.word,
langTypeStr: 'en',
tranTypeStr: 'zh',
version: 0,
...val
}
}
@@ -256,7 +256,6 @@ export interface Dict {
lastLearnIndex: number,
perDayStudyNumber: number,
description: string,
sort: Sort,
words: Word[],
articles: Article[],
statistics: Statistics[],
@@ -266,10 +265,11 @@ export interface Dict {
resourceId: string,
category: string
tags: string[]
language: LanguageType
type: DictType
translateLanguage: TranslateLanguageType
url: string,
dictType: DictType
fileName: string,
langTypeStr: string,
tranTypeStr: string,
version: number,
}
export interface ArticleItem {

View File

@@ -129,20 +129,10 @@ export function isMobile(): boolean {
export function getDictFile(url: string) {
return new Promise<any[]>(async resolve => {
let r = await fetch(url)
let r = await fetch(url).catch(r => {
})
if (url.includes('.7z')) {
console.time()
const data = await r.arrayBuffer();
const mod = await libarchiveWasm();
const reader = new ArchiveReader(mod, new Int8Array(data));
for (const entry of reader.entries()) {
if (entry.getPathname().endsWith('.json')) {
let data = new TextDecoder().decode(entry.readData());
resolve(JSON.parse(data))
}
console.timeEnd()
}
reader.free();
} else {
let v = await r.json()
resolve(v)
@@ -173,23 +163,69 @@ export function _dateFormat(val: any, format?: string): string {
return dayjs(d).format(format)
}
export function _fetch(url: string) {
return new Promise<any[]>(async (resolve, reject) => {
await fetch(url).then(async r => {
let v = await r.json()
resolve(v)
}).catch(r => {
console.log('err', r)
reject(r)
})
})
}
export async function _checkDictWords(dict: Dict) {
console.log('_checkDictWords', dict)
if ([DictType.collect,
DictType.simple,
DictType.wrong].includes(dict.type)) {
DictType.wrong].includes(dict.dictType)) {
} else {
//TODO 需要和其他需要下载的地方统一
let url = `./dicts/${dict.language}/${dict.type}/${dict.translateLanguage}/${dict.url}`;
//TODO 需要和其他需要下载的地方统一
//如果不是自定义词典并且有url地址才去下载
if (!dict.isCustom && dict.url) {
if (!dict.words.length) {
let v = await getDictFile(url)
v.map(s => {
s.id = nanoid(6)
})
// dict.words = Object.freeze(v)
dict.words = v
if (!dict.isCustom && dict.fileName) {
let res: any = await _fetch(`http://localhost/index.php/v1/support/getDictVersion?id=${dict.id}`)
let r
let dictLocalUrl = `./dicts/${dict.langTypeStr}/${dict.dictType}/${dict.tranTypeStr}/${dict.fileName}-${dict.version}`;
let dictServeUrl = `http://localhost/index.php/v1/support/getDictDetail?id=${dict.id}`;
if (res.success) {
if (res.version > dict.version) {
let r2: any = await _fetch(dictServeUrl)
if (r2.success) {
r = r2.data
} else {
let r3 = await fetch(dictLocalUrl)
try {
r = await r3.json()
} catch (e) {
}
}
} else {
if (!dict.words.length) {
let r3 = await fetch(dictLocalUrl)
try {
r = await r3.json()
} catch (e) {
let r2: any = await _fetch(dictServeUrl)
if (r2.success) {
r = r2.data
}
}
}
}
} else {
let r3 = await fetch(dictLocalUrl)
try {
r = await r3.json()
} catch (e) {
}
}
console.log('v', r)
// // dict.words = Object.freeze(v)
// dict.words = v
dict = Object.assign(dict, r)
}
}
}