154 lines
4.3 KiB
Vue
154 lines
4.3 KiB
Vue
<script lang="ts" setup>
|
||
/**
|
||
* 诊所设置「基础资料」会员卡片
|
||
* 大尺寸等级徽标 + 期限丝带叠加,展示等级名与到期时间
|
||
*/
|
||
import { computed } from 'vue';
|
||
|
||
import VipBadgeCombo from './VipBadgeCombo.vue';
|
||
|
||
const props = defineProps<{
|
||
vip?: Record<string, any> | null;
|
||
}>();
|
||
|
||
const hasVipVisual = computed(() => {
|
||
const v = props.vip;
|
||
return !!(v && (v.badge_url || v.duration_badge_url));
|
||
});
|
||
|
||
const expireText = computed(() => {
|
||
const v = props.vip;
|
||
if (!v) return '默认会员';
|
||
if (v.is_lifetime) return '永久有效';
|
||
const expireAt = Number(v.expire_at || 0);
|
||
if (!expireAt) {
|
||
if ((v.level_code || 'V0') === 'V0') return '默认会员';
|
||
return '永久有效';
|
||
}
|
||
if (typeof v.expire_at === 'string' && String(v.expire_at).includes('-')) {
|
||
return `有效期至 ${v.expire_at}`;
|
||
}
|
||
const d = new Date(expireAt * 1000);
|
||
const pad = (n: number) => String(n).padStart(2, '0');
|
||
return `有效期至 ${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
||
});
|
||
</script>
|
||
<template>
|
||
<!-- 黑金会员卡:与小程序端 vip-member-card 同一套视觉语言,深色卡面亮暗主题通用 -->
|
||
<div class="store-vip-card">
|
||
<div class="store-vip-card__glow"></div>
|
||
<div class="store-vip-card__sheen"></div>
|
||
<VipBadgeCombo
|
||
v-if="hasVipVisual"
|
||
size="xl"
|
||
:badge-url="vip?.badge_url"
|
||
:duration-badge-url="vip?.duration_badge_url"
|
||
:level-name="vip?.level_name"
|
||
:duration-label="vip?.duration_label"
|
||
/>
|
||
<div v-else class="store-vip-card__placeholder">V</div>
|
||
<div class="store-vip-card__info">
|
||
<div class="store-vip-card__title-row">
|
||
<span class="store-vip-card__title">{{ vip?.level_name || '普通会员' }}</span>
|
||
<span class="store-vip-card__chip">{{ vip?.duration_label || '普通会员' }}</span>
|
||
</div>
|
||
<div class="store-vip-card__expire">{{ expireText }}</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<style scoped>
|
||
.store-vip-card {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24px;
|
||
padding: 20px 28px;
|
||
margin-bottom: 24px;
|
||
overflow: hidden;
|
||
border-radius: 18px;
|
||
/* 深色曜石底 + 右上暗金光晕,比单一渐变更有实体卡层次 */
|
||
background:
|
||
radial-gradient(120% 160% at 100% 0%, rgba(212, 175, 55, 0.22) 0%, rgba(212, 175, 55, 0) 45%),
|
||
linear-gradient(135deg, #23201a 0%, #12100c 55%, #1f1a12 100%);
|
||
border: 1px solid rgba(220, 186, 110, 0.35);
|
||
box-shadow:
|
||
0 12px 32px rgba(0, 0, 0, 0.28),
|
||
0 2px 8px rgba(212, 175, 55, 0.12);
|
||
}
|
||
/* 右上金色光晕:模拟灯光打在卡面的高光 */
|
||
.store-vip-card__glow {
|
||
position: absolute;
|
||
top: -70px;
|
||
right: -50px;
|
||
width: 220px;
|
||
height: 220px;
|
||
border-radius: 50%;
|
||
background: radial-gradient(circle, rgba(240, 217, 168, 0.26) 0%, rgba(240, 217, 168, 0) 70%);
|
||
pointer-events: none;
|
||
}
|
||
/* 斜切静态流光条:金属光泽感 */
|
||
.store-vip-card__sheen {
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
left: 32%;
|
||
width: 90px;
|
||
transform: skewX(-24deg);
|
||
background: linear-gradient(
|
||
90deg,
|
||
rgba(255, 255, 255, 0) 0%,
|
||
rgba(255, 255, 255, 0.05) 50%,
|
||
rgba(255, 255, 255, 0) 100%
|
||
);
|
||
pointer-events: none;
|
||
}
|
||
.store-vip-card__placeholder {
|
||
display: flex;
|
||
flex-shrink: 0;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 120px;
|
||
height: 120px;
|
||
font-size: 48px;
|
||
font-weight: 700;
|
||
color: #f0d9a8;
|
||
text-shadow: 0 2px 8px rgba(212, 175, 55, 0.4);
|
||
background: radial-gradient(circle, rgba(212, 175, 55, 0.16) 0%, rgba(212, 175, 55, 0.04) 100%);
|
||
border: 1px solid rgba(220, 186, 110, 0.4);
|
||
border-radius: 50%;
|
||
box-shadow: inset 0 0 16px rgba(212, 175, 55, 0.15);
|
||
}
|
||
.store-vip-card__info {
|
||
position: relative;
|
||
min-width: 0;
|
||
}
|
||
.store-vip-card__title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-bottom: 8px;
|
||
}
|
||
.store-vip-card__title {
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
line-height: 1.3;
|
||
color: #f5e3bd;
|
||
letter-spacing: 1px;
|
||
text-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
|
||
}
|
||
/* 期限徽章:金字描边小胶囊 */
|
||
.store-vip-card__chip {
|
||
flex-shrink: 0;
|
||
padding: 1px 10px;
|
||
font-size: 12px;
|
||
color: #e8cf9a;
|
||
background: rgba(212, 175, 55, 0.1);
|
||
border: 1px solid rgba(232, 207, 154, 0.5);
|
||
border-radius: 999px;
|
||
}
|
||
.store-vip-card__expire {
|
||
font-size: 13px;
|
||
color: rgba(240, 224, 190, 0.75);
|
||
}
|
||
</style>
|