854 lines
21 KiB
Vue
854 lines
21 KiB
Vue
<template>
|
||
<view class="home-container">
|
||
<!-- 自定义头部 -->
|
||
<view class="custom-header">
|
||
<view class="status-bar"></view>
|
||
<view class="header-content">
|
||
<view class="header-title">情侣菜谱</view>
|
||
<view class="header-actions">
|
||
<uni-icons type="more-filled" size="20" color="#fff"></uni-icons>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 主要内容区域 -->
|
||
<view class="main-content">
|
||
<!-- 情侣头像和恋爱天数 -->
|
||
<view class="couple-info">
|
||
<view class="avatar-section">
|
||
<view class="avatar left-avatar">
|
||
<img
|
||
:src="userInfo.avatar"
|
||
class="avatar-img"
|
||
:key="userInfo.avatar"
|
||
alt="用户头像"
|
||
></img>
|
||
</view>
|
||
<view class="heart-icon">
|
||
<uni-icons type="heart-filled" size="30" color="#FF6B9D"></uni-icons>
|
||
</view>
|
||
<view class="avatar right-avatar">
|
||
<img
|
||
:src="partnerInfo.avatar"
|
||
class="avatar-img"
|
||
alt="伴侣头像"
|
||
></img>
|
||
<view v-if="!partnerInfo.avatar" class="add-partner">
|
||
<uni-icons type="plus" size="24" color="#FF6B9D"></uni-icons>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="relationship-info">
|
||
<text class="relationship-text">我们在一起已经</text>
|
||
<view class="days-count">
|
||
<text class="days-number">{{ loveDays }}</text>
|
||
<text class="days-unit">天</text>
|
||
</view>
|
||
<text class="start-date">{{ startDate }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 快捷功能卡片 -->
|
||
<view class="feature-cards">
|
||
<view class="feature-card diary-card" @click="goToDiary">
|
||
<view class="card-content">
|
||
<text class="card-title">写日志</text>
|
||
<uni-icons type="compose" size="32" color="#fff"></uni-icons>
|
||
</view>
|
||
</view>
|
||
<view class="feature-card order-card" @click="goToOrder">
|
||
<view class="card-content">
|
||
<text class="card-title">点餐下单</text>
|
||
<uni-icons type="cart" size="32" color="#fff"></uni-icons>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 纪念日列表 -->
|
||
<view class="anniversary-section">
|
||
<view class="section-header">
|
||
<text class="section-title">重要纪念日</text>
|
||
<view class="add-anniversary" @click="addAnniversary">
|
||
<uni-icons type="plus" size="20" color="#FF6B9D"></uni-icons>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="anniversary-list">
|
||
<view
|
||
v-for="(item, index) in anniversaryList"
|
||
:key="item.ID || index"
|
||
class="anniversary-item"
|
||
@click="viewAnniversary(item)"
|
||
>
|
||
<view class="anniversary-icon no-circle" :data-type="item.type">
|
||
<view class="icon-wrapper">
|
||
<!-- 生日类型显示图片,其他类型显示图标 -->
|
||
<img
|
||
v-if="item.type === 2"
|
||
src="/static/images/birthday.png"
|
||
class="birthday-icon"
|
||
alt="生日"
|
||
/>
|
||
<uni-icons
|
||
v-else
|
||
:type="getIconByType(item.type)"
|
||
size="26"
|
||
:color="getIconColorByType(item.type)"
|
||
></uni-icons>
|
||
</view>
|
||
</view>
|
||
<view class="anniversary-info">
|
||
<text class="anniversary-name">{{ item.title }}</text>
|
||
<view class="anniversary-meta">
|
||
<!-- <text class="anniversary-type" :data-type="item.type">{{ getTypeTextByType(item.type) }}</text> -->
|
||
<text class="anniversary-date">{{ item.date }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="anniversary-countdown">
|
||
<text class="countdown-text">{{ getCountdownText(item) }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view v-if="anniversaryList.length === 0" class="empty-anniversary">
|
||
<text class="empty-text">还没有添加纪念日</text>
|
||
<text class="empty-desc">点击右上角添加第一个纪念日吧</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onMounted } from 'vue'
|
||
import { useUserStore } from '@/store/user.js'
|
||
import api from '@/api'
|
||
import { onPullDownRefresh } from '@dcloudio/uni-app'
|
||
|
||
const userStore = useUserStore()
|
||
|
||
// 响应式数据
|
||
const userInfo = ref({
|
||
avatar: '',
|
||
nickname: ''
|
||
})
|
||
|
||
const partnerInfo = ref({
|
||
avatar: '',
|
||
nickname: ''
|
||
})
|
||
|
||
const startDate = ref('')
|
||
const loveDays = ref(0)
|
||
|
||
const anniversaryList = ref([])
|
||
|
||
// 计算属性
|
||
const computedLoveDays = computed(() => loveDays.value)
|
||
|
||
// API: 初始化用户与情侣信息
|
||
const initHomeData = async () => {
|
||
try {
|
||
// 1. 优先从缓存拿本人信息(登录后已缓存到 userInfo)
|
||
const cached = uni.getStorageSync('userInfo')
|
||
if (cached) {
|
||
userInfo.value.avatar = cached.avatar || ''
|
||
userInfo.value.nickname = cached.nick_name || cached.nickname || ''
|
||
}
|
||
|
||
// 2. 调用情侣关系接口,拿到 loverId 与 startDate
|
||
const loverRes = await api.getLoverInfo()
|
||
if (loverRes?.code === 0 && loverRes.data) {
|
||
const { loverId, startDate: s } = loverRes.data
|
||
// 设置开始日期(用于恋爱天数)
|
||
startDate.value = s || ''
|
||
|
||
// 若未缓存本人信息或需要刷新,可用 getUserInfo 再拉一遍(可选)
|
||
if (!userInfo.value.avatar || !userInfo.value.nickname) {
|
||
const meRes = await api.getUserInfo()
|
||
if (meRes?.code === 0 && meRes.data) {
|
||
userInfo.value.avatar = meRes.data.avatar || userInfo.value.avatar
|
||
userInfo.value.nickname = meRes.data.nick_name || meRes.data.nickname || userInfo.value.nickname
|
||
}
|
||
}
|
||
|
||
// 3. 根据 loverId 获取另一半资料
|
||
if (loverId) {
|
||
const loverInfoRes = await api.getUserInfoById(loverId)
|
||
if (loverInfoRes?.code === 0 && loverInfoRes.data) {
|
||
partnerInfo.value.avatar = loverInfoRes.data.avatar || ''
|
||
partnerInfo.value.nickname = loverInfoRes.data.nick_name || loverInfoRes.data.nickname || ''
|
||
}
|
||
}
|
||
|
||
// 4. 计算恋爱天数
|
||
computeLoveDays(startDate.value)
|
||
}
|
||
|
||
// 5. 加载纪念日列表
|
||
await loadAnniversaryList()
|
||
} catch (e) {
|
||
console.error('初始化首页数据失败:', e)
|
||
}
|
||
}
|
||
|
||
const computeLoveDays = (dateStr) => {
|
||
if (!dateStr) {
|
||
loveDays.value = 0
|
||
return
|
||
}
|
||
// 支持 yyyy-MM-dd 或 yyyy/MM/dd
|
||
const norm = dateStr.replace(/\./g, '-').replace(/\//g, '-')
|
||
const start = new Date(norm)
|
||
if (isNaN(start.getTime())) {
|
||
loveDays.value = 0
|
||
return
|
||
}
|
||
const today = new Date()
|
||
const diffTime = today.getTime() - start.getTime()
|
||
loveDays.value = Math.max(0, Math.ceil(diffTime / (1000 * 60 * 60 * 24)))
|
||
}
|
||
|
||
// 加载纪念日列表
|
||
const loadAnniversaryList = async () => {
|
||
try {
|
||
const res = await api.getMemorialDayList()
|
||
if (res?.code === 0 && res.data?.list) {
|
||
anniversaryList.value = res.data.list || []
|
||
// 按日期排序,只显示最近的几个
|
||
anniversaryList.value.sort((a, b) => {
|
||
const dateA = new Date(a.date)
|
||
const dateB = new Date(b.date)
|
||
return dateA - dateB
|
||
})
|
||
// 只显示前3个
|
||
anniversaryList.value = anniversaryList.value.slice(0, 3)
|
||
}
|
||
} catch (error) {
|
||
console.error('加载纪念日列表失败:', error)
|
||
}
|
||
}
|
||
|
||
// 获取纪念日倒计时文本
|
||
const getCountdownText = (item) => {
|
||
if (!item.date) return ''
|
||
const today = new Date()
|
||
const anniversary = new Date(item.date)
|
||
|
||
// 设置今年的纪念日
|
||
const thisYear = new Date(today.getFullYear(), anniversary.getMonth(), anniversary.getDate())
|
||
|
||
// 如果今年的纪念日已过,计算明年的
|
||
if (thisYear < today) {
|
||
thisYear.setFullYear(thisYear.getFullYear() + 1)
|
||
}
|
||
|
||
const diffTime = thisYear.getTime() - today.getTime()
|
||
const days = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||
|
||
if (days === 0) return '就是今天'
|
||
if (days < 0) return '已过'
|
||
if (days === 1) return '明天'
|
||
return `还有${days}天`
|
||
}
|
||
|
||
// 获取纪念日图标
|
||
const getIconByType = (type) => {
|
||
const iconMap = {
|
||
1: 'heart-filled', // 恋爱纪念日 - 使用 heart-filled
|
||
2: 'star-filled', // 生日 - 使用 star-filled
|
||
3: 'calendar-filled' // 其他 - 使用 calendar-filled
|
||
}
|
||
return iconMap[type] || 'calendar-filled'
|
||
}
|
||
|
||
// 获取纪念日图标颜色
|
||
const getIconColorByType = (type) => {
|
||
const colorMap = {
|
||
1: '#FF6B9D', // 恋爱纪念日 - 粉色
|
||
2: '#FFD700', // 生日 - 金色
|
||
3: '#4CAF50' // 其他 - 绿色
|
||
}
|
||
return colorMap[type] || '#FF6B9D'
|
||
}
|
||
|
||
// 获取纪念日类型文字
|
||
const getTypeTextByType = (type) => {
|
||
const textMap = {
|
||
1: '恋爱纪念日',
|
||
2: '生日',
|
||
3: '其他'
|
||
}
|
||
return textMap[type] || '其他'
|
||
}
|
||
|
||
// 方法
|
||
const invitePartner = () => {
|
||
uni.showToast({
|
||
title: '邀请功能开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
const goToDiary = () => {
|
||
uni.switchTab({ url: '/pages/diary/diary' })
|
||
}
|
||
|
||
const goToOrder = () => {
|
||
uni.switchTab({ url: '/pages/order/order' })
|
||
}
|
||
|
||
const addAnniversary = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/anniversary/anniversary'
|
||
})
|
||
}
|
||
|
||
const viewAnniversary = (item) => {
|
||
uni.navigateTo({
|
||
url: '/pages/anniversary/anniversary'
|
||
})
|
||
}
|
||
|
||
// 生命周期
|
||
onMounted(() => {
|
||
initHomeData()
|
||
})
|
||
|
||
// 下拉刷新
|
||
onPullDownRefresh(() => {
|
||
// 同时刷新用户信息和纪念日列表
|
||
Promise.all([
|
||
initHomeData(),
|
||
loadAnniversaryList()
|
||
]).finally(() => {
|
||
// 结束下拉刷新动画
|
||
uni.stopPullDownRefresh()
|
||
})
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.home-container {
|
||
min-height: 100vh;
|
||
background: linear-gradient(135deg, #FFE4E1 0%, #FFB6C1 50%, #E6E6FA 100%);
|
||
}
|
||
|
||
.custom-header {
|
||
background: linear-gradient(135deg, #FF6B9D 0%, #FF8E9E 100%);
|
||
padding: 0 20rpx;
|
||
|
||
.status-bar {
|
||
height: var(--status-bar-height);
|
||
}
|
||
|
||
.header-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 20rpx 0;
|
||
|
||
.header-title {
|
||
color: #fff;
|
||
font-size: 36rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.main-content {
|
||
padding: 40rpx 30rpx 60rpx;
|
||
}
|
||
|
||
.couple-info {
|
||
text-align: center;
|
||
margin-bottom: 60rpx;
|
||
|
||
.avatar-section {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
margin-bottom: 40rpx;
|
||
gap: 40rpx;
|
||
|
||
.avatar {
|
||
position: relative;
|
||
|
||
.avatar-img {
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
border-radius: 50%;
|
||
border: 4rpx solid #fff;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
|
||
object-fit: cover;
|
||
background: #f0f0f0;
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
|
||
&:hover {
|
||
transform: scale(1.05);
|
||
box-shadow: 0 6rpx 25rpx rgba(0, 0, 0, 0.2);
|
||
}
|
||
}
|
||
|
||
.add-partner {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 50%;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
}
|
||
|
||
.heart-icon {
|
||
animation: heartbeat 1.5s ease-in-out infinite;
|
||
filter: drop-shadow(0 2rpx 8rpx rgba(255, 107, 157, 0.3));
|
||
// background: rgba(255, 255, 255, 0.9);
|
||
border-radius: 50%;
|
||
padding: 15rpx;
|
||
// box-shadow: 0 4rpx 15rpx rgba(255, 107, 157, 0.2);
|
||
}
|
||
}
|
||
|
||
.relationship-info {
|
||
margin-bottom: 30rpx;
|
||
|
||
.relationship-text {
|
||
display: block;
|
||
color: #ff6b9d;
|
||
font-size: 31rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.days-count {
|
||
margin-bottom: 20rpx;
|
||
|
||
.days-number {
|
||
font-size: 80rpx;
|
||
font-weight: bold;
|
||
color: #FF6B9D;
|
||
}
|
||
|
||
.days-unit {
|
||
font-size: 32rpx;
|
||
color: #FF6B9D;
|
||
margin-left: 10rpx;
|
||
}
|
||
}
|
||
|
||
.start-date {
|
||
color: #ff6b9d;
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
|
||
.invite-button {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
background: linear-gradient(135deg, #FF6B9D 0%, #FF8E9E 100%);
|
||
color: #fff;
|
||
padding: 20rpx 40rpx;
|
||
border-radius: 50rpx;
|
||
font-size: 28rpx;
|
||
|
||
.invite-text {
|
||
color: #fff;
|
||
}
|
||
}
|
||
}
|
||
|
||
.feature-cards {
|
||
display: flex;
|
||
gap: 30rpx;
|
||
margin-bottom: 60rpx;
|
||
|
||
.feature-card {
|
||
flex: 1;
|
||
height: 160rpx;
|
||
border-radius: 20rpx;
|
||
overflow: hidden;
|
||
|
||
.card-content {
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 30rpx;
|
||
|
||
.card-title {
|
||
color: #fff;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
&.diary-card {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
}
|
||
|
||
&.order-card {
|
||
background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
|
||
}
|
||
}
|
||
}
|
||
|
||
.anniversary-section {
|
||
background: linear-gradient(135deg, #E6E6FA 0%, #DDA0DD 50%, #D8BFD8 100%);
|
||
border-radius: 25rpx;
|
||
padding: 30rpx;
|
||
margin-top: 20rpx;
|
||
box-shadow: 0 6rpx 25rpx rgba(221, 160, 221, 0.3);
|
||
animation: fadeInScale 0.8s ease-out;
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 30rpx;
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #333;
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: -8rpx;
|
||
left: 0;
|
||
width: 60rpx;
|
||
height: 3rpx;
|
||
background: linear-gradient(90deg, #FF6B9D, #FF8E9E);
|
||
border-radius: 2rpx;
|
||
}
|
||
}
|
||
|
||
.add-anniversary {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
background: #fff;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
|
||
transition: all 0.3s ease;
|
||
cursor: pointer;
|
||
|
||
&:active {
|
||
transform: scale(0.95);
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
&:hover {
|
||
transform: scale(1.05);
|
||
box-shadow: 0 6rpx 25rpx rgba(0, 0, 0, 0.15);
|
||
}
|
||
}
|
||
}
|
||
|
||
.anniversary-list {
|
||
.anniversary-item {
|
||
display: flex;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
padding: 35rpx;
|
||
border-radius: 25rpx;
|
||
margin-bottom: 25rpx;
|
||
box-shadow: 0 8rpx 30rpx rgba(221, 160, 221, 0.2);
|
||
backdrop-filter: blur(15rpx);
|
||
border: 2rpx solid rgba(255, 255, 255, 0.6);
|
||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||
position: relative;
|
||
overflow: hidden;
|
||
animation: slideInUp 0.6s ease-out;
|
||
|
||
@for $i from 1 through 5 {
|
||
&:nth-child(#{$i}) {
|
||
animation-delay: #{$i * 0.1}s;
|
||
}
|
||
}
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
|
||
transition: left 0.6s ease;
|
||
}
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 50%, rgba(255, 255, 255, 0.1) 100%);
|
||
opacity: 0;
|
||
transition: opacity 0.3s ease;
|
||
}
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
&:active {
|
||
transform: translateY(3rpx) scale(0.98);
|
||
box-shadow: 0 4rpx 20rpx rgba(221, 160, 221, 0.3);
|
||
|
||
&::before {
|
||
left: 100%;
|
||
}
|
||
|
||
&::after {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
|
||
&:hover {
|
||
transform: translateY(-2rpx);
|
||
box-shadow: 0 12rpx 40rpx rgba(221, 160, 221, 0.3);
|
||
}
|
||
|
||
.anniversary-icon {
|
||
margin-right: 35rpx;
|
||
border-radius: 50%;
|
||
padding: 20rpx;
|
||
position: relative;
|
||
z-index: 1;
|
||
transition: all 0.3s ease;
|
||
|
||
&[data-type="1"],
|
||
&[data-type="2"],
|
||
&[data-type="3"] {
|
||
background: transparent;
|
||
box-shadow: none;
|
||
}
|
||
|
||
&::after {
|
||
display: none;
|
||
}
|
||
|
||
.icon-wrapper {
|
||
background: transparent;
|
||
border-radius: 0;
|
||
padding: 0;
|
||
box-shadow: none;
|
||
|
||
.birthday-icon {
|
||
width: 50rpx;
|
||
height: 50rpx;
|
||
object-fit: contain;
|
||
display: block;
|
||
}
|
||
}
|
||
|
||
&:hover {
|
||
transform: scale(1.1);
|
||
|
||
&[data-type="1"] {
|
||
box-shadow: 0 6rpx 20rpx rgba(255, 107, 157, 0.4);
|
||
}
|
||
|
||
&[data-type="2"] {
|
||
box-shadow: 0 6rpx 20rpx rgba(255, 215, 0, 0.4);
|
||
}
|
||
|
||
&[data-type="3"] {
|
||
box-shadow: 0 6rpx 20rpx rgba(76, 175, 80, 0.4);
|
||
}
|
||
|
||
&::after {
|
||
opacity: 0.5;
|
||
transform: scale(1.1);
|
||
}
|
||
}
|
||
}
|
||
|
||
.anniversary-info {
|
||
flex: 1;
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.anniversary-name {
|
||
display: block;
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #2c3e50;
|
||
margin-bottom: 12rpx;
|
||
line-height: 1.3;
|
||
text-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.05);
|
||
}
|
||
|
||
.anniversary-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
margin-bottom: 12rpx;
|
||
|
||
.anniversary-type {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
padding: 6rpx 12rpx;
|
||
border-radius: 12rpx;
|
||
border: 1rpx solid;
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
&[data-type="1"] {
|
||
color: #FF6B9D;
|
||
background: rgba(255, 107, 157, 0.1);
|
||
border-color: rgba(255, 107, 157, 0.3);
|
||
}
|
||
|
||
&[data-type="2"] {
|
||
color: #FFD700;
|
||
background: rgba(255, 215, 0, 0.1);
|
||
border-color: rgba(255, 215, 0, 0.3);
|
||
}
|
||
|
||
&[data-type="3"] {
|
||
color: #4CAF50;
|
||
background: rgba(76, 175, 80, 0.1);
|
||
border-color: rgba(76, 175, 80, 0.3);
|
||
}
|
||
}
|
||
|
||
.anniversary-date {
|
||
font-size: 26rpx;
|
||
color: #7f8c8d;
|
||
font-weight: 500;
|
||
background: rgba(255, 255, 255, 0.8);
|
||
padding: 6rpx 12rpx;
|
||
border-radius: 15rpx;
|
||
display: inline-block;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||
}
|
||
}
|
||
}
|
||
|
||
.anniversary-countdown {
|
||
position: relative;
|
||
z-index: 1;
|
||
|
||
.countdown-text {
|
||
color: #FF6B9D;
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.95) 100%);
|
||
padding: 12rpx 20rpx;
|
||
border-radius: 25rpx;
|
||
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
||
border: 2rpx solid rgba(255, 107, 157, 0.2);
|
||
position: relative;
|
||
overflow: hidden;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, rgba(255, 107, 157, 0.1), transparent);
|
||
transition: left 0.6s ease;
|
||
}
|
||
|
||
&:hover::before {
|
||
left: 100%;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-anniversary {
|
||
text-align: center;
|
||
padding: 80rpx 0;
|
||
color: #666;
|
||
font-size: 28rpx;
|
||
background: rgba(255, 255, 255, 0.7);
|
||
border-radius: 20rpx;
|
||
backdrop-filter: blur(10rpx);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.4);
|
||
|
||
.empty-text {
|
||
display: block;
|
||
margin-bottom: 10rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.empty-desc {
|
||
font-size: 24rpx;
|
||
color: #888;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@keyframes heartbeat {
|
||
0% {
|
||
transform: scale(1);
|
||
filter: drop-shadow(0 2rpx 8rpx rgba(255, 107, 157, 0.3));
|
||
}
|
||
25% {
|
||
transform: scale(1.1);
|
||
filter: drop-shadow(0 4rpx 12rpx rgba(255, 107, 157, 0.4));
|
||
}
|
||
50% {
|
||
transform: scale(1.15);
|
||
filter: drop-shadow(0 6rpx 16rpx rgba(255, 107, 157, 0.5));
|
||
}
|
||
75% {
|
||
transform: scale(1.1);
|
||
filter: drop-shadow(0 4rpx 12rpx rgba(255, 107, 157, 0.4));
|
||
}
|
||
100% {
|
||
transform: scale(1);
|
||
filter: drop-shadow(0 2rpx 8rpx rgba(255, 107, 157, 0.3));
|
||
}
|
||
}
|
||
|
||
@keyframes slideInUp {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(50px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
@keyframes fadeInScale {
|
||
from {
|
||
opacity: 0;
|
||
transform: scale(0.9);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
</style>
|