163 lines
4.3 KiB
Vue
163 lines
4.3 KiB
Vue
<script setup lang="ts">
|
||
import { CircleClose, Loading } from '@element-plus/icons-vue'
|
||
|
||
import ClaimBindingStep from './components/ClaimBindingStep.vue'
|
||
import ClaimConfirmStep from './components/ClaimConfirmStep.vue'
|
||
import ClaimHeaderCard from './components/ClaimHeaderCard.vue'
|
||
import ClaimResultStep from './components/ClaimResultStep.vue'
|
||
import ClaimTicketStep from './components/ClaimTicketStep.vue'
|
||
import { useKuaishouCloudClaim } from './composables/useKuaishouCloudClaim'
|
||
|
||
const props = defineProps<{
|
||
token: string
|
||
}>()
|
||
|
||
const claim = useKuaishouCloudClaim(() => props.token)
|
||
</script>
|
||
|
||
<template>
|
||
<main class="claim-page">
|
||
<ClaimHeaderCard
|
||
:order="claim.order.value"
|
||
:product="claim.product.value"
|
||
:current-step="claim.currentStep.value"
|
||
:progress-text="claim.progressText.value"
|
||
/>
|
||
|
||
<div v-if="claim.loading.value" class="content-card loading-card">
|
||
<el-icon class="large-icon spinning"><Loading /></el-icon>
|
||
<p>正在读取当前领取进度...</p>
|
||
</div>
|
||
|
||
<div v-else-if="claim.errorMessage.value" class="content-card error-card">
|
||
<el-icon class="large-icon error"><CircleClose /></el-icon>
|
||
<p>{{ claim.errorMessage.value }}</p>
|
||
</div>
|
||
|
||
<template v-else-if="claim.detail.value && claim.flow.value">
|
||
<ClaimTicketStep
|
||
v-if="claim.currentStep.value === 1"
|
||
:ticket-code="claim.ticketCode.value"
|
||
:can-submit-ticket="claim.canSubmitTicket.value"
|
||
:submitting="claim.submitting.value"
|
||
:is-binding-preparing="claim.isBindingPreparing.value"
|
||
:flow="claim.flow.value"
|
||
@update:ticket-code="claim.ticketCode.value = $event"
|
||
@submit-ticket="claim.submitTicket()"
|
||
/>
|
||
|
||
<ClaimBindingStep
|
||
v-else-if="claim.currentStep.value === 2"
|
||
:qr-code-data-url="claim.qrCodeDataUrl.value"
|
||
:is-binding-prepared="claim.isBindingPrepared.value"
|
||
:is-binding-preparing="claim.isBindingPreparing.value"
|
||
:is-role-ready="claim.isRoleReady.value"
|
||
:refreshing-role="claim.refreshingRole.value"
|
||
:confirming-role="claim.confirmingRole.value"
|
||
:flow="claim.flow.value"
|
||
:format-date-time="claim.formatAdminDateTime"
|
||
@open-bind-url="claim.openBindUrl($event)"
|
||
@refresh-role="claim.refreshRole()"
|
||
@confirm-role="claim.confirmRole()"
|
||
/>
|
||
|
||
<ClaimConfirmStep
|
||
v-else-if="claim.currentStep.value === 3"
|
||
:role-name="claim.roleName.value"
|
||
:role-id="claim.roleId.value"
|
||
:product="claim.product.value"
|
||
:redeeming="claim.redeeming.value"
|
||
@confirm-redeem="claim.confirmRedeem()"
|
||
/>
|
||
|
||
<ClaimResultStep
|
||
v-else
|
||
:result-title="claim.resultTitle.value"
|
||
:result-description="claim.resultDescription.value"
|
||
:flow="claim.flow.value"
|
||
:order="claim.order.value"
|
||
:product="claim.product.value"
|
||
:role-name="claim.roleName.value"
|
||
:role-id="claim.roleId.value"
|
||
:format-date-time="claim.formatAdminDateTime"
|
||
/>
|
||
</template>
|
||
|
||
<div v-else class="content-card error-card">
|
||
<el-icon class="large-icon error"><CircleClose /></el-icon>
|
||
<p>流程数据不完整,请联系客服处理</p>
|
||
</div>
|
||
</main>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.claim-page {
|
||
min-height: 100vh;
|
||
padding: 24px;
|
||
background:
|
||
radial-gradient(circle at top right, rgba(59, 130, 246, 0.18), transparent 28%),
|
||
linear-gradient(180deg, #f8fafc 0%, #eef4fb 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 18px;
|
||
}
|
||
|
||
.content-card {
|
||
width: 100%;
|
||
max-width: 680px;
|
||
background: rgba(255, 255, 255, 0.92);
|
||
border: 1px solid rgba(148, 163, 184, 0.16);
|
||
border-radius: 20px;
|
||
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.08);
|
||
backdrop-filter: blur(12px);
|
||
padding: 28px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 18px;
|
||
}
|
||
|
||
.loading-card,
|
||
.error-card {
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
min-height: 240px;
|
||
}
|
||
|
||
.large-icon {
|
||
font-size: 44px;
|
||
}
|
||
|
||
.large-icon.success {
|
||
color: #16a34a;
|
||
}
|
||
|
||
.large-icon.error {
|
||
color: #dc2626;
|
||
}
|
||
|
||
.spinning {
|
||
animation: spin 1s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
from {
|
||
transform: rotate(0deg);
|
||
}
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 720px) {
|
||
.claim-page {
|
||
padding: 16px;
|
||
}
|
||
|
||
.content-card {
|
||
max-width: 100%;
|
||
}
|
||
}
|
||
</style>
|