添加文章

This commit is contained in:
zyronon
2023-08-30 16:13:11 +08:00
parent ba729f0c0f
commit 3b84d8e3a9
8 changed files with 249 additions and 157 deletions

View File

@@ -8,6 +8,8 @@ import Backgorund from "@/components/Backgorund.vue";
import {onMounted, watch} from "vue";
import {useBaseStore} from "@/stores/base.ts";
import {SaveKey} from "@/types.ts"
import Footer from "@/components/Footer.vue"
import TypeArticle from "@/components/TypeArticle.vue"
const store = useBaseStore()
// 查询当前系统主题颜色
@@ -34,13 +36,15 @@ onMounted(() => {
</script>
<template>
<!-- <Backgorund/>-->
<!-- <Backgorund/>-->
<div class="main-page">
<div class="center">
<Toolbar/>
<div class="content">
<Type/>
<!-- <Type/>-->
<TypeArticle/>
</div>
<Footer/>
<Side/>
</div>
<Statistics></Statistics>
@@ -62,7 +66,7 @@ onMounted(() => {
background-color: var(--color-main-bg);
.center {
width: 70vw;
width: var(--toolbar-width);
height: 100%;
display: flex;
flex-direction: column;
@@ -71,12 +75,13 @@ onMounted(() => {
position: relative;
.content {
width: 100%;
position: relative;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
}
}

View File

@@ -126,8 +126,8 @@ onMounted(() => {
_move() {
let dx = this.boomArea.x - this.x,
dy = this.boomArea.y - this.y;
this.x = this.x + dx * 0.01;
this.y = this.y + dy * 0.01;
this.x = this.x + dx * 0.02;
this.y = this.y + dy * 0.02;
// console.log(this.x, this.y, dx, this.ba)
if (Math.abs(dx) <= this.ba && Math.abs(dy) <= this.ba) {

156
src/components/Footer.vue Normal file
View File

@@ -0,0 +1,156 @@
<script setup lang="ts">
import {$computed, $ref} from "vue/macros"
import {onMounted, onUnmounted} from "vue"
import {useBaseStore} from "@/stores/base.ts"
import Tooltip from "@/components/Tooltip.vue"
import {Down} from "@icon-park/vue-next"
const store = useBaseStore()
function format(val: number, suffix: string = '') {
return val === -1 ? '-' : (val + suffix)
}
const progress = $computed(() => {
if (!store.chapter.length) return 0
return ((store.current.index / store.current.words.length) * 100)
})
let speedMinute = $ref(0)
let timer = $ref(0)
onMounted(() => {
timer = setInterval(() => {
speedMinute = Math.floor((Date.now() - store.current.statistics.startDate) / 1000 / 60)
}, 1000)
})
onUnmounted(() => {
timer && clearInterval(timer)
})
</script>
<template>
<div class="footer" :class="!store.setting.showToolbar && 'hide'">
<Tooltip :title="store.setting.showToolbar?'收起':'展开'">
<Down
@click="store.setting.showToolbar = !store.setting.showToolbar"
class="arrow"
:class="!store.setting.showToolbar && 'down'"
theme="outline" size="24" fill="#999"/>
</Tooltip>
<div class="bottom">
<el-progress :percentage="progress"
:stroke-width="8"
:show-text="false"/>
<div class="stat">
<div class="row">
<div class="num">{{ speedMinute }}分钟</div>
<div class="line"></div>
<div class="name">时间</div>
</div>
<div class="row">
<div class="num">{{ store.current.words.length }}</div>
<div class="line"></div>
<div class="name">单词总数</div>
</div>
<div class="row">
<div class="num">{{ store.current.index }}</div>
<div class="line"></div>
<div class="name">输入数</div>
</div>
<div class="row">
<div class="num">{{ format(store.current.wrongWords.length) }}</div>
<div class="line"></div>
<div class="name">错误数</div>
</div>
<div class="row">
<div class="num">{{ format(store.current.statistics.correctRate, '%') }}</div>
<div class="line"></div>
<div class="name">正确率</div>
</div>
</div>
</div>
<div class="progress">
<el-progress :percentage="progress"
:stroke-width="8"
:show-text="false"/>
</div>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/colors.scss";
.footer {
width: 100%;
margin-bottom: 30rem;
transition: all .3s;
position: relative;
margin-top: 30rem;
&.hide {
margin-bottom: -90rem;
margin-top: 65rem;
.arrow {
transform: translate3d(-50%, -220%, 0) rotate(180deg);
}
.progress {
bottom: calc(100% + 30rem);
}
}
.arrow {
position: absolute;
top: 0;
left: 50%;
cursor: pointer;
transition: all .3s;
transform: translate3d(-50%, -100%, 0) rotate(0);
padding: 5rem;
}
.bottom {
position: relative;
width: 100%;
box-sizing: border-box;
border-radius: 10rem;
background: var(--color-header-bg);
padding: 2rem 10rem 10rem 10rem;
z-index: 2;
.stat {
margin-top: 10rem;
display: flex;
justify-content: space-around;
.row {
display: flex;
flex-direction: column;
align-items: center;
gap: 10rem;
width: 80rem;
.line {
height: 1px;
width: 100%;
background: gainsboro;
}
}
}
}
.progress {
width: 100%;
transition: all .3s;
padding: 0 10rem;
box-sizing: border-box;
position: absolute;
bottom: 0;
}
}
</style>

View File

@@ -113,9 +113,7 @@ const skipWordDictActiveIndex = computed(() => {
:title="`确认切换?`"
@confirm="store.changeDict(store.dict)"
>
<div class="my-button">
切换
</div>
<BaseButton>切换</BaseButton>
</PopConfirm>
</footer>
</div>
@@ -136,9 +134,7 @@ const skipWordDictActiveIndex = computed(() => {
:title="`确认切换?`"
@confirm="store.changeDict(store.newWordDict)"
>
<div class="my-button">
切换
</div>
<BaseButton>切换</BaseButton>
</PopConfirm>
</footer>
</div>
@@ -161,9 +157,7 @@ const skipWordDictActiveIndex = computed(() => {
:title="`确认切换?`"
@confirm="store.changeDict(store.wrongWordDict)"
>
<BaseButton>
切换
</BaseButton>
<BaseButton>切换</BaseButton>
</PopConfirm>
</footer>
</div>
@@ -184,9 +178,7 @@ const skipWordDictActiveIndex = computed(() => {
:title="`确认切换?`"
@confirm="store.changeDict(store.skipWordDict)"
>
<div class="my-button hvr-grow">
切换
</div>
<BaseButton>切换</BaseButton>
</PopConfirm>
</footer>
</div>
@@ -209,9 +201,10 @@ const skipWordDictActiveIndex = computed(() => {
.side {
$width: 20vw;
position: absolute;
right: 0;
left: calc(100% + $space);
width: $width;
background: var(--color-second-bg);
//background: white;
height: 100%;
display: flex;
flex-direction: column;
@@ -285,7 +278,7 @@ const skipWordDictActiveIndex = computed(() => {
justify-content: flex-end;
gap: 10rem;
font-size: 18rem;
color: white;
color: black;
}
.word-list {

View File

@@ -32,21 +32,29 @@ import IconEyeSlash from '~icons/heroicons/eye-slash-solid'
import IconRepeat from '~icons/tabler/repeat'
import IconRepeatOff from '~icons/tabler/repeat-off'
import {emitter, EventKey} from "@/utils/eventBus.ts"
import {watch} from "vue"
const {toggle} = useTheme()
const store = useBaseStore()
const showFeedbackModal = $ref(false)
const showSettingModal = $ref(false)
const showDictModal = $ref(false)
const headerRef = $ref<HTMLDivElement>(null)
function t() {
console.log('t')
}
watch(() => store.setting.showToolbar, n => {
if (headerRef) {
if (n) {
headerRef.style.marginTop = '10rem'
} else {
let rect = headerRef.getBoundingClientRect()
headerRef.style.marginTop = `-${rect.height}px`
}
}
})
</script>
<template>
<header :class="!store.setting.showToolbar && 'hide'">
<header ref="headerRef">
<div class="info" @click="showDictModal = true">
{{ store.dictTitle }}
</div>
@@ -122,18 +130,21 @@ function t() {
@import "@/assets/css/colors.scss";
header {
top: 10rem;
height: 60rem;
width: var(--toolbar-width);
margin-top: 10rem;
min-height: 60rem;
width: 100%;
background: var(--color-header-bg);
display: flex;
justify-content: space-between;
border-radius: 8rem;
position: absolute;
margin-bottom: 30rem;
//position: absolute;
position: relative;
z-index: 2;
padding: 10rem $space;
box-sizing: border-box;
transition: all .3s;
gap: 10rem;
.info {
font-size: 16rem;
@@ -150,10 +161,6 @@ header {
gap: 10rem;
}
&.hide {
transform: translateY(calc(-100% - 10rem));
}
.arrow {
position: absolute;
bottom: 0;

View File

@@ -30,7 +30,6 @@ export default {
this.show = true
nextTick(() => {
let tip = this.$refs?.tip?.getBoundingClientRect()
console.log('re', rect)
if (!tip) return
if (rect.top < 50) {
this.$refs.tip.style.top = rect.top + rect.height + 10 + 'px'

View File

@@ -179,35 +179,16 @@ async function onKeyDown(e: KeyboardEvent) {
}
}
const progress = $computed(() => {
if (!store.chapter.length) return 0
return ((store.current.index / store.current.words.length) * 100)
})
const {toggle} = useTheme()
function format(val: number, suffix: string = '') {
return val === -1 ? '-' : (val + suffix)
}
let speedMinute = $ref(0)
let timer = $ref(0)
onMounted(() => {
timer = setInterval(() => {
speedMinute = Math.floor((Date.now() - store.current.statistics.startDate) / 1000 / 60)
}, 1000)
})
onUnmounted(() => {
timer && clearInterval(timer)
})
</script>
<template>
<div class="type-word">
<div class="translate">{{ store.word.trans.join('') }}</div>
<div class="word-wrapper">
<div class="word" :class="wrong&&'is-wrong'">
<div class="word" :class="wrong && 'is-wrong'">
<span class="input" v-if="input">{{ input }}</span>
<span class="wrong" v-if="wrong">{{ wrong }}</span>
<template v-if="store.isDictation">
@@ -231,50 +212,6 @@ onUnmounted(() => {
下一个
</BaseButton>
</div>
<div class="bottom" :class="!store.setting.showToolbar && 'hide'">
<Tooltip :title="store.setting.showToolbar?'收起':'展开'">
<Down
@click="store.setting.showToolbar = !store.setting.showToolbar"
class="arrow"
:class="!store.setting.showToolbar && 'down'"
theme="outline" size="24" fill="#999"/>
</Tooltip>
<el-progress :percentage="progress"
:stroke-width="8"
:show-text="false"/>
<div class="stat">
<div class="row">
<div class="num">{{ speedMinute }}分钟</div>
<div class="line"></div>
<div class="name">时间</div>
</div>
<div class="row">
<div class="num">{{ store.current.words.length }}</div>
<div class="line"></div>
<div class="name">单词总数</div>
</div>
<div class="row">
<div class="num">{{ store.current.index }}</div>
<div class="line"></div>
<div class="name">输入数</div>
</div>
<div class="row">
<div class="num">{{ format(store.current.wrongWords.length) }}</div>
<div class="line"></div>
<div class="name">错误数</div>
</div>
<div class="row">
<div class="num">{{ format(store.current.statistics.correctRate, '%') }}</div>
<div class="line"></div>
<div class="name">正确率</div>
</div>
</div>
</div>
<div class="progress">
<el-progress :percentage="progress"
:stroke-width="8"
:show-text="false"/>
</div>
</div>
</template>
@@ -301,6 +238,7 @@ onUnmounted(() => {
.phonetic, .translate {
font-size: 20rem;
margin-left: -30rem;
}
.word-wrapper {
@@ -327,65 +265,6 @@ onUnmounted(() => {
}
}
}
.bottom {
position: absolute;
bottom: 30rem;
width: var(--toolbar-width);
box-sizing: border-box;
border-radius: 10rem;
background: var(--color-header-bg);
padding: 2rem 10rem 10rem 10rem;
margin-top: 20rem;
transition: all .3s;
z-index: 2;
.arrow {
position: absolute;
top: 0;
left: 50%;
cursor: pointer;
transition: all .3s;
transform: translate3d(-50%, -100%, 0) rotate(0);
padding: 5rem;
}
.stat {
margin-top: 10rem;
display: flex;
justify-content: space-around;
.row {
display: flex;
flex-direction: column;
align-items: center;
gap: 10rem;
width: 80rem;
.line {
height: 1px;
width: 100%;
background: gainsboro;
}
}
}
&.hide {
transform: translateY(calc(100% + 30rem));
.arrow {
transform: translate3d(-50%, -220%, 0) rotate(180deg);
}
}
}
.progress {
width: var(--toolbar-width);
padding: 0 10rem;
box-sizing: border-box;
position: fixed;
bottom: 30rem;
}
}
@keyframes shake {

View File

@@ -0,0 +1,53 @@
<script setup lang="ts">
</script>
<template>
<div class="type-wrapper">
<article v-if="true">
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
</article>
</div>
</template>
<style scoped lang="scss">
@import "@/assets/css/style.scss";
.type-wrapper {
height: 100%;
overflow: auto;
article {
font-size: 24rem;
line-height: 1.5;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
letter-spacing: 0rem;
color: gray;
}
}
</style>