Files
taimed-international-app/pages/vip/book.vue

391 lines
8.0 KiB
Vue

<template>
<view class="page-wrapper">
<!-- 自定义导航栏 -->
<nav-bar :title="$t('vip.bookVip')" />
<!-- VIP介绍卡片 -->
<view class="vip-intro-card">
<view class="vip-intro-header">
<text class="vip-intro-title">📚 读书VIP特权</text>
<!-- <text class="vip-intro-subtitle">畅享海量电子图书</text> -->
</view>
<view class="vip-intro-features">
<view class="feature-item">
<wd-icon name="check-circle" size="16px" color="#258feb" />
<text>畅享海量电子图书</text>
</view>
</view>
</view>
<!-- VIP套餐列表 -->
<view class="vip-packages">
<text class="section-title">选择套餐</text>
<view class="package-grid">
<view
class="package-card"
:class="{ 'package-card--popular': vip.isRecommend }"
v-for="(vip, index) in vipList"
:key="index"
@click="selectPackage(vip)"
>
<view class="package-header">
<view class="package-title-wrapper">
<text class="package-title package-title--vip">{{ vip.title }}</text>
</view>
</view>
<view class="package-price">
<text class="price-amount">{{ vip.money }}</text>
<text class="price-unit">{{ $t('global.coin') }}</text>
</view>
<view class="package-duration">
<view class="duration-text">{{ vip.days }} {{ $t('global.days') }}</view>
<view class="daily-price">{{ $t('vip.daily') }}{{ Math.round(vip.money / vip.days * 100) / 100 }}{{ $t('global.coin') }}</view>
</view>
<wd-button
type="primary"
size="small"
class="package-btn"
@click="handlePurchase(vip)"
>
{{ $t('vip.openVip') }}
</wd-button>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useUserStore } from '@/stores/user'
import { vipApi } from '@/api/modules/vip'
const userStore = useUserStore()
const vipList = ref([])
const getVipList = async () => {
const res = await vipApi.getBookVipList()
// 模拟推荐标识,实际项目中应该从后端获取
vipList.value = res.lableList || []
}
// 处理购买
const handlePurchase = (vip: any) => {
const selectedGoods = {
productId: vip.id,
productName: `${vip.title}`,
price: vip.money,
productImages: '/static/vip.png',
state: null,
orderType: 'abroadVip'
}
uni.navigateTo({
url: `/pages/order/vipConfirm`,
success: () => {
setTimeout(() => {
uni.$emit('selectedGoods', selectedGoods)
}, 100)
}
})
}
onShow(() => {
getVipList()
})
</script>
<style lang="scss" scoped>
.page-wrapper {
padding: 20rpx;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
// VIP介绍卡片
.vip-intro-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 20rpx;
padding: 30rpx 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10rpx);
}
.vip-intro-header {
text-align: center;
}
.vip-intro-title {
display: block;
font-size: 40rpx;
font-weight: bold;
color: #333;
margin-bottom: 10rpx;
}
.vip-intro-subtitle {
display: block;
font-size: 28rpx;
color: #666;
}
.vip-intro-features {
margin-top: 20rpx;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.feature-item {
display: flex;
align-items: center;
margin: 10rpx;
font-size: 28rpx;
color: #555;
}
.feature-item text {
margin-left: 8rpx;
}
// 套餐区域
.vip-packages {
margin-bottom: 30rpx;
}
.section-title {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #fff;
margin-bottom: 20rpx;
text-align: center;
}
.package-grid {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
gap: 20rpx;
}
.package-card {
flex: 0 0 calc(50% - 10rpx);
background: rgba(255, 255, 255, 0.95);
border-radius: 20rpx;
padding: 30rpx;
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.15);
backdrop-filter: blur(10rpx);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
&:active {
transform: scale(0.98);
}
}
.package-card--popular {
background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 50%, #fecfef 100%);
border: 2rpx solid #ff6b6b;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 0;
height: 0;
border-left: 60rpx solid transparent;
border-top: 60rpx solid #ff6b6b;
}
}
.package-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
// .package-title-wrapper {
// position: relative;
// display: inline-block;
// }
.package-title {
font-size: 36rpx;
font-weight: bold;
position: absolute;
top: 0;
right: 0;
z-index: 2;
display: inline-block;
width: 3em;
text-align: center;
padding: 8rpx 0;
border-radius: 12rpx;
transition: all 0.3s ease;
}
.package-title--vip {
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 25%, #ffd700 50%, #ffed4e 75%, #ffd700 100%);
color: #8b4513;
box-shadow:
0 4rpx 15rpx rgba(255, 215, 0, 0.6),
0 0 20rpx rgba(255, 215, 0, 0.4),
inset 0 2rpx 0 rgba(255, 255, 255, 0.3);
border: 1rpx solid rgba(255, 215, 0, 0.5);
text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.2);
}
.package-title--popular {
background: linear-gradient(135deg, #ffd700 0%, #ffed4e 25%, #ffd700 50%, #ffed4e 75%, #ffd700 100%);
color: #8b4513;
box-shadow:
0 6rpx 20rpx rgba(255, 215, 0, 0.8),
0 0 30rpx rgba(255, 215, 0, 0.6),
inset 0 2rpx 0 rgba(255, 255, 255, 0.4);
border: 2rpx solid rgba(255, 215, 0, 0.7);
text-shadow: 0 1rpx 3rpx rgba(0, 0, 0, 0.3);
font-size: 38rpx;
}
.title-decoration {
position: absolute;
top: -10rpx;
right: -10rpx;
width: 20rpx;
height: 20rpx;
background: linear-gradient(45deg, #ffd700, #ffed4e);
border-radius: 50%;
animation: decorationPulse 2s ease-in-out infinite;
z-index: 1;
}
@keyframes crownFloat {
0%, 100% { transform: translateY(0rpx); }
50% { transform: translateY(-4rpx); }
}
@keyframes starSparkle {
0%, 100% {
transform: scale(1) rotate(0deg);
filter: brightness(1);
}
50% {
transform: scale(1.2) rotate(180deg);
filter: brightness(1.3);
}
}
@keyframes decorationPulse {
0%, 100% {
transform: scale(1);
opacity: 0.8;
}
50% {
transform: scale(1.3);
opacity: 1;
}
}
.popular-badge {
background: #ff6b6b;
padding: 4rpx 12rpx;
border-radius: 20rpx;
}
.popular-text {
color: #fff;
font-size: 20rpx;
font-weight: bold;
}
.package-price {
text-align: center;
margin-bottom: 20rpx;
}
.price-amount {
font-size: 48rpx;
font-weight: bold;
color: #ff6b6b;
}
.price-unit {
font-size: 28rpx;
color: #666;
margin-left: 8rpx;
}
.package-duration {
margin-bottom: 20rpx;
padding: 15rpx;
background: rgba(102, 126, 234, 0.1);
border-radius: 12rpx;
text-align: center;
}
.duration-text {
font-size: 28rpx;
color: #333;
font-weight: bold;
margin-bottom: 10rpx;
}
.daily-price {
font-size: 24rpx;
color: #666;
}
.package-features {
margin-bottom: 30rpx;
}
.feature-dot {
font-size: 24rpx;
color: #555;
margin-bottom: 10rpx;
padding-left: 20rpx;
position: relative;
&::before {
content: '•';
position: absolute;
left: 0;
color: #667eea;
font-weight: bold;
}
}
.package-btn {
width: 100%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border: none !important;
border-radius: 50rpx !important;
font-size: 28rpx !important;
font-weight: bold;
padding: 30rpx !important;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
}
}
.package-btn--popular {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%) !important;
}
// 响应式设计
@media (max-width: 480px) {
.package-grid {
grid-template-columns: 1fr;
}
}
</style>