1.追加:投票结束查看倒计时时间

2.修改:倒计时样式
3.优化:抽奖和投票倒计时代码统一
This commit is contained in:
wangshun
2025-09-02 14:46:18 +08:00
parent 564ebfbc2c
commit e96ba3c26f
3 changed files with 66 additions and 89 deletions

View File

@@ -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()

View File

@@ -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()

View 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 }
}