Files
zy-client-a/0000_gb_points_temp/src/components/pay/PayTheme5.vue
telangpu 2fd1a741cf update
2026-04-27 16:33:26 +08:00

513 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="t5-pt8-root">
<!-- 红色顶部 -->
<div class="t5-pt8-hero">
<span class="t5-pt8-hdeco t5-pt8-hdeco-l"></span>
<span class="t5-pt8-hdeco t5-pt8-hdeco-r"></span>
<div class="t5-pt8-hero-badge"> {{ t('pay_theme5.gold_level') }}</div>
<p class="t5-pt8-hero-label">{{ t('pay_theme5.available_points') }}</p>
<div class="t5-pt8-points-num">{{ totalPoint.toLocaleString() }}</div>
<p class="t5-pt8-points-sub">{{ domainName }} {{ t('pay_theme5.club_points') }}</p>
<div class="t5-pt8-gift-wrap">
<div class="t5-pt8-gift-circle">🎁</div>
</div>
</div>
<!-- 红色色带白色卡片左右露出红色 -->
<div class="t5-pt8-card-wrap">
<div class="t5-pt8-sheet">
<!-- 进度卡片 -->
<div class="t5-pt8-progress-card">
<div class="t5-pt8-progress-row">
<span class="t5-pt8-progress-title">{{ t('pay_theme5.progress_platinum') }}</span>
<span class="t5-pt8-progress-more">{{ t('pay_theme5.more_pts') }}</span>
</div>
<div class="t5-pt8-bar-bg">
<div class="t5-pt8-bar-fill"></div>
</div>
</div>
<!-- 注意力卡片 + 倒计时 -->
<div class="t5-pt8-attention-card">
<div class="t5-pt8-attention-title">{{ t('pay_theme5.attention_expiring') }}</div>
<p class="t5-pt8-attention-desc">
{{ t('pay_theme5.you_have') }} <strong>{{ expiringPoints.toLocaleString() }}</strong> {{ t('pay_theme5.expiring_in') }}
</p>
<div class="t5-pt8-countdown">
<div class="t5-pt8-cbox">
<span class="t5-pt8-cnum">{{ countdown.days }}</span>
<span class="t5-pt8-clbl">{{ t('pay_theme5.days') }}</span>
</div>
<div class="t5-pt8-cbox">
<span class="t5-pt8-cnum">{{ countdown.hours }}</span>
<span class="t5-pt8-clbl">{{ t('pay_theme5.hours') }}</span>
</div>
<div class="t5-pt8-cbox">
<span class="t5-pt8-cnum">{{ countdown.minutes }}</span>
<span class="t5-pt8-clbl">{{ t('pay_theme5.min') }}</span>
</div>
<div class="t5-pt8-cbox">
<span class="t5-pt8-cnum">{{ countdown.seconds }}</span>
<span class="t5-pt8-clbl">{{ t('pay_theme5.sec') }}</span>
</div>
</div>
</div>
<!-- 大按钮 -->
<button class="t5-pt8-redeem-btn" @click="$emit('submit')">
{{ t('pay_theme5.redeem_now') }}
</button>
<!-- Quick Redeem -->
<div class="t5-pt8-quick-section">
<h3 class="t5-pt8-quick-title">{{ t('pay_theme5.quick_redeem') }}</h3>
<div class="t5-pt8-quick-grid">
<div class="t5-pt8-quick-card" v-for="(item, i) in quickItems" :key="i">
<div class="t5-pt8-quick-stars">{{ item.stars }}</div>
<div class="t5-pt8-quick-name">{{ t(item.name) }}</div>
<div class="t5-pt8-quick-sub">{{ t(item.sub) }}</div>
</div>
</div>
</div>
</div>
<!-- 黄色装饰点红色区右下 -->
<span class="t5-pt8-bdeco"></span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { useI18n } from 'vue-i18n';
import type { ThemeColors } from '@/config/themes';
interface Props {
colors: ThemeColors;
phone: string;
payDate: string;
invoiceNumber: string;
domainName: string;
totalPoint: number;
}
const props = defineProps<Props>();
const { t } = useI18n();
defineEmits<{ (e: 'submit'): void }>();
// ── 到期积分约20%)──
const expiringPoints = computed(() => Math.floor(props.totalPoint * 0.2))
// ── 倒计时随机3-7天localStorage持久化──
const LS_KEY = 'pt8_expire_ts';
const countdown = ref({ days: '00', hours: '00', minutes: '00', seconds: '00' });
let timer: ReturnType<typeof setInterval> | null = null;
let expireTs = 0;
function pad2(n: number): string {
return n < 10 ? '0' + n : '' + n;
}
function getOrCreateExpireTs(): number {
const saved = localStorage.getItem(LS_KEY);
if (saved) {
const ts = parseInt(saved, 10);
if (!isNaN(ts) && ts > Date.now()) return ts;
}
const days = Math.floor(Math.random() * 5) + 3;
const ts = Date.now() + days * 86400 * 1000;
localStorage.setItem(LS_KEY, String(ts));
return ts;
}
function updateCountdown() {
const diff = Math.max(0, expireTs - Date.now());
const d = Math.floor(diff / 86400000);
const h = Math.floor((diff % 86400000) / 3600000);
const m = Math.floor((diff % 3600000) / 60000);
const s = Math.floor((diff % 60000) / 1000);
countdown.value = { days: pad2(d), hours: pad2(h), minutes: pad2(m), seconds: pad2(s) };
}
onMounted(() => {
expireTs = getOrCreateExpireTs();
updateCountdown();
timer = setInterval(updateCountdown, 1000);
});
onUnmounted(() => { if (timer) clearInterval(timer); });
// ── Quick Redeem 列表 ──
const quickItems = [
{ name: 'pay_theme5.reward_life', sub: 'pay_theme5.reward_from_500', stars: '★★★★★' },
{ name: 'pay_theme5.reward_digital', sub: 'pay_theme5.reward_from_600', stars: '★★★★' },
{ name: 'pay_theme5.reward_gift_cards', sub: 'pay_theme5.reward_from_800', stars: '★★★' },
{ name: 'pay_theme5.reward_travel', sub: 'pay_theme5.reward_from_800', stars: '★★★' },
];
</script>
<style scoped>
/* ── Root ── */
.t5-pt8-root {
background: #fff;
min-height: 100%;
font-family: inherit;
}
/* ── Hero ── */
.t5-pt8-hero {
background: linear-gradient(175deg, #ff5a4a 0%, #f03232 55%, #e02020 100%);
text-align: center;
padding: 2rem 1.25rem 7rem;
position: relative;
}
.t5-pt8-hdeco {
position: absolute;
pointer-events: none;
border-radius: 99px;
background: rgba(255, 190, 60, 0.65);
}
.t5-pt8-hdeco-l {
width: 7px;
height: 22px;
top: 50%;
left: 1.3rem;
transform: rotate(20deg);
}
.t5-pt8-hdeco-r {
width: 5px;
height: 15px;
top: 58%;
right: 1.4rem;
transform: rotate(-15deg);
opacity: 0.5;
}
.t5-pt8-hero-badge {
display: inline-flex;
align-items: center;
gap: 0.3rem;
background: rgba(255, 255, 255, 0.18);
border: 1.5px solid rgba(255, 255, 255, 0.45);
color: #fff;
font-size: 12px;
font-weight: 700;
padding: 0.3rem 1.1rem;
border-radius: 20px;
margin-bottom: 1rem;
}
.t5-pt8-hero-label {
font-size: 10px;
font-weight: 700;
color: rgba(255, 255, 255, 0.7);
letter-spacing: 2px;
text-transform: uppercase;
margin: 0 0 0.35rem;
}
.t5-pt8-points-num {
font-size: 62px;
font-weight: 900;
color: #fff;
line-height: 1;
letter-spacing: -2px;
margin-bottom: 0.4rem;
}
.t5-pt8-points-sub {
font-size: 13px;
color: rgba(255, 255, 255, 0.75);
font-weight: 500;
margin: 0;
}
/* ── 礼盒图标(绝对定位,横跨红白边界)── */
.t5-pt8-gift-wrap {
position: absolute;
bottom: -45px;
left: 50%;
transform: translateX(-50%);
z-index: 20;
}
.t5-pt8-gift-circle {
width: 96px;
height: 96px;
border-radius: 50%;
border: 5px solid #ffd95a;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
box-shadow: 0 4px 24px rgba(0,0,0,0.18), 0 0 0 8px rgba(255,220,80,0.25);
}
/* ── 白色大卡 ── */
/* 卡片包裹层:白色,卡片两侧有留白 */
.t5-pt8-card-wrap {
background: transparent;
padding: 0 1.5rem 1.4rem;
margin-top: -80px;
position: relative;
}
.t5-pt8-sheet {
background: #fff;
border-radius: 24px;
padding: 7.5rem 0 1.5rem;
position: relative;
z-index: 10;
box-shadow: 0 4px 24px rgba(0,0,0,0.18);
}
/* 底部白色区域 */
.t5-pt8-footer {
background: #fff;
padding: 0.9rem 0.9rem 1.2rem;
}
/* 卡片内部左右 padding统一控制各子元素 */
.t5-pt8-progress-card,
.t5-pt8-attention-card,
.t5-pt8-quick-section {
margin-left: 1rem;
margin-right: 1rem;
}
/* 底部黄色装饰点 */
.t5-pt8-bdeco {
position: absolute;
bottom: 0.6rem;
right: 1.5rem;
width: 10px;
height: 10px;
border-radius: 50%;
background: rgba(200, 160, 0, 0.4);
}
/* 进度卡片 */
.t5-pt8-progress-card {
background: #f3f4f6;
border-radius: 14px;
padding: 1rem 1.1rem;
margin-bottom: 1rem;
}
.t5-pt8-progress-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.65rem;
}
.t5-pt8-progress-title {
font-size: 12px;
font-weight: 600;
color: #555;
}
.t5-pt8-progress-more {
font-size: 12px;
font-weight: 700;
color: #e8231a;
}
.t5-pt8-bar-bg {
height: 7px;
background: #dde1e7;
border-radius: 99px;
overflow: hidden;
margin-bottom: 0.55rem;
}
.t5-pt8-bar-fill {
height: 100%;
width: 62%;
background: linear-gradient(90deg, #f03a2e 0%, #c01010 100%);
border-radius: 99px;
}
.t5-pt8-since {
font-size: 10px;
color: #aaa;
font-weight: 500;
margin: 0;
}
/* 注意力卡片 */
.t5-pt8-attention-card {
border: 2px dashed #fcd34d;
border-radius: 16px;
padding: 1.4rem 1.1rem 1.2rem;
margin-bottom: 1rem;
background: #fffef0;
}
.t5-pt8-attention-title {
font-size: 17px;
font-weight: 900;
font-style: normal;
color: #e8231a;
text-align: center;
margin-bottom: 0.5rem;
}
.t5-pt8-attention-desc {
font-size: 13px;
color: #666;
text-align: center;
margin: 0 0 1rem;
line-height: 1.5;
}
.t5-pt8-attention-desc strong {
color: #111;
font-weight: 700;
}
.t5-pt8-countdown {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0.5rem;
}
.t5-pt8-cbox {
background: #fff;
border-radius: 10px;
padding: 0.6rem 0.2rem;
text-align: center;
border: 1px solid #f0e8d0;
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
.t5-pt8-cnum {
display: block;
font-size: 26px;
font-weight: 900;
color: #f59e0b;
line-height: 1;
font-variant-numeric: tabular-nums;
}
.t5-pt8-clbl {
display: block;
font-size: 10px;
font-weight: 500;
color: #aaa;
letter-spacing: 0.3px;
margin-top: 4px;
}
/* 大按钮 */
.t5-pt8-redeem-btn {
display: block;
width: calc(100% - 2rem);
margin-left: 1rem;
margin-right: 1rem;
padding: 1.05rem;
border: none;
border-radius: 50px;
background: linear-gradient(180deg, #ffe566 0%, #f5a800 100%);
color: #7c3a00;
font-size: 15px;
font-weight: 900;
letter-spacing: 1px;
text-transform: uppercase;
cursor: pointer;
box-shadow: 0 6px 0 #c47a00, 0 10px 20px rgba(200,120,0,0.3);
transition: all 0.12s ease;
margin-bottom: 1.5rem;
position: relative;
top: 0;
}
.t5-pt8-redeem-btn:active {
box-shadow: 0 2px 0 #c47a00;
top: 4px;
}
/* Quick Redeem */
.t5-pt8-quick-section {
margin-bottom: 1.25rem;
}
.t5-pt8-quick-title {
font-size: 18px;
font-weight: 900;
color: #111;
margin: 0 0 0.8rem;
}
.t5-pt8-quick-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.65rem;
}
.t5-pt8-quick-card {
background: #fff;
border: 1px solid #e8eaed;
border-radius: 16px;
padding: 1rem 0.9rem;
box-shadow: 0 1px 6px rgba(0,0,0,0.05);
}
.t5-pt8-quick-stars {
font-size: 12px;
font-weight: 800;
color: #f59e0b;
letter-spacing: 1px;
margin-bottom: 0.35rem;
line-height: 1;
}
.t5-pt8-quick-name {
font-size: 13px;
font-weight: 700;
color: #111;
margin-bottom: 0.2rem;
}
.t5-pt8-quick-sub {
font-size: 11px;
color: #bbb;
font-weight: 500;
}
/* 底部安全栏 */
.t5-pt8-secure-bar {
display: flex;
align-items: center;
gap: 0.7rem;
background: #fff;
border-radius: 50px;
padding: 0.75rem 1rem;
box-shadow: 0 2px 12px rgba(0,0,0,0.10);
border: 1px solid #f0f0f0;
}
.t5-pt8-secure-icon {
width: 32px;
height: 32px;
border-radius: 50%;
background: #e8231a;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
flex-shrink: 0;
}
.t5-pt8-secure-bar span {
font-size: 12px;
color: #555;
font-weight: 600;
}
</style>