save
This commit is contained in:
@@ -6,6 +6,9 @@ import {ActivityCalendar} from "vue-activity-calendar";
|
||||
import "vue-activity-calendar/style.css";
|
||||
import {useRouter} from "vue-router";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import DictList from "@/pages/pc/components/list/DictList.vue";
|
||||
import {enArticle} from "@/assets/dictionary.ts";
|
||||
import {DictType} from "@/types.ts";
|
||||
|
||||
const base = useBaseStore()
|
||||
const router = useRouter()
|
||||
@@ -19,18 +22,24 @@ function clickEvent(e) {
|
||||
<div class="word flex justify-center ">
|
||||
<div class="w-5/10 pt-5">
|
||||
<div class="flex gap-6">
|
||||
<div class="card w-1/2 flex flex-col">
|
||||
<div class="card w-1/4 flex flex-col">
|
||||
<div class="title">
|
||||
我的词典
|
||||
</div>
|
||||
<div class="grid flex-1 flex gap-5 mt-4">
|
||||
<div class="p-4 flex-1 rounded-md bg-slate-200 relative" v-for="i in 3">
|
||||
<div class="p-4 flex-1 rounded-md bg-slate-200 relative">
|
||||
<span>收藏</span>
|
||||
<div class="absolute bottom-4 right-4">333个词</div>
|
||||
<div class="absolute bottom-4 right-4">3篇</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid flex-1 flex gap-5 mt-4">
|
||||
<div class="p-4 flex-1 rounded-md bg-slate-200 relative">
|
||||
<span>添加</span>
|
||||
<div class="absolute bottom-4 right-4">3篇</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1/2">
|
||||
<div class="w-3/4">
|
||||
<div class="card ">
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="bg-slate-200 p-3 rounded-md cursor-pointer flex items-center">
|
||||
@@ -39,39 +48,30 @@ function clickEvent(e) {
|
||||
<Icon icon="uil:setting" class="text-2xl ml-2"/>
|
||||
</div>
|
||||
<div class="rounded-xl bg-slate-800 flex items-center py-3 px-5 text-white cursor-pointer"
|
||||
@click="router.push('/practice')">
|
||||
@click="router.push('/learn-article')">
|
||||
开始学习
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 text-sm">已学习5555个单词的1%</div>
|
||||
<el-progress class="mt-1" percentage="80" :show-text="false"></el-progress>
|
||||
<el-progress class="mt-1" :percentage="80" :show-text="false"></el-progress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="flex justify-between">
|
||||
<div class="title">
|
||||
其他学习词典
|
||||
</div>
|
||||
<BaseIcon icon="ic:round-add" @click="router.push('/dict')"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-6 mt-5 ">
|
||||
<div class=" p-4 rounded-md justify-between items-center bg-slate-200 " v-for="i in 3">
|
||||
<div class="flex justify-between w-full">
|
||||
<span>{{ base.currentDict.name }}</span>
|
||||
<div class="text-2xl ml-2 flex gap-4">
|
||||
<Icon icon="hugeicons:delete-02"/>
|
||||
<Icon icon="nonicons:go-16"/>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<div class="title">文章</div>
|
||||
<div class="mt-4 flex gap-4">
|
||||
<div
|
||||
class="bg-white rounded-md p-4 h-40 w-30 relative cursor-pointer"
|
||||
v-for="dict in enArticle"
|
||||
>
|
||||
<div class="top">
|
||||
<div class="name">{{ dict.name }}</div>
|
||||
<div class="desc">{{ dict.description }}</div>
|
||||
</div>
|
||||
<div class="mt-5 text-sm">已学习5555个单词的1%</div>
|
||||
<el-progress class="mt-1" percentage="80" color="white" :show-text="false"></el-progress>
|
||||
<div class="absolute bottom-4 right-4">{{ dict.length }}篇</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-center mt-2 text-2xl">
|
||||
<Icon icon="mingcute:down-line"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
163
src/pages/pc/article/LearnArticle.vue
Normal file
163
src/pages/pc/article/LearnArticle.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import Toolbar from "@/pages/pc/components/toolbar/index.vue"
|
||||
import {onMounted, onUnmounted, watch} from "vue";
|
||||
import {usePracticeStore} from "@/stores/practice.ts";
|
||||
import Footer from "@/pages/pc/practice/Footer.vue";
|
||||
import {useBaseStore} from "@/stores/base.ts";
|
||||
|
||||
import Statistics from "@/pages/pc/practice/Statistics.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {MessageBox} from "@/utils/MessageBox.tsx";
|
||||
import PracticeArticle from "@/pages/pc/practice/practice-article/index.vue";
|
||||
import {ShortcutKey} from "@/types.ts";
|
||||
import DictModal from "@/pages/pc/components/dialog/DictDiglog.vue";
|
||||
import {useStartKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import useTheme from "@/hooks/theme.ts";
|
||||
|
||||
const practiceStore = usePracticeStore()
|
||||
const store = useBaseStore()
|
||||
const settingStore = useSettingStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
const {toggleTheme} = useTheme()
|
||||
const practiceRef: any = $ref()
|
||||
|
||||
watch(practiceStore, () => {
|
||||
if (practiceStore.inputWordNumber < 1) {
|
||||
return practiceStore.correctRate = -1
|
||||
}
|
||||
if (practiceStore.wrongWordNumber > practiceStore.inputWordNumber) {
|
||||
return practiceStore.correctRate = 0
|
||||
}
|
||||
practiceStore.correctRate = 100 - Math.trunc(((practiceStore.wrongWordNumber) / (practiceStore.inputWordNumber)) * 100)
|
||||
})
|
||||
|
||||
|
||||
function test() {
|
||||
MessageBox.confirm(
|
||||
'2您选择了“本地翻译”,但译文内容却为空白,是否修改为“不需要翻译”并保存?',
|
||||
'1提示',
|
||||
() => {
|
||||
console.log('ok')
|
||||
},
|
||||
() => {
|
||||
console.log('cencal')
|
||||
})
|
||||
}
|
||||
|
||||
function write() {
|
||||
// console.log('write')
|
||||
settingStore.dictation = true
|
||||
repeat()
|
||||
}
|
||||
|
||||
//TODO 需要判断是否已忽略
|
||||
function repeat() {
|
||||
// console.log('repeat')
|
||||
emitter.emit(EventKey.resetWord)
|
||||
practiceRef.getCurrentPractice()
|
||||
}
|
||||
|
||||
function prev() {
|
||||
// console.log('next')
|
||||
if (store.currentDict.chapterIndex === 0) {
|
||||
ElMessage.warning('已经在第一章了~')
|
||||
} else {
|
||||
store.currentDict.chapterIndex--
|
||||
repeat()
|
||||
}
|
||||
}
|
||||
|
||||
function toggleShowTranslate() {
|
||||
settingStore.translate = !settingStore.translate
|
||||
}
|
||||
|
||||
function toggleDictation() {
|
||||
settingStore.dictation = !settingStore.dictation
|
||||
}
|
||||
|
||||
function openSetting() {
|
||||
runtimeStore.showSettingModal = true
|
||||
}
|
||||
|
||||
function openDictDetail() {
|
||||
emitter.emit(EventKey.openDictModal, 'detail')
|
||||
}
|
||||
|
||||
function toggleConciseMode() {
|
||||
settingStore.showToolbar = !settingStore.showToolbar
|
||||
settingStore.showPanel = settingStore.showToolbar
|
||||
}
|
||||
|
||||
function togglePanel() {
|
||||
settingStore.showPanel = !settingStore.showPanel
|
||||
}
|
||||
|
||||
function jumpSpecifiedChapter(val: number) {
|
||||
store.currentDict.chapterIndex = val
|
||||
repeat()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
emitter.on(EventKey.write, write)
|
||||
emitter.on(EventKey.repeat, repeat)
|
||||
emitter.on(EventKey.jumpSpecifiedChapter, jumpSpecifiedChapter)
|
||||
|
||||
emitter.on(ShortcutKey.PreviousChapter, prev)
|
||||
emitter.on(ShortcutKey.RepeatChapter, repeat)
|
||||
emitter.on(ShortcutKey.DictationChapter, write)
|
||||
emitter.on(ShortcutKey.ToggleShowTranslate, toggleShowTranslate)
|
||||
emitter.on(ShortcutKey.ToggleDictation, toggleDictation)
|
||||
emitter.on(ShortcutKey.OpenSetting, openSetting)
|
||||
emitter.on(ShortcutKey.OpenDictDetail, openDictDetail)
|
||||
emitter.on(ShortcutKey.ToggleTheme, toggleTheme)
|
||||
emitter.on(ShortcutKey.ToggleConciseMode, toggleConciseMode)
|
||||
emitter.on(ShortcutKey.TogglePanel, togglePanel)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
emitter.off(EventKey.write, write)
|
||||
emitter.off(EventKey.repeat, repeat)
|
||||
emitter.off(EventKey.jumpSpecifiedChapter, jumpSpecifiedChapter)
|
||||
|
||||
emitter.off(ShortcutKey.PreviousChapter, prev)
|
||||
emitter.off(ShortcutKey.RepeatChapter, repeat)
|
||||
emitter.off(ShortcutKey.DictationChapter, write)
|
||||
emitter.off(ShortcutKey.ToggleShowTranslate, toggleShowTranslate)
|
||||
emitter.off(ShortcutKey.ToggleDictation, toggleDictation)
|
||||
emitter.off(ShortcutKey.OpenSetting, openSetting)
|
||||
emitter.off(ShortcutKey.OpenDictDetail, openDictDetail)
|
||||
emitter.off(ShortcutKey.ToggleTheme, toggleTheme)
|
||||
emitter.off(ShortcutKey.ToggleConciseMode, toggleConciseMode)
|
||||
emitter.off(ShortcutKey.TogglePanel, togglePanel)
|
||||
})
|
||||
|
||||
useStartKeyboardEventListener()
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="practice-wrapper">
|
||||
<PracticeArticle ref="practiceRef"/>
|
||||
<Footer/>
|
||||
</div>
|
||||
<DictModal/>
|
||||
<Statistics/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.practice-wrapper {
|
||||
font-size: 0.9rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
//padding-right: var(--practice-wrapper-padding-right);
|
||||
transform: translateX(var(--practice-wrapper-translateX));
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="jsx">
|
||||
import {nextTick, Teleport, Transition} from "vue";
|
||||
import {nextTick} from "vue";
|
||||
|
||||
export default {
|
||||
name: "PopConfirm",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="jsx">
|
||||
import {nextTick, Teleport, Transition} from "vue";
|
||||
|
||||
export default {
|
||||
name: "Tooltip",
|
||||
@@ -29,7 +28,7 @@ export default {
|
||||
e.stopPropagation()
|
||||
let rect = e.target.getBoundingClientRect()
|
||||
this.show = true
|
||||
nextTick(() => {
|
||||
this.$nextTick(() => {
|
||||
let tip = this.$refs?.tip?.getBoundingClientRect()
|
||||
if (!tip) return
|
||||
if (rect.top < 50) {
|
||||
|
||||
@@ -9,6 +9,11 @@ import {cloneDeep} from "lodash-es";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
import {useArticleOptions} from "@/hooks/dict.ts";
|
||||
import IconWrapper from "@/pages/pc/components/IconWrapper.vue";
|
||||
import Tooltip from "@/pages/pc/components/Tooltip.vue";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import TranslateSetting from "@/pages/pc/components/toolbar/TranslateSetting.vue";
|
||||
import VolumeSetting from "@/pages/pc/components/toolbar/VolumeSetting.vue";
|
||||
|
||||
interface IProps {
|
||||
article: Article,
|
||||
@@ -340,12 +345,30 @@ defineExpose({showSentence, play, del,hideSentence,nextSentence})
|
||||
<div class="title word">{{ props.article.title }}</div>
|
||||
<div class="titleTranslate" v-if="settingStore.translate">{{ props.article.titleTranslate }}</div>
|
||||
<div class="options-wrapper">
|
||||
<div class="flex gap10">
|
||||
<div class="flex gap-1">
|
||||
<Tooltip
|
||||
:title="`开关默写模式(${settingStore.shortcutKeyMap[ShortcutKey.ToggleDictation]})`"
|
||||
>
|
||||
<IconWrapper>
|
||||
<Icon icon="majesticons:eye-off-line"
|
||||
v-if="settingStore.dictation"
|
||||
@click="settingStore.dictation = false"/>
|
||||
<Icon icon="mdi:eye-outline"
|
||||
v-else
|
||||
@click="settingStore.dictation = true"/>
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
|
||||
<TranslateSetting/>
|
||||
|
||||
<VolumeSetting/>
|
||||
|
||||
<BaseIcon
|
||||
:title="`编辑(${settingStore.shortcutKeyMap[ShortcutKey.EditArticle]})`"
|
||||
icon="tabler:edit"
|
||||
@click="emit('edit',props.article)"
|
||||
/>
|
||||
|
||||
<BaseIcon
|
||||
v-if="!isArticleCollect(props.article)"
|
||||
class="collect"
|
||||
@@ -359,7 +382,7 @@ defineExpose({showSentence, play, del,hideSentence,nextSentence})
|
||||
:title="`取消收藏(${settingStore.shortcutKeyMap[ShortcutKey.ToggleCollect]})`"
|
||||
icon="ph:star-fill"/>
|
||||
<BaseIcon
|
||||
:title="`跳过(${settingStore.shortcutKeyMap[ShortcutKey.Next]})`"
|
||||
:title="`下一句(${settingStore.shortcutKeyMap[ShortcutKey.Next]})`"
|
||||
icon="icon-park-outline:go-ahead"
|
||||
@click="emit('over')"/>
|
||||
</div>
|
||||
@@ -450,28 +473,31 @@ $article-width: 1000px;
|
||||
header {
|
||||
word-wrap: break-word;
|
||||
position: relative;
|
||||
padding: 15rem 0;
|
||||
padding: .9rem 0;
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: rgba(gray, .8);
|
||||
font-size: 36rem;
|
||||
font-size: 2.2rem;
|
||||
font-family: var(--word-font-family);
|
||||
}
|
||||
|
||||
.titleTranslate {
|
||||
@extend .title;
|
||||
font-size: 20rem;
|
||||
font-size: 1.2rem;
|
||||
font-family: unset;
|
||||
}
|
||||
|
||||
.options-wrapper {
|
||||
position: absolute;
|
||||
right: 20rem;
|
||||
//position: absolute;
|
||||
right: 1.2rem;
|
||||
top: 0;
|
||||
display: flex;
|
||||
gap: 10rem;
|
||||
font-size: 18rem;
|
||||
margin-top: 1rem;
|
||||
justify-content: center;
|
||||
gap: .6rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,13 +508,13 @@ $article-width: 1000px;
|
||||
|
||||
article {
|
||||
//height: 100%;
|
||||
font-size: 24rem;
|
||||
font-size: 1.6rem;
|
||||
line-height: 2.5;
|
||||
color: gray;
|
||||
word-break: keep-all;
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
padding-top: 20rem;
|
||||
padding-top: 1.2rem;
|
||||
|
||||
.section {
|
||||
font-family: var(--word-font-family);
|
||||
@@ -498,11 +524,11 @@ $article-width: 1000px;
|
||||
transition: all .3s;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 50rem;
|
||||
padding-left: .2rem;
|
||||
}
|
||||
|
||||
&.dictation {
|
||||
letter-spacing: 3rem;
|
||||
letter-spacing: .2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,10 +545,10 @@ $article-width: 1000px;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 18rem;
|
||||
font-size: 1.1rem;
|
||||
color: gray;
|
||||
line-height: 3.5;
|
||||
letter-spacing: 3rem;
|
||||
letter-spacing: .2rem;
|
||||
//display: none;
|
||||
|
||||
.row {
|
||||
@@ -545,20 +571,20 @@ $article-width: 1000px;
|
||||
&::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
width: 1.5rem;
|
||||
height: 4rem;
|
||||
width: .1rem;
|
||||
height: .25rem;
|
||||
background: gray;
|
||||
bottom: 2rem;
|
||||
right: 2.5rem;
|
||||
bottom: .12rem;
|
||||
right: .25rem;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
width: 1.5rem;
|
||||
height: 4rem;
|
||||
width: .1rem;
|
||||
height: .26rem;
|
||||
background: gray;
|
||||
bottom: 2rem;
|
||||
bottom: .12rem;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
@@ -591,10 +617,10 @@ $article-width: 1000px;
|
||||
|
||||
@keyframes underline {
|
||||
0%, 100% {
|
||||
border-left: 1.3rem solid black;
|
||||
border-left: .1rem solid black;
|
||||
}
|
||||
50% {
|
||||
border-left: 1.3rem solid transparent;
|
||||
border-left: .1rem solid transparent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ function init() {
|
||||
if (!store.currentDict.articles.length) return
|
||||
articleData.articles = cloneDeep(store.currentDict.articles)
|
||||
getCurrentPractice()
|
||||
console.log('inin', articleData.article)
|
||||
|
||||
}
|
||||
|
||||
function setArticle(val: Article) {
|
||||
@@ -95,7 +97,7 @@ function getCurrentPractice() {
|
||||
tabIndex = 0
|
||||
articleData.article = cloneDeep(DefaultArticle)
|
||||
|
||||
let currentArticle = articleData.articles [store.currentDict.chapterIndex]
|
||||
let currentArticle = articleData.articles[store.currentDict.chapterIndex]
|
||||
let tempArticle = {...DefaultArticle, ...currentArticle}
|
||||
// console.log('article', tempArticle)
|
||||
if (tempArticle.sections.length) {
|
||||
|
||||
@@ -44,7 +44,7 @@ function clickEvent(e) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 text-sm">已学习5555个单词的1%</div>
|
||||
<el-progress class="mt-1" percentage="80" :show-text="false"></el-progress>
|
||||
<el-progress class="mt-1" :percentage="80" :show-text="false"></el-progress>
|
||||
</div>
|
||||
<div class="card flex gap-3">
|
||||
<div class="bg-slate-200 w-10 h-10 flex center text-2xl rounded">
|
||||
@@ -60,7 +60,7 @@ function clickEvent(e) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 text-xs">学习 50 个单词</div>
|
||||
<el-progress class="flex-1 mt-1" percentage="80" :show-text="false"></el-progress>
|
||||
<el-progress class="flex-1 mt-1" :percentage="80" :show-text="false"></el-progress>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -83,7 +83,7 @@ function clickEvent(e) {
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 text-sm">已学习5555个单词的1%</div>
|
||||
<el-progress class="mt-1" percentage="80" color="white" :show-text="false"></el-progress>
|
||||
<el-progress class="mt-1" :percentage="80" color="white" :show-text="false"></el-progress>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-center mt-2 text-2xl">
|
||||
|
||||
Reference in New Issue
Block a user