save
This commit is contained in:
parent
1868144c41
commit
c2e2c7b895
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 367 B |
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
|
@ -1,11 +1,15 @@
|
||||||
import { computed, defineComponent, onMounted, ref, Transition } from 'vue'
|
import { computed, defineComponent, onMounted, ref, Transition } from 'vue'
|
||||||
import WelcomeImg from '~/public/icons/welcome/welcomeTitle.png'
|
import returnImg from "~/public/icons/work/return.png"
|
||||||
import DivBgImg from '~/public/icons/welcome/back.png'
|
import endImg from "~/public/icons/work/tomotoIconEnd.png"
|
||||||
import startUseImg from '~/public/icons/welcome/startUse.png'
|
import playWaveGif from "~/public/icons/work/playMusicIcon.gif"
|
||||||
|
import PlayStartImg from "~/public/icons/work/start.png"
|
||||||
|
import musicIcon from "~/public/icons/work/musicIcon.png"
|
||||||
import useBackgroundStore from '../background/useBackgroundStore'
|
import useBackgroundStore from '../background/useBackgroundStore'
|
||||||
import useLayoutStore from '../useLayoutStore'
|
import useLayoutStore from '../useLayoutStore'
|
||||||
import useTomatoStore from '@/widgets/work/useTomatoStore'
|
import useTomatoStore, { musicList } from '@/widgets/work/useTomatoStore'
|
||||||
import Search from '../header/search'
|
import Search from '../header/search'
|
||||||
|
import { Tooltip } from 'ant-design-vue'
|
||||||
|
import { formatSeconds } from '@/utils/tool'
|
||||||
export const DefaultPageSetting = [
|
export const DefaultPageSetting = [
|
||||||
{
|
{
|
||||||
name: '游戏',
|
name: '游戏',
|
||||||
|
@ -51,7 +55,7 @@ export default defineComponent(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return () =>
|
return () =>
|
||||||
!store.openFullscreen && (
|
store.openFullscreen && (
|
||||||
<div class="fixed left-0 top-0 z-50 w-full ">
|
<div class="fixed left-0 top-0 z-50 w-full ">
|
||||||
<Transition name="background">
|
<Transition name="background">
|
||||||
{background.bgTrriger && (
|
{background.bgTrriger && (
|
||||||
|
@ -84,14 +88,55 @@ export default defineComponent(() => {
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
<div class={"w-[500px] flex justify-center flex-col items-center h-full "}>
|
<div class={"w-[500px] flex justify-center flex-col items-center gap-y-3 h-full text-white "}>
|
||||||
<span class={"text-[24px] leading-[36px]"}>专注中</span>
|
<span class={"text-[24px] leading-[36px]"}>专注中</span>
|
||||||
<span class={"font-din text-[82px] font-bold leading-[115px]"}>15:00</span>
|
<span class={"font-din text-[82px] font-bold leading-[115px]"}>{!store.state.isStart ? '15:00' : formatSeconds(store.remainingTime)}</span>
|
||||||
<div class={"relative"}>
|
<div class={"relative"}>
|
||||||
<Search isMini></Search>
|
<div class={"aboslute w-[370px]"}>
|
||||||
</div>
|
<Search isMini></Search>
|
||||||
<div class={"w-full flex gap-x-3"}>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class={"w-full flex gap-x-4 justify-center mt-5"}>
|
||||||
|
<Tooltip title={"返回工作模式"}>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
store.openFullscreen = false
|
||||||
|
}}
|
||||||
|
class={"w-[44px] h-[44px] flex items-center justify-center rounded-lg cursor-pointer hover:opacity-90"}
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(225deg,#707eff 0%,#6b97ff 100%)',
|
||||||
|
boxShadow: '0 2px 4px #0003'
|
||||||
|
}}>
|
||||||
|
<img src={returnImg} alt='return' class={"w-[18px] h-[18px]"}></img>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={"停止"}>
|
||||||
|
<div
|
||||||
|
class={"w-[44px] h-[44px] flex items-center justify-center rounded-lg cursor-pointer hover:opacity-90"}
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(225deg,#707eff 0%,#6b97ff 100%)',
|
||||||
|
boxShadow: '0 2px 4px #0003'
|
||||||
|
}}>
|
||||||
|
<img src={endImg} alt='return' class={"w-[18px] h-[18px]"}></img>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<div class={"w-[140px] h-[44px] relative bg-[#f0f0f0] rounded-lg flex px-3 items-center justify-between cursor-pointer hover:opacity-90"}
|
||||||
|
style={{
|
||||||
|
boxShadow: '0 2px 4px #0003'
|
||||||
|
}}>
|
||||||
|
{
|
||||||
|
store.state.isPlaying ?
|
||||||
|
<img src={playWaveGif} alt='return' class={"w-[18px] h-[18px] "}></img>
|
||||||
|
:
|
||||||
|
<img src={musicIcon} alt='return' class={"w-[18px] h-[18px] "}></img>
|
||||||
|
}
|
||||||
|
<span class={"whitespace-nowrap text-ellipsis overflow-hidden text-[#333]"}>{musicList[store.state.selectMusic].name}</span>
|
||||||
|
<div class={"w-[26px] h-[26px] right-[-14px] rounded-full bg-[#c0c0c0] absolute flex items-center justify-center"}>
|
||||||
|
<img src={PlayStartImg} alt='start ' class={"w-[12px] h-[12px]"}></img>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -23,3 +23,17 @@ export function generateRandomString(n: number): string {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 将秒转换为“分:秒”的格式
|
||||||
|
* @param seconds - 输入的秒数
|
||||||
|
* @returns 格式化后的字符串,格式为“MM:SS”
|
||||||
|
*/
|
||||||
|
export function formatSeconds(seconds: number): string {
|
||||||
|
// 计算分钟数
|
||||||
|
const minutes = Math.floor(seconds / 60);
|
||||||
|
// 计算剩余的秒数
|
||||||
|
const remainingSeconds = seconds % 60;
|
||||||
|
|
||||||
|
// 返回格式化后的字符串,确保分钟和秒数都是两位数
|
||||||
|
return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { defineComponent } from 'vue'
|
||||||
export default defineComponent(() => {
|
export default defineComponent(() => {
|
||||||
return () => (
|
return () => (
|
||||||
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
|
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
|
||||||
large
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { computed, defineComponent, ref } from 'vue'
|
import { computed, defineComponent, ref } from 'vue'
|
||||||
import useTomatoStore from '../useTomatoStore'
|
import useTomatoStore from '../useTomatoStore'
|
||||||
import NoDataImg from "~/public/icons/work/noData.png"
|
import NoDataImg from "~/public/icons/work/noData.png"
|
||||||
|
import StopImg from "~/public/icons/work/tomotoIconEnd.png"
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import PlayImg from "~/public/icons/work/work_page-play.png"
|
import PlayImg from "~/public/icons/work/work_page-play.png"
|
||||||
|
@ -88,18 +89,36 @@ export default defineComponent(() => {
|
||||||
<span class={" tracking-wide"}>你今日已完成 <span class={"text-[#5b47ff]"}>{store.state.list.filter(val => dayjs(val.finishTime).isSame(dayjs(), 'day') && val.isCompleted).length}</span>个番茄时</span>
|
<span class={" tracking-wide"}>你今日已完成 <span class={"text-[#5b47ff]"}>{store.state.list.filter(val => dayjs(val.finishTime).isSame(dayjs(), 'day') && val.isCompleted).length}</span>个番茄时</span>
|
||||||
<span class={"text-[#ff8686]"}>不积跬步无以至千里、千里之行始于足下。</span>
|
<span class={"text-[#ff8686]"}>不积跬步无以至千里、千里之行始于足下。</span>
|
||||||
</div>
|
</div>
|
||||||
<button class={"w-[126px] h-[44px] text-[16px] text-white rounded-lg gap-x-1 font-bold flex items-center justify-center"} style={{
|
{
|
||||||
background: 'linear-gradient(225deg,#642FFF 0%,#5162FF 100%)',
|
store.state.isStart ?
|
||||||
boxShadow: '0 2px 4px #0003'
|
<button class={"w-[126px] h-[44px] text-[16px] text-white rounded-lg gap-x-1 font-bold flex items-center justify-center"} style={{
|
||||||
}}
|
background: 'linear-gradient(225deg,#642FFF 0%,#5162FF 100%)',
|
||||||
onClick={() => {
|
boxShadow: '0 2px 4px #0003'
|
||||||
store.openFullscreen = true
|
}}
|
||||||
}}
|
onClick={() => {
|
||||||
>
|
store.stopTomatoTime()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<img src={StopImg} alt="play img " class={"w-[13px]"} />
|
||||||
|
停止计时
|
||||||
|
</button> :
|
||||||
|
<button class={"w-[126px] h-[44px] text-[16px] text-white rounded-lg gap-x-1 font-bold flex items-center hover:opacity-90 justify-center"} style={{
|
||||||
|
background: 'linear-gradient(225deg,#642FFF 0%,#5162FF 100%)',
|
||||||
|
boxShadow: '0 2px 4px #0003'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
store.openFullscreen = true
|
||||||
|
store.beginTomatoTime()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<img src={PlayImg} alt="play img " class={"w-[13px]"} />
|
||||||
|
开始计时
|
||||||
|
</button>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
<img src={PlayImg} alt="play img " class={"w-[13px]"} />
|
|
||||||
开始计时
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
|
import useTimeStore from "@/utils/useTimeStore";
|
||||||
|
import dayjs from "dayjs";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { reactive, ref } from "vue";
|
import { computed, reactive, ref, watch } from "vue";
|
||||||
|
import APartOfUsMusic from "~/public/icons/work/music/aPartOfUs.mp3"
|
||||||
|
import AsignalRose from "~/public/icons/work/music/AsignalRose.mp3"
|
||||||
|
import AThousandLifetimes from "~/public/icons/work/music/aThousandLifetimes.mp3"
|
||||||
|
import AVeryBradySpecial from "~/public/icons/work/music/AVeryBradySpecial.mp3"
|
||||||
|
import AWonderfulStore from "~/public/icons/work/music/AWonderfulStore.mp3"
|
||||||
|
|
||||||
|
const TOTAL_TIME = 60 * 60 * 15
|
||||||
export type TomatoTarget = {
|
export type TomatoTarget = {
|
||||||
id: string;
|
id: string;
|
||||||
finishTime: number;
|
finishTime: number;
|
||||||
|
@ -13,18 +21,99 @@ export type TomatoTime = {
|
||||||
date: number;
|
date: number;
|
||||||
finishTime: number;
|
finishTime: number;
|
||||||
}
|
}
|
||||||
|
export const musicList = [
|
||||||
|
{
|
||||||
|
name: 'A Part of Us',
|
||||||
|
music: APartOfUsMusic
|
||||||
|
}, {
|
||||||
|
name: 'a signal rose',
|
||||||
|
music: AsignalRose
|
||||||
|
}, {
|
||||||
|
name: 'a thousand lifetimes',
|
||||||
|
music: AThousandLifetimes
|
||||||
|
}, {
|
||||||
|
name: 'A Very Brady Special',
|
||||||
|
music: AVeryBradySpecial
|
||||||
|
}, {
|
||||||
|
name: 'A Wonderful Story',
|
||||||
|
music: AWonderfulStore
|
||||||
|
}
|
||||||
|
]
|
||||||
export default defineStore("work", () => {
|
export default defineStore("work", () => {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
list: [] as TomatoTarget[],
|
list: [] as TomatoTarget[],
|
||||||
timeList: [] as TomatoTime[]
|
timeList: [] as TomatoTime[],
|
||||||
|
isPlaying: false as boolean,
|
||||||
|
selectMusic: 0,
|
||||||
|
isStart: false as boolean,
|
||||||
|
beginTime: -1 as number
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const time = useTimeStore()
|
||||||
|
const beginTomatoTime = () => {
|
||||||
|
state.beginTime = dayjs().valueOf()
|
||||||
|
state.isStart = true
|
||||||
|
playMusic()
|
||||||
|
}
|
||||||
|
const stopTomatoTime = () => {
|
||||||
|
state.isStart = false
|
||||||
|
state.beginTime = -1
|
||||||
|
stopMusic()
|
||||||
|
}
|
||||||
|
const remainingTime = computed(() => {
|
||||||
|
const totalTime = TOTAL_TIME
|
||||||
|
|
||||||
|
return dayjs(state.beginTime).add(15, 'minute').diff(dayjs(time.date), 'second')
|
||||||
|
})
|
||||||
|
const playAudio = computed(() => {
|
||||||
|
const audio = new Audio(musicList[state.selectMusic].music)
|
||||||
|
return audio
|
||||||
|
})
|
||||||
|
watch(() => remainingTime, (val) => {
|
||||||
|
if (val.value < 0) {
|
||||||
|
state.isPlaying = false
|
||||||
|
state.isStart = false
|
||||||
|
state.beginTime = -1
|
||||||
|
state.timeList.push({
|
||||||
|
date: dayjs().valueOf(),
|
||||||
|
finishTime: TOTAL_TIME
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// watch(() => state.isPlaying, (val) => {
|
||||||
|
// if (val) {
|
||||||
|
// playAudio.value.play()
|
||||||
|
// } else {
|
||||||
|
// playAudio.value.pause()
|
||||||
|
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
const playMusic = () => {
|
||||||
|
state.isPlaying = true
|
||||||
|
playAudio.value.play()
|
||||||
|
}
|
||||||
|
|
||||||
|
const pauseMusic = () => {
|
||||||
|
state.isPlaying = false
|
||||||
|
playAudio.value.pause()
|
||||||
|
}
|
||||||
|
const stopMusic = () => {
|
||||||
|
state.isPlaying = false
|
||||||
|
playAudio.value.pause()
|
||||||
|
playAudio.value.currentTime = 0
|
||||||
|
}
|
||||||
const openShowModel = ref<undefined | null | TomatoTarget>()
|
const openShowModel = ref<undefined | null | TomatoTarget>()
|
||||||
const openFullscreen = ref(false)
|
const openFullscreen = ref(false)
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
openShowModel,
|
openShowModel,
|
||||||
openFullscreen
|
openFullscreen,
|
||||||
|
beginTomatoTime,
|
||||||
|
remainingTime,
|
||||||
|
playMusic,
|
||||||
|
pauseMusic,
|
||||||
|
stopMusic,
|
||||||
|
stopTomatoTime
|
||||||
}
|
}
|
||||||
})
|
})
|
Loading…
Reference in New Issue