135 lines
4.5 KiB
Vue
135 lines
4.5 KiB
Vue
<template>
|
||
<view class="expiry-overlay" @tap.stop>
|
||
<view class="expiry-dialog" :class="`expiry-${reminder.level}`" role="dialog"
|
||
aria-modal="true" aria-label="套餐临期提醒" @keydown.esc="$emit('close')">
|
||
<view class="reminder-header">
|
||
<button class="reminder-close" aria-label="关闭临期提醒" @tap="$emit('close')">×</button>
|
||
<view class="clock-halo" aria-hidden="true"><view class="clock-face"></view></view>
|
||
<view class="reminder-title">套餐即将到期</view>
|
||
<view class="remaining-label">当前资产套餐剩余</view>
|
||
<view class="remaining-days"><text class="day-number">{{ reminder.remaining_days }}</text><text class="day-unit">天</text></view>
|
||
</view>
|
||
<view class="reminder-content">
|
||
<view class="expiry-details">
|
||
<text class="expiry-label">预计到期时间</text>
|
||
<text class="expiry-value">{{ formatShanghaiExpiry(reminder.expires_at) }}</text>
|
||
</view>
|
||
<view class="reminder-description">为避免套餐到期影响使用,请及时续费。</view>
|
||
<button class="reminder-confirm" @tap="$emit('renew')">立即续费</button>
|
||
<button class="reminder-later" @tap="$emit('close')">我知道了</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { formatShanghaiExpiry } from '@/utils/expiry-reminder.js';
|
||
defineProps({ reminder: { type: Object, required: true } });
|
||
defineEmits(['close', 'renew']);
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.expiry-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 1200;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 40rpx;
|
||
box-sizing: border-box;
|
||
background: rgba(20, 26, 36, 0.48);
|
||
backdrop-filter: blur(4px);
|
||
}
|
||
.expiry-dialog {
|
||
width: 100%;
|
||
max-width: 640rpx;
|
||
max-height: calc(100vh - 80rpx);
|
||
overflow-y: auto;
|
||
border-radius: 32rpx;
|
||
background: var(--bg-primary);
|
||
box-shadow: 0 24rpx 80rpx rgba(0, 0, 0, 0.18);
|
||
}
|
||
.reminder-header {
|
||
position: relative;
|
||
padding: 40rpx 36rpx 28rpx;
|
||
text-align: center;
|
||
background: linear-gradient(180deg, var(--reminder-tint), var(--bg-primary));
|
||
}
|
||
.reminder-close {
|
||
position: absolute;
|
||
top: 20rpx;
|
||
right: 20rpx;
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
margin: 0;
|
||
padding: 0;
|
||
border-radius: 50%;
|
||
font-size: 40rpx;
|
||
line-height: 52rpx;
|
||
color: var(--text-tertiary);
|
||
background: transparent;
|
||
}
|
||
.reminder-close::after, .reminder-confirm::after, .reminder-later::after { border: none; }
|
||
.clock-halo {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 108rpx;
|
||
height: 108rpx;
|
||
margin: 28rpx auto 22rpx;
|
||
border-radius: 50%;
|
||
background: var(--reminder-tint);
|
||
}
|
||
.clock-face {
|
||
position: relative;
|
||
width: 50rpx;
|
||
height: 50rpx;
|
||
border: 4rpx solid var(--reminder-color);
|
||
border-radius: 50%;
|
||
}
|
||
.clock-face::before, .clock-face::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 23rpx;
|
||
top: 10rpx;
|
||
width: 4rpx;
|
||
height: 17rpx;
|
||
border-radius: 4rpx;
|
||
background: var(--reminder-color);
|
||
}
|
||
.clock-face::after { top: 23rpx; height: 14rpx; transform: rotate(-55deg); transform-origin: top center; }
|
||
.reminder-title { color: var(--text-primary); font-size: 38rpx; font-weight: 700; }
|
||
.remaining-label { margin-top: 20rpx; color: var(--text-secondary); font-size: 26rpx; }
|
||
.remaining-days { margin-top: 8rpx; color: var(--reminder-color); line-height: 1.2; }
|
||
.day-number { font-size: 88rpx; font-weight: 700; letter-spacing: -3rpx; font-variant-numeric: tabular-nums; }
|
||
.day-unit { margin-left: 12rpx; font-size: 28rpx; }
|
||
.reminder-content { padding: 0 36rpx 36rpx; }
|
||
.expiry-details {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10rpx;
|
||
padding: 22rpx;
|
||
border-radius: 16rpx;
|
||
text-align: center;
|
||
background: var(--bg-secondary);
|
||
}
|
||
.expiry-label { font-size: 22rpx; color: var(--text-tertiary); }
|
||
.expiry-value { font-size: 26rpx; color: var(--text-primary); font-weight: 500; }
|
||
.reminder-description { margin: 22rpx 0 28rpx; color: var(--text-secondary); font-size: 24rpx; line-height: 1.6; text-align: center; }
|
||
.reminder-confirm {
|
||
margin: 0;
|
||
padding: 24rpx;
|
||
border-radius: 16rpx;
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
line-height: 1;
|
||
color: #fff;
|
||
background: var(--reminder-color);
|
||
}
|
||
.expiry-red { --reminder-color: #d94040; --reminder-tint: rgba(217, 64, 64, 0.08); }
|
||
.reminder-later { margin: 12rpx 0 0; padding: 14rpx; font-size: 24rpx; line-height: 1.5; color: var(--text-tertiary); background: transparent; }
|
||
.expiry-purple { --reminder-color: #8850c4; --reminder-tint: rgba(136, 80, 196, 0.08); }
|
||
.expiry-pink { --reminder-color: #ce4878; --reminder-tint: rgba(206, 72, 120, 0.08); }
|
||
</style>
|