mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-02-06 23:21:16 +08:00
1.追加:投票结束查看倒计时时间
2.修改:倒计时样式 3.优化:抽奖和投票倒计时代码统一
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
<div class="prize-count">x {{ lottery.prizeCount }}</div>
|
||||
</div>
|
||||
<div class="prize-end-time prize-info-right">
|
||||
<div v-if="!isMobile" class="prize-end-time-title">离结束还有</div>
|
||||
<div v-if="!isMobile" class="prize-end-time-title"><i class="fas fa-stopwatch"></i>距离结束还有</div>
|
||||
<div class="prize-end-time-value">{{ countdown }}</div>
|
||||
<div v-if="!isMobile" class="join-prize-button-container-desktop">
|
||||
<div
|
||||
@@ -84,6 +84,7 @@ import { getToken, authState } from '~/utils/auth'
|
||||
import { toast } from '~/main'
|
||||
import { useRuntimeConfig } from '#imports'
|
||||
import { useIsMobile } from '~/utils/screen'
|
||||
import { useCountdown } from '~/composables/useCountdown'
|
||||
|
||||
const props = defineProps({
|
||||
lottery: { type: Object, required: true },
|
||||
@@ -95,54 +96,14 @@ const isMobile = useIsMobile()
|
||||
const loggedIn = computed(() => authState.loggedIn)
|
||||
const lotteryParticipants = computed(() => props.lottery?.participants || [])
|
||||
const lotteryWinners = computed(() => props.lottery?.winners || [])
|
||||
const lotteryEnded = computed(() => {
|
||||
if (!props.lottery || !props.lottery.endTime) return false
|
||||
return new Date(props.lottery.endTime).getTime() <= Date.now()
|
||||
})
|
||||
// 倒计时和结束flg
|
||||
const { countdown, isEnded } = useCountdown(props.lottery?.endTime)
|
||||
const lotteryEnded = computed(() => isEnded.value)
|
||||
const hasJoined = computed(() => {
|
||||
if (!loggedIn.value) return false
|
||||
return lotteryParticipants.value.some((p) => p.id === Number(authState.userId))
|
||||
})
|
||||
|
||||
const countdown = ref('00:00:00')
|
||||
let timer = null
|
||||
const updateCountdown = () => {
|
||||
if (!props.lottery || !props.lottery.endTime) {
|
||||
countdown.value = '00:00:00'
|
||||
return
|
||||
}
|
||||
const diff = new Date(props.lottery.endTime).getTime() - Date.now()
|
||||
if (diff <= 0) {
|
||||
countdown.value = '00:00:00'
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
return
|
||||
}
|
||||
const h = String(Math.floor(diff / 3600000)).padStart(2, '0')
|
||||
const m = String(Math.floor((diff % 3600000) / 60000)).padStart(2, '0')
|
||||
const s = String(Math.floor((diff % 60000) / 1000)).padStart(2, '0')
|
||||
countdown.value = `${h}:${m}:${s}`
|
||||
}
|
||||
const startCountdown = () => {
|
||||
updateCountdown()
|
||||
if (timer) clearInterval(timer)
|
||||
timer = setInterval(updateCountdown, 1000)
|
||||
}
|
||||
watch(
|
||||
() => props.lottery?.endTime,
|
||||
() => {
|
||||
if (props.lottery && props.lottery.endTime) startCountdown()
|
||||
},
|
||||
)
|
||||
onMounted(() => {
|
||||
if (props.lottery && props.lottery.endTime) startCountdown()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
if (timer) clearInterval(timer)
|
||||
})
|
||||
|
||||
const gotoUser = (id) => navigateTo(`/users/${id}`, { replace: true })
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<div class="poll-option-title" v-else>单选</div>
|
||||
|
||||
<div class="poll-left-time">
|
||||
<div class="poll-left-time-title">离结束还有</div>
|
||||
<div class="poll-left-time-title"><i class="fas fa-stopwatch"></i>距离结束还有</div>
|
||||
<div class="poll-left-time-value">{{ countdown }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -107,7 +107,11 @@
|
||||
<i class="fas fa-stopwatch"></i> 投票已结束
|
||||
</div>
|
||||
<div v-else class="poll-option-hint">
|
||||
<i class="fas fa-stopwatch"></i> 您已投票,等待结束查看结果
|
||||
<div>您已投票,等待结束查看结果</div>
|
||||
<div class="poll-left-time">
|
||||
<div class="poll-left-time-title"><i class="fas fa-stopwatch"></i>距离结束还有</div>
|
||||
<div class="poll-left-time-value">{{ countdown }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -118,6 +122,7 @@ import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { getToken, authState } from '~/utils/auth'
|
||||
import { toast } from '~/main'
|
||||
import { useRuntimeConfig } from '#imports'
|
||||
import { useCountdown } from '~/composables/useCountdown'
|
||||
|
||||
const props = defineProps({
|
||||
poll: { type: Object, required: true },
|
||||
@@ -140,10 +145,9 @@ const pollPercentages = computed(() =>
|
||||
})
|
||||
: [],
|
||||
)
|
||||
const pollEnded = computed(() => {
|
||||
if (!props.poll || !props.poll.endTime) return false
|
||||
return new Date(props.poll.endTime).getTime() <= Date.now()
|
||||
})
|
||||
// 倒计时
|
||||
const { countdown, isEnded } = useCountdown(props.poll?.endTime)
|
||||
const pollEnded = computed(() => isEnded.value)
|
||||
const hasVoted = computed(() => {
|
||||
if (!loggedIn.value) return false
|
||||
return pollParticipants.value.some((p) => p.id === Number(authState.userId))
|
||||
@@ -152,45 +156,6 @@ watch([hasVoted, pollEnded], ([voted, ended]) => {
|
||||
if (voted || ended) showPollResult.value = true
|
||||
})
|
||||
|
||||
const countdown = ref('00:00:00')
|
||||
let timer = null
|
||||
const updateCountdown = () => {
|
||||
if (!props.poll || !props.poll.endTime) {
|
||||
countdown.value = '00:00:00'
|
||||
return
|
||||
}
|
||||
const diff = new Date(props.poll.endTime).getTime() - Date.now()
|
||||
if (diff <= 0) {
|
||||
countdown.value = '00:00:00'
|
||||
if (timer) {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
return
|
||||
}
|
||||
const h = String(Math.floor(diff / 3600000)).padStart(2, '0')
|
||||
const m = String(Math.floor((diff % 3600000) / 60000)).padStart(2, '0')
|
||||
const s = String(Math.floor((diff % 60000) / 1000)).padStart(2, '0')
|
||||
countdown.value = `${h}:${m}:${s}`
|
||||
}
|
||||
const startCountdown = () => {
|
||||
updateCountdown()
|
||||
if (timer) clearInterval(timer)
|
||||
timer = setInterval(updateCountdown, 1000)
|
||||
}
|
||||
watch(
|
||||
() => props.poll?.endTime,
|
||||
() => {
|
||||
if (props.poll && props.poll.endTime) startCountdown()
|
||||
},
|
||||
)
|
||||
onMounted(() => {
|
||||
if (props.poll && props.poll.endTime) startCountdown()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
if (timer) clearInterval(timer)
|
||||
})
|
||||
|
||||
const gotoUser = (id) => navigateTo(`/users/${id}`, { replace: true })
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
51
frontend_nuxt/composables/useCountdown.ts
Normal file
51
frontend_nuxt/composables/useCountdown.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
||||
|
||||
/**
|
||||
* 通用倒计时 composable
|
||||
* @param endTime 截止时间字符串或 Date 对象
|
||||
* @returns { countdown, isEnded }
|
||||
*/
|
||||
export function useCountdown(endTime?: string | Date) {
|
||||
const countdown = ref('')
|
||||
const isEnded = ref(false)
|
||||
let timer: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
const update = () => {
|
||||
if (!endTime) {
|
||||
countdown.value = ''
|
||||
isEnded.value = true
|
||||
return
|
||||
}
|
||||
const diff = new Date(endTime).getTime() - Date.now()
|
||||
if (diff <= 0) {
|
||||
countdown.value = '已结束'
|
||||
isEnded.value = true
|
||||
if (timer) clearInterval(timer)
|
||||
return
|
||||
}
|
||||
// 计算天、时、分、秒
|
||||
const days = Math.floor(diff / (24 * 3600 * 1000))
|
||||
const hours = Math.floor((diff % (24 * 3600 * 1000)) / 3600000)
|
||||
const minutes = Math.floor((diff % 3600000) / 60000)
|
||||
const seconds = Math.floor((diff % 60000) / 1000)
|
||||
|
||||
if (days > 0) {
|
||||
countdown.value = `${days}天 ${hours}小时 ${minutes}分 ${seconds}秒`
|
||||
} else if (hours > 0) {
|
||||
countdown.value = `${hours}小时 ${minutes}分 ${seconds}秒`
|
||||
} else {
|
||||
countdown.value = `${minutes}分 ${seconds}秒`
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
update()
|
||||
timer = setInterval(update, 1000)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (timer) clearInterval(timer)
|
||||
})
|
||||
|
||||
return { countdown, isEnded }
|
||||
}
|
||||
Reference in New Issue
Block a user