登录对接

This commit is contained in:
2025-12-31 06:39:11 -08:00
parent 033dda7744
commit 2b0741fdb9
3 changed files with 222 additions and 6 deletions
@@ -1,4 +1,5 @@
<template>
<div v-if="!devices?.length" class="w-full text-center">暂无绑定设备</div>
<div class="grid min-h-[76px] grid-cols-2 gap-3">
<div
v-for="device in devices"
@@ -0,0 +1,191 @@
<template>
<Dialog :open="open" @update:open="handleClose">
<DialogContent
:show-close-button="false"
@pointer-down-outside="(event) => event.preventDefault()"
@focus-outside="(event) => event.preventDefault()"
class="max-w-[345px] rounded-[32px] border-none bg-[#E5E5E5] p-6"
>
<div class="flex flex-col items-center py-6">
<h2 class="mb-1 text-xl font-semibold text-black">订单状态</h2>
<div class="mb-10 text-[24px] font-bold text-black">
{{ statusInfo.title }}
</div>
<div
v-if="statusInfo.description"
class="mb-8 text-center text-sm whitespace-pre-line text-gray-600"
>
{{ statusInfo.description }}
</div>
<div class="mt-4 flex w-full gap-3">
<Button
variant="secondary"
class="h-[50px] flex-1 rounded-[25px] bg-[#D1D1D1] text-lg font-bold text-gray-600 hover:bg-gray-300"
@click="handleClose"
>
关闭
</Button>
<Button
class="h-[50px] flex-1 rounded-[25px] bg-[#ADFF5B] text-lg font-bold text-black hover:bg-[#9EE64F]"
@click="handleClose"
>
返回首页
</Button>
</div>
</div>
</DialogContent>
</Dialog>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { Dialog, DialogContent } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import request from '@/utils/request'
const emit = defineEmits(['close', 'refresh'])
const open = ref(false)
const orderNo = ref<string | null>(null)
const status = ref<number>(1) // 1: Pending, 2: Paid, 3: Finished, 4: Close, 5: Failed, -1: Error
const countdown = ref('')
let timer: any = null
let countdownTimer: any = null
let createdAt: Date | null = null
const statusInfo = computed(() => {
switch (status.value) {
case -1:
return {
title: '检查失败',
description: '检查支付状态失败,请稍后刷新页面或联系客服',
}
case 1:
return {
title: '待支付',
description: `订单正在处理中\n剩余时间: ${countdown.value}`,
}
case 2:
return {
title: '支付确认中',
description: '订单已支付,系统正在确认,请稍候...',
}
case 3:
return {
title: '支付成功',
description: '您的订单已支付完成',
}
case 4:
return {
title: '订单已关闭',
description: '该订单已超时或被手动关闭',
}
case 5:
return {
title: '支付失败',
description: '订单支付失败,请检查支付信息并重试',
}
default:
return {
title: '待支付',
description: `订单正在处理中\n剩余时间: ${countdown.value}`,
}
}
})
function handleClose() {
stopPolling()
open.value = false
emit('close')
}
async function checkStatus() {
if (!orderNo.value) return
try {
const res: any = await request.get('/api/v1/public/order/detail', { order_no: orderNo.value })
// 1. 保存订单创建时间(用于倒计时)
if (!createdAt && res.created_at) {
const timestamp = res.created_at
const isMilliseconds = timestamp > 10000000000
createdAt = new Date(isMilliseconds ? timestamp : timestamp * 1000)
startCountdown()
}
status.value = res.status
// 2. 根据状态处理业务逻辑
if (status.value === 3) {
// Finished
stopPolling()
emit('refresh')
} else if (status.value === 4 || status.value === 5) {
// Closed or Failed
stopPolling()
}
} catch (error) {
console.error('❌ 查询失败:', error)
status.value = -1
stopPolling()
}
}
function startPolling() {
stopPolling()
checkStatus()
timer = setInterval(checkStatus, 3000)
}
function stopPolling() {
if (timer) {
clearInterval(timer)
timer = null
}
if (countdownTimer) {
clearInterval(countdownTimer)
countdownTimer = null
}
}
function startCountdown() {
if (!createdAt) return
const updateCountdown = () => {
const now = new Date()
// 假设订单有效期为 15 分钟 (900 秒)
const expiryTime = new Date(createdAt!.getTime() + 900 * 1000)
const diff = expiryTime.getTime() - now.getTime()
console.log('diff', diff)
if (diff <= 0) {
countdown.value = '00:00'
clearInterval(countdownTimer)
return
}
const minutes = Math.floor(diff / 1000 / 60)
const seconds = Math.floor((diff / 1000) % 60)
countdown.value = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
}
updateCountdown()
if (countdownTimer) clearInterval(countdownTimer)
countdownTimer = setInterval(updateCountdown, 1000)
}
function show(no: string) {
orderNo.value = no
status.value = 1
createdAt = null
countdown.value = '15:00'
open.value = true
startPolling()
}
defineExpose({ show })
onUnmounted(() => {
stopPolling()
})
</script>