Showing
1 changed file
with
84 additions
and
1 deletions
| ... | @@ -88,6 +88,9 @@ | ... | @@ -88,6 +88,9 @@ |
| 88 | </button> | 88 | </button> |
| 89 | </div> | 89 | </div> |
| 90 | </div> | 90 | </div> |
| 91 | + <div v-if="order.status === 'NOT_PAY' && order.countdown" class="text-right mt-4"> | ||
| 92 | + <span class="text-red-500 text-sm font-medium">支付倒计时:{{ order.countdown }}</span> | ||
| 93 | + </div> | ||
| 91 | </FrostedGlass> | 94 | </FrostedGlass> |
| 92 | </van-list> | 95 | </van-list> |
| 93 | 96 | ||
| ... | @@ -187,7 +190,7 @@ | ... | @@ -187,7 +190,7 @@ |
| 187 | </template> | 190 | </template> |
| 188 | 191 | ||
| 189 | <script setup> | 192 | <script setup> |
| 190 | -import { ref } from 'vue' | 193 | +import { ref, computed, onMounted, onUnmounted } from 'vue' |
| 191 | import { useRoute, useRouter } from 'vue-router'; | 194 | import { useRoute, useRouter } from 'vue-router'; |
| 192 | import AppLayout from '@/components/layout/AppLayout.vue' | 195 | import AppLayout from '@/components/layout/AppLayout.vue' |
| 193 | import FrostedGlass from '@/components/ui/FrostedGlass.vue' | 196 | import FrostedGlass from '@/components/ui/FrostedGlass.vue' |
| ... | @@ -292,6 +295,12 @@ const onLoad = async () => { | ... | @@ -292,6 +295,12 @@ const onLoad = async () => { |
| 292 | status: selectedStatus.value | 295 | status: selectedStatus.value |
| 293 | }); | 296 | }); |
| 294 | if (res.code) { | 297 | if (res.code) { |
| 298 | + // 待支付订单倒计时 | ||
| 299 | + res.data.forEach(order => { | ||
| 300 | + if (order.status === 'NOT_PAY') { | ||
| 301 | + startCountdown(order); | ||
| 302 | + } | ||
| 303 | + }) | ||
| 295 | orders.value = [...orders.value, ...res.data]; | 304 | orders.value = [...orders.value, ...res.data]; |
| 296 | finished.value = res.data.length < limit.value; | 305 | finished.value = res.data.length < limit.value; |
| 297 | page.value = nextPage + 1; | 306 | page.value = nextPage + 1; |
| ... | @@ -372,4 +381,78 @@ const handleCancel = async (order) => { | ... | @@ -372,4 +381,78 @@ const handleCancel = async (order) => { |
| 372 | // on cancel | 381 | // on cancel |
| 373 | }); | 382 | }); |
| 374 | }; | 383 | }; |
| 384 | + | ||
| 385 | +/** | ||
| 386 | + * 待支付订单的支付倒计时功能 | ||
| 387 | + * @param {Object} order - 订单对象 | ||
| 388 | + */ | ||
| 389 | +const startCountdown = (order) => { | ||
| 390 | + // 清除可能存在的旧定时器 | ||
| 391 | + if (order._countdownTimer) { | ||
| 392 | + clearInterval(order._countdownTimer); | ||
| 393 | + order._countdownTimer = null; | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + // 计算剩余时间(毫秒) | ||
| 397 | + const current_date = new Date(order.server_time); | ||
| 398 | + const end_date = new Date(order.pay_deadline_time); | ||
| 399 | + let time_left = end_date - current_date; | ||
| 400 | + | ||
| 401 | + // 检查是否已过期 | ||
| 402 | + if (time_left <= 0) { | ||
| 403 | + // 使用Vue的响应式API更新对象属性 | ||
| 404 | + order.status = 'CANCEL'; | ||
| 405 | + order.statusText = '已取消'; | ||
| 406 | + order.statusColor = 'text-gray-500'; | ||
| 407 | + order.countdown = ''; | ||
| 408 | + // 强制触发视图更新 | ||
| 409 | + orders.value = [...orders.value]; | ||
| 410 | + return; | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + // 更新倒计时显示 | ||
| 414 | + const updateCountdown = () => { | ||
| 415 | + // 计算时、分、秒 | ||
| 416 | + const hours = Math.floor(time_left / 3600000); | ||
| 417 | + const minutes = Math.floor((time_left % 3600000) / 60000); | ||
| 418 | + const seconds = Math.floor((time_left % 60000) / 1000); | ||
| 419 | + | ||
| 420 | + // 格式化显示 | ||
| 421 | + order.countdown = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; | ||
| 422 | + | ||
| 423 | + // 强制触发视图更新 | ||
| 424 | + orders.value = [...orders.value]; | ||
| 425 | + | ||
| 426 | + // 减少剩余时间 | ||
| 427 | + time_left -= 1000; | ||
| 428 | + | ||
| 429 | + // 检查是否已到期 | ||
| 430 | + if (time_left < 0) { | ||
| 431 | + clearInterval(order._countdownTimer); | ||
| 432 | + order._countdownTimer = null; | ||
| 433 | + | ||
| 434 | + order.status = 'CANCEL'; | ||
| 435 | + order.statusText = '已取消'; | ||
| 436 | + order.statusColor = 'text-gray-500'; | ||
| 437 | + order.countdown = ''; | ||
| 438 | + | ||
| 439 | + // 强制触发视图更新 | ||
| 440 | + orders.value = [...orders.value]; | ||
| 441 | + } | ||
| 442 | + }; | ||
| 443 | + | ||
| 444 | + // 立即执行一次更新 | ||
| 445 | + updateCountdown(); | ||
| 446 | + | ||
| 447 | + // 设置定时器,每秒更新一次 | ||
| 448 | + order._countdownTimer = setInterval(updateCountdown, 1000); | ||
| 449 | + | ||
| 450 | + // 组件卸载时清除定时器 | ||
| 451 | + onUnmounted(() => { | ||
| 452 | + if (order._countdownTimer) { | ||
| 453 | + clearInterval(order._countdownTimer); | ||
| 454 | + order._countdownTimer = null; | ||
| 455 | + } | ||
| 456 | + }); | ||
| 457 | +}; | ||
| 375 | </script> | 458 | </script> | ... | ... |
-
Please register or login to post a comment