Merge remote-tracking branch 'origin/master'
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -16,6 +16,7 @@ declare module 'vue' {
|
||||
BaseList: typeof import('./src/components/list/BaseList.vue')['default']
|
||||
ChapterName: typeof import('./src/components/toolbar/ChapterName.vue')['default']
|
||||
Close: typeof import('./src/components/icon/Close.vue')['default']
|
||||
CollectNotice: typeof import('./src/components/CollectNotice.vue')['default']
|
||||
Dialog: typeof import('./src/components/dialog/Dialog.vue')['default']
|
||||
DictDiglog: typeof import('./src/components/dialog/DictDiglog.vue')['default']
|
||||
DictGroup: typeof import('./src/components/list/DictGroup.vue')['default']
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as localforage from "localforage";
|
||||
import SettingDialog from "@/components/dialog/SettingDialog.vue";
|
||||
import ArticleContentDialog from "@/components/dialog/ArticleContentDialog.vue";
|
||||
import {useStartKeyboardEventListener} from "@/hooks/event.ts";
|
||||
import CollectNotice from "@/components/CollectNotice.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
@@ -91,6 +92,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<Backgorund/>
|
||||
<router-view/>
|
||||
<CollectNotice/>
|
||||
<ArticleContentDialog/>
|
||||
<SettingDialog v-if="runtimeStore.showSettingModal" @close="runtimeStore.showSettingModal = false"/>
|
||||
</template>
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
--toolbar-height: 54rem;
|
||||
--panel-width: 400rem;
|
||||
--space: 20rem;
|
||||
--radius: 8rem;
|
||||
--shadow: rgba(17, 17, 26, 0.05) 0px 4px 16px, rgba(17, 17, 26, 0.05) 0px 8px 32px;
|
||||
--shadow: rgba(0, 0, 0, 0.08) 0px 4px 12px;;
|
||||
--panel-margin-left: calc(50% - var(--practice-wrapper-translateX) / 2 + var(--toolbar-width) / 2 + 24rem);
|
||||
--article-panel-margin-left: calc(50% - var(--practice-wrapper-translateX) / 2 + var(--article-width) / 2 + 24rem);
|
||||
--anim-time: 0.5s;
|
||||
@@ -156,7 +159,7 @@ html, body {
|
||||
}
|
||||
|
||||
a {
|
||||
$main: rgb(64,158,255);
|
||||
$main: rgb(64, 158, 255);
|
||||
color: $main;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,10 @@ defineEmits(['click'])
|
||||
&.large {
|
||||
height: 50rem;
|
||||
font-size: 18rem;
|
||||
padding: 0 18rem;
|
||||
padding: 0 22rem;
|
||||
& > span {
|
||||
font-size: 18rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
181
src/components/CollectNotice.vue
Normal file
181
src/components/CollectNotice.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Close from "@/components/icon/Close.vue";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {watch} from "vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
|
||||
let settingStore = useSettingStore()
|
||||
let showNotice = $ref(false)
|
||||
let show = $ref(false)
|
||||
let num = $ref(5)
|
||||
let timer = -1
|
||||
|
||||
function toggleNotice() {
|
||||
showNotice = true
|
||||
timer = setInterval(() => {
|
||||
num--
|
||||
if (num <= 0) {
|
||||
show = settingStore.first = false
|
||||
clearInterval(timer)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
function close() {
|
||||
clearInterval(timer)
|
||||
show = settingStore.first = false
|
||||
}
|
||||
|
||||
watch(() => settingStore.load, (n) => {
|
||||
if (n && settingStore.first) {
|
||||
show = true
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<transition name="right">
|
||||
<div class="CollectNotice" v-if="show">
|
||||
<div class="notice">
|
||||
坚持练习,提高外语能力。将
|
||||
<span class="active">「Typing Word」</span>
|
||||
保存到收藏夹,永不迷失!
|
||||
</div>
|
||||
<div class="wrapper">
|
||||
<transition name="fade">
|
||||
<div class="collect" v-if="showNotice">
|
||||
<div class="href-wrapper">
|
||||
<div class="round">
|
||||
<div class="href">typing-word.ttentau.top</div>
|
||||
<Icon
|
||||
width="22"
|
||||
icon="mdi:star-outline"/>
|
||||
</div>
|
||||
<div class="right">
|
||||
👈
|
||||
<Icon
|
||||
class="star"
|
||||
width="22"
|
||||
icon="mdi:star"/>
|
||||
点亮它!
|
||||
</div>
|
||||
</div>
|
||||
<div class="collect-keyboard">或使用收藏快捷键<span class="active">Ctrl + D</span></div>
|
||||
</div>
|
||||
<BaseButton v-else size="large" @click="toggleNotice">我想收藏</BaseButton>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="close-wrapper">
|
||||
<span v-show="showNotice"><span class="active">{{ num }}s</span> 后自动关闭</span>
|
||||
<Close @click="close" title="关闭"/>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.right-enter-active,
|
||||
.right-leave-active {
|
||||
transition: all .5s ease;
|
||||
}
|
||||
|
||||
.right-enter-from,
|
||||
.right-leave-to {
|
||||
transform: translateX(110%);
|
||||
}
|
||||
|
||||
.CollectNotice {
|
||||
position: fixed;
|
||||
right: var(--space);
|
||||
top: var(--space);
|
||||
z-index: 2;
|
||||
font-size: 20rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
background: var(--color-second-bg);
|
||||
padding: 30rem;
|
||||
border-radius: 12rem;
|
||||
width: 500rem;
|
||||
gap: 40rem;
|
||||
color: var(--color-font-1);
|
||||
line-height: 1.5;
|
||||
border: 1px solid var(--color-item-border);
|
||||
box-shadow: var(--shadow);
|
||||
|
||||
.notice {
|
||||
margin-top: 30rem;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: var(--color-main-active);
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
.collect {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.href-wrapper {
|
||||
display: flex;
|
||||
font-size: 16rem;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
|
||||
.round {
|
||||
color: var(--color-font-1);
|
||||
border-radius: 50rem;
|
||||
padding: 10rem 10rem;
|
||||
padding-left: 20rem;
|
||||
gap: 30rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: var(--color-main-bg);
|
||||
|
||||
.href {
|
||||
font-size: 14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.star {
|
||||
color: var(--color-main-active);
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.collect-keyboard {
|
||||
margin-top: 20rem;
|
||||
font-size: 16rem;
|
||||
|
||||
span {
|
||||
margin-left: 10rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close-wrapper {
|
||||
right: var(--space);
|
||||
top: var(--space);
|
||||
position: absolute;
|
||||
font-size: 14rem;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
color: var(--color-font-1);
|
||||
gap: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -18,10 +18,7 @@ const settingStore = useSettingStore()
|
||||
|
||||
<template>
|
||||
<div class="right-bar">
|
||||
<BaseIcon
|
||||
@click="showFeedbackModal = true"
|
||||
title="反馈"
|
||||
icon="ph:bug-beetle"/>
|
||||
|
||||
|
||||
<Tooltip
|
||||
:title="`切换主题(快捷键:${settingStore.shortcutKeyMap[ShortcutKey.ToggleTheme]})`"
|
||||
@@ -39,7 +36,6 @@ const settingStore = useSettingStore()
|
||||
icon="mdi:github"/>
|
||||
</a>
|
||||
</div>
|
||||
<FeedbackModal v-if="showFeedbackModal" @close="showFeedbackModal = false"/>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -257,7 +257,7 @@ $header-height: 60rem;
|
||||
.window {
|
||||
//width: 75vw;
|
||||
//height: 70vh;
|
||||
box-shadow: var(--color-main-bg) 0 0 6rem 0;
|
||||
box-shadow: var(--shadow);
|
||||
border-radius: $radius;
|
||||
animation: bounce-in $time ease-out;
|
||||
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import {Icon} from "@iconify/vue";
|
||||
import Tooltip from "@/components/Tooltip.vue";
|
||||
|
||||
defineEmits(['click'])
|
||||
defineProps<{
|
||||
title?: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="close"
|
||||
@click="$emit('click')"
|
||||
>
|
||||
<Icon icon="ic:round-close"
|
||||
width="20"
|
||||
/>
|
||||
<Tooltip :title="title">
|
||||
<Icon icon="carbon:close-outline"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -20,5 +25,6 @@ defineEmits(['click'])
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18rem;
|
||||
}
|
||||
</style>
|
||||
@@ -18,6 +18,7 @@ import {$ref} from "vue/macros";
|
||||
import {DictType, ShortcutKey} from "@/types.ts";
|
||||
import ChapterName from "@/components/toolbar/ChapterName.vue";
|
||||
import {emitter, EventKey} from "@/utils/eventBus.ts";
|
||||
import BaseIcon from "@/components/BaseIcon.vue";
|
||||
|
||||
const {toggleTheme} = useTheme()
|
||||
const store = useBaseStore()
|
||||
@@ -113,7 +114,10 @@ watch(() => store.load, n => {
|
||||
</IconWrapper>
|
||||
</Tooltip>
|
||||
|
||||
|
||||
<BaseIcon
|
||||
@click="showFeedbackModal = true"
|
||||
title="反馈"
|
||||
icon="ph:bug-beetle"/>
|
||||
|
||||
|
||||
|
||||
@@ -149,6 +153,8 @@ watch(() => store.load, n => {
|
||||
color="#999"/>
|
||||
</Tooltip>
|
||||
</header>
|
||||
<FeedbackModal v-if="showFeedbackModal" @close="showFeedbackModal = false"/>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -203,6 +209,7 @@ header {
|
||||
gap: 10rem;
|
||||
border: 1px solid var(--color-item-border);
|
||||
transition: all var(--anim-time);
|
||||
box-shadow: var(--shadow);
|
||||
|
||||
.content {
|
||||
min-height: var(--toolbar-height);
|
||||
|
||||
@@ -104,6 +104,7 @@ onUnmounted(() => {
|
||||
padding: 3rem var(--space) 6rem var(--space);
|
||||
z-index: 2;
|
||||
border: 1px solid var(--color-item-border);
|
||||
box-shadow: var(--shadow);
|
||||
|
||||
.stat {
|
||||
margin-top: 8rem;
|
||||
|
||||
@@ -272,6 +272,7 @@ $header-height: 50rem;
|
||||
transition: all .3s;
|
||||
z-index: 1;
|
||||
border: 1px solid var(--color-item-border);
|
||||
box-shadow: var(--shadow);
|
||||
|
||||
|
||||
& > header {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {splitEnArticle} from "@/hooks/article.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
|
||||
let data = {
|
||||
"title": "A cold welcome",
|
||||
@@ -25,14 +27,21 @@ let data = {
|
||||
// "id": "TdAAqD"
|
||||
// }
|
||||
splitEnArticle(data.text)
|
||||
const settingStore = useSettingStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="page">
|
||||
test
|
||||
<BaseButton @click="settingStore.load = !settingStore.load">test</BaseButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.page {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: 14rem;
|
||||
color: black;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
import {defineStore} from "pinia"
|
||||
import {cloneDeep} from "lodash-es";
|
||||
import {cloneDeep, merge} from "lodash-es";
|
||||
import {DefaultShortcutKeyMap, SaveConfig} from "@/types.ts";
|
||||
|
||||
export interface SettingState {
|
||||
@@ -36,7 +36,9 @@ export interface SettingState {
|
||||
theme: string,
|
||||
collapse: boolean,
|
||||
chapterWordNumber: number,
|
||||
shortcutKeyMap: Record<string, string>
|
||||
shortcutKeyMap: Record<string, string>,
|
||||
first: boolean
|
||||
load: boolean
|
||||
}
|
||||
|
||||
export const DefaultChapterWordNumber = 30
|
||||
@@ -78,14 +80,18 @@ export const useSettingStore = defineStore('setting', {
|
||||
theme: 'auto',
|
||||
collapse: false,
|
||||
chapterWordNumber: DefaultChapterWordNumber,
|
||||
shortcutKeyMap: cloneDeep(DefaultShortcutKeyMap)
|
||||
shortcutKeyMap: cloneDeep(DefaultShortcutKeyMap),
|
||||
first: true,
|
||||
load: false
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setState(obj: any) {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
this[key] = value
|
||||
}
|
||||
// for (const [key, value] of Object.entries(obj)) {
|
||||
// this[key] = value
|
||||
// }
|
||||
//这样不会丢失watch的值的引用
|
||||
merge(this, obj)
|
||||
},
|
||||
init() {
|
||||
return new Promise(resolve => {
|
||||
@@ -99,6 +105,7 @@ export const useSettingStore = defineStore('setting', {
|
||||
if (!obj.version) {
|
||||
setDefaultConfig()
|
||||
} else {
|
||||
obj.val.load = false
|
||||
if (obj.version !== SaveConfig.version) {
|
||||
for (const [key, value] of Object.entries(this.shortcutKeyMap)) {
|
||||
if (obj.val.shortcutKeyMap[key]) this.shortcutKeyMap[key] = obj.val.shortcutKeyMap[key]
|
||||
@@ -120,6 +127,7 @@ export const useSettingStore = defineStore('setting', {
|
||||
setDefaultConfig()
|
||||
}
|
||||
}
|
||||
this.load = true
|
||||
resolve(true)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user