feat: rebuild auth identity foundation flow

This commit is contained in:
IanShaw027
2026-04-20 17:39:57 +08:00
parent fbd0a2e3c4
commit e9de839d87
123 changed files with 33599 additions and 772 deletions

View File

@@ -141,7 +141,9 @@ const props = defineProps<{
orderType?: string
}>()
const emit = defineEmits<{ done: []; success: [] }>()
type PaymentOutcome = 'success' | 'cancelled' | 'expired'
const emit = defineEmits<{ done: []; success: []; settled: [outcome: PaymentOutcome] }>()
const { t } = useI18n()
const paymentStore = usePaymentStore()
@@ -154,7 +156,7 @@ const cancelling = ref(false)
const paidOrder = ref<PaymentOrder | null>(null)
// Terminal outcome: null = still active, 'success' | 'cancelled' | 'expired'
const outcome = ref<'success' | 'cancelled' | 'expired' | null>(null)
const outcome = ref<PaymentOutcome | null>(null)
let pollTimer: ReturnType<typeof setInterval> | null = null
let countdownTimer: ReturnType<typeof setInterval> | null = null
@@ -194,10 +196,19 @@ const countdownDisplay = computed(() => {
function reopenPopup() {
if (props.payUrl) {
window.open(props.payUrl, 'paymentPopup', POPUP_WINDOW_FEATURES)
const win = window.open(props.payUrl, 'paymentPopup', POPUP_WINDOW_FEATURES)
if (!win || win.closed) {
window.location.href = props.payUrl
}
}
}
function setOutcome(next: PaymentOutcome) {
if (outcome.value === next) return
outcome.value = next
emit('settled', next)
}
async function renderQR() {
await nextTick()
if (!qrCanvas.value || !qrUrl.value) return
@@ -214,23 +225,23 @@ async function pollStatus() {
if (order.status === 'COMPLETED' || order.status === 'PAID') {
cleanup()
paidOrder.value = order
outcome.value = 'success'
setOutcome('success')
emit('success')
} else if (order.status === 'CANCELLED') {
cleanup()
outcome.value = 'cancelled'
setOutcome('cancelled')
} else if (order.status === 'EXPIRED' || order.status === 'FAILED') {
cleanup()
outcome.value = 'expired'
setOutcome('expired')
}
}
function startCountdown(seconds: number) {
remainingSeconds.value = Math.max(0, seconds)
if (remainingSeconds.value <= 0) { outcome.value = 'expired'; return }
if (remainingSeconds.value <= 0) { setOutcome('expired'); return }
countdownTimer = setInterval(() => {
remainingSeconds.value--
if (remainingSeconds.value <= 0) { outcome.value = 'expired'; cleanup() }
if (remainingSeconds.value <= 0) { setOutcome('expired'); cleanup() }
}, 1000)
}
@@ -240,7 +251,7 @@ async function handleCancel() {
try {
await paymentAPI.cancelOrder(props.orderId)
cleanup()
outcome.value = 'cancelled'
setOutcome('cancelled')
} catch (err: unknown) {
appStore.showError(extractApiErrorMessage(err, t('common.error')))
} finally {