提交
This commit is contained in:
parent
107ab36a80
commit
952f70d3e8
12
App.vue
12
App.vue
|
|
@ -62,12 +62,12 @@ export default {
|
|||
},
|
||||
onShow: function () {
|
||||
console.log("App Show");
|
||||
// 如果不是首次启动才调用登录记录接口,避免与onLaunch重复调用
|
||||
if (!this.isFirstLaunch) {
|
||||
this.callLoginRecordApi();
|
||||
} else {
|
||||
this.isFirstLaunch = false; // 重置标志
|
||||
}
|
||||
// // 如果不是首次启动才调用登录记录接口,避免与onLaunch重复调用,有问题,当用户分享的时候,会频繁触发
|
||||
// if (!this.isFirstLaunch) {
|
||||
// this.callLoginRecordApi();
|
||||
// } else {
|
||||
// this.isFirstLaunch = false; // 重置标志
|
||||
// }
|
||||
},
|
||||
onHide: function () {
|
||||
console.log("App Hide");
|
||||
|
|
|
|||
58
components/empty-state/empty-state.vue
Normal file
58
components/empty-state/empty-state.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<view class="empty-state">
|
||||
<image class="empty-image" :src="imageSrc" mode="aspectFit"></image>
|
||||
<text class="empty-text">{{ message }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'EmptyState',
|
||||
props: {
|
||||
// 空状态显示的图片,默认使用kong.png
|
||||
imageSrc: {
|
||||
type: String,
|
||||
default: '/static/common/kong.png'
|
||||
},
|
||||
// 空状态显示的文本
|
||||
message: {
|
||||
type: String,
|
||||
default: '暂无数据'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.empty-state {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: emptyFadeIn 0.5s ease-out;
|
||||
}
|
||||
|
||||
.empty-image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
@keyframes emptyFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -466,6 +466,13 @@
|
|||
{
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/shouye/danye",
|
||||
"style" :
|
||||
{
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [{
|
||||
|
|
|
|||
|
|
@ -17,78 +17,83 @@
|
|||
|
||||
<!-- 内容列表区域 -->
|
||||
<view class="benefits-container">
|
||||
<!-- 进行中列表 -->
|
||||
<template v-if="tabCur == 1">
|
||||
<scroll-view scroll-y="true" class="benefits-scroll">
|
||||
<swiper class="benefits-swiper" :current="tabCur - 1" @change="handleSwiperChange">
|
||||
<!-- 进行中列表 -->
|
||||
<swiper-item>
|
||||
<scroll-view scroll-y="true" class="benefits-scroll">
|
||||
<template v-if="ongoingData.length > 0">
|
||||
<view v-for="(item, index) in ongoingData" :key="index" class="benefit-item relative"
|
||||
@click="$c.to({ url: '/pages/infinite/bonus_house_details?goods_id=' + item.id })">
|
||||
<text class="benefit-title">{{ item.title }}</text>
|
||||
<text class="benefit-tips">{{ item.tips }}</text>
|
||||
|
||||
<!-- 已结束列表 -->
|
||||
<view v-for="(item, index) in ongoingData" :key="index" class="benefit-item relative"
|
||||
@click="$c.to({ url: '/pages/infinite/bonus_house_details?goods_id=' + item.id })">
|
||||
<text class="benefit-title">{{ item.title }}</text>
|
||||
<text class="benefit-tips">{{ item.tips }}</text>
|
||||
|
||||
<view class="action-btn center">
|
||||
<text>马上参与</text>
|
||||
</view>
|
||||
<scroll-view scroll-x="true" class="goods-scroll">
|
||||
<view v-for="(item1, index1) in item.GoodsList" :key="index1" class="goods-item relative">
|
||||
<image class="goods-img" :src="item1.imgUrl">
|
||||
</image>
|
||||
<view class="goods-num center">
|
||||
<text>x{{ item1.num }}</text>
|
||||
<view class="action-btn center">
|
||||
<text>马上参与</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="divider"></view>
|
||||
<view class="popularity center">
|
||||
<image class="fire-icon" :src="$img1('checkin/Fire.png')"></image>
|
||||
<text class="popularity-text">{{ item.Popularity }}</text>
|
||||
</view>
|
||||
|
||||
<text class="time-text">{{ item.Time }}</text>
|
||||
</view>
|
||||
|
||||
</scroll-view>
|
||||
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<scroll-view scroll-y="true" class="benefits-scroll">
|
||||
|
||||
<view v-for="(item, index) in endedData" :key="index" class="benefit-item relative"
|
||||
@click="$c.to({ url: '/pages/infinite/bonus_house_details?goods_id=' + item.id })">
|
||||
<text class="benefit-title">{{ item.title }}</text>
|
||||
<text class="benefit-tips">{{ item.tips }}</text>
|
||||
|
||||
<view class="action-btn center ended">
|
||||
<text>已结束</text>
|
||||
</view>
|
||||
<scroll-view scroll-x="true" class="goods-scroll">
|
||||
<view v-for="(item1, index1) in item.GoodsList" :key="index1" class="goods-item relative">
|
||||
<image class="goods-img" :src="item1.imgUrl">
|
||||
</image>
|
||||
<view class="goods-num center">
|
||||
<text>x{{ item1.num }}</text>
|
||||
<scroll-view scroll-x="true" class="goods-scroll">
|
||||
<view v-for="(item1, index1) in item.GoodsList" :key="index1" class="goods-item relative">
|
||||
<image class="goods-img" :src="item1.imgUrl">
|
||||
</image>
|
||||
<view class="goods-num center">
|
||||
<text>x{{ item1.num }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="divider"></view>
|
||||
<view class="popularity center">
|
||||
<image class="fire-icon" :src="$img1('checkin/Fire.png')"></image>
|
||||
<text class="popularity-text">{{ item.Popularity }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="divider"></view>
|
||||
<view class="popularity center">
|
||||
<image class="fire-icon" :src="$img1('checkin/Fire.png')"></image>
|
||||
<text class="popularity-text">{{ item.Popularity }}</text>
|
||||
</view>
|
||||
|
||||
<text class="time-text">{{ item.Time }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
<text class="time-text">{{ item.Time }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<empty-state message="暂无进行中的活动"></empty-state>
|
||||
</template>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
|
||||
<!-- 已结束列表 -->
|
||||
<swiper-item>
|
||||
<scroll-view scroll-y="true" class="benefits-scroll">
|
||||
<template v-if="endedData.length > 0">
|
||||
<view v-for="(item, index) in endedData" :key="index" class="benefit-item relative"
|
||||
@click="$c.to({ url: '/pages/infinite/bonus_house_details?goods_id=' + item.id })">
|
||||
<text class="benefit-title">{{ item.title }}</text>
|
||||
<text class="benefit-tips">{{ item.tips }}</text>
|
||||
|
||||
<view class="action-btn center ended">
|
||||
<text>已结束</text>
|
||||
</view>
|
||||
<scroll-view scroll-x="true" class="goods-scroll">
|
||||
<view v-for="(item1, index1) in item.GoodsList" :key="index1" class="goods-item relative">
|
||||
<image class="goods-img" :src="item1.imgUrl">
|
||||
</image>
|
||||
<view class="goods-num center">
|
||||
<text>x{{ item1.num }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="divider"></view>
|
||||
<view class="popularity center">
|
||||
<image class="fire-icon" :src="$img1('checkin/Fire.png')"></image>
|
||||
<text class="popularity-text">{{ item.Popularity }}</text>
|
||||
</view>
|
||||
|
||||
<text class="time-text">{{ item.Time }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<empty-state message="暂无已结束的活动"></empty-state>
|
||||
</template>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
|
||||
<view class="btn-group row center">
|
||||
<!-- <view class="my-coupon center" @click="$c.to({ url: '/pages/infinite/my_coupons' })">
|
||||
<text>我的卡券</text>
|
||||
|
||||
</view> -->
|
||||
|
||||
<view class="reward-record center" @click="$c.to({ url: '/pages/infinite/reward_records' })">
|
||||
<text>赏品记录</text>
|
||||
</view>
|
||||
|
|
@ -99,17 +104,21 @@
|
|||
|
||||
<script>
|
||||
import PageContainer from '@/components/page-container/page-container.vue'
|
||||
import EmptyState from '@/components/empty-state/empty-state.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PageContainer
|
||||
PageContainer,
|
||||
EmptyState
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabCur: 1,
|
||||
ongoingData: [], // 进行中数据
|
||||
endedData: [], // 已结束数据
|
||||
loading: false
|
||||
loading: false,
|
||||
ongoingLoaded: false, // 进行中数据是否已加载
|
||||
endedLoaded: false, // 已结束数据是否已加载
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -120,7 +129,7 @@ export default {
|
|||
methods: {
|
||||
// 加载进行中的福利屋数据
|
||||
async loadOngoingData() {
|
||||
if (this.loading) return;
|
||||
if (this.loading || this.ongoingLoaded) return;
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
|
|
@ -133,6 +142,7 @@ export default {
|
|||
|
||||
if (res?.data?.data) {
|
||||
this.ongoingData = this.formatBenefitsData(res.data.data);
|
||||
this.ongoingLoaded = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载进行中福利屋数据失败:', error);
|
||||
|
|
@ -143,7 +153,7 @@ export default {
|
|||
|
||||
// 加载已结束的福利屋数据
|
||||
async loadEndedData() {
|
||||
if (this.loading) return;
|
||||
if (this.loading || this.endedLoaded) return;
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
|
|
@ -156,6 +166,7 @@ export default {
|
|||
|
||||
if (res?.data?.data) {
|
||||
this.endedData = this.formatBenefitsData(res.data.data);
|
||||
this.endedLoaded = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载已结束福利屋数据失败:', error);
|
||||
|
|
@ -193,19 +204,23 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
// 切换标签
|
||||
// 处理滑动切换
|
||||
handleSwiperChange(e) {
|
||||
const index = e.detail.current;
|
||||
this.tabChange(index + 1);
|
||||
},
|
||||
|
||||
// 修改标签切换方法
|
||||
tabChange(i) {
|
||||
if (this.tabCur === i) return; // 避免重复加载
|
||||
if (this.tabCur === i) return;
|
||||
this.tabCur = i;
|
||||
|
||||
if (i === 1) {
|
||||
// 切换到进行中,加载进行中数据
|
||||
if (this.ongoingData.length === 0) {
|
||||
if (!this.ongoingLoaded) {
|
||||
this.loadOngoingData();
|
||||
}
|
||||
} else {
|
||||
// 切换到已结束,加载已结束数据
|
||||
if (this.endedData.length === 0) {
|
||||
if (!this.endedLoaded) {
|
||||
this.loadEndedData();
|
||||
}
|
||||
}
|
||||
|
|
@ -225,74 +240,94 @@ export default {
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.tab-item1 {
|
||||
.tab-item1, .tab-item2, .tab-item3 {
|
||||
width: 160rpx;
|
||||
height: 92rpx;
|
||||
font-weight: 400;
|
||||
margin-right: 30rpx;
|
||||
background: url($imgurl + "index/uncheckTab1.png") no-repeat 0 0 / 100% 100%;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
animation: ripple 0.6s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
>text {
|
||||
font-weight: 600;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item1 {
|
||||
background: url($imgurl + "index/uncheckTab1.png") no-repeat 0 0 / 100% 100%;
|
||||
|
||||
&:active {
|
||||
background: url($imgurl + "index/checkTab1.png") no-repeat 0 0 / 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item2 {
|
||||
width: 160rpx;
|
||||
height: 92rpx;
|
||||
font-weight: 400;
|
||||
margin-right: 30rpx;
|
||||
|
||||
&.act {
|
||||
background: url($imgurl + "index/checkTab2.png") no-repeat 0 0 / 100% 100%;
|
||||
|
||||
>text {
|
||||
font-weight: 600;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
}
|
||||
animation: tabActivate 0.3s ease-out;
|
||||
}
|
||||
|
||||
&.unact {
|
||||
background: url($imgurl + "index/uncheckTab2.png") no-repeat 0 0 / 100% 100%;
|
||||
|
||||
>text {
|
||||
font-weight: 600;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item3 {
|
||||
width: 160rpx;
|
||||
height: 92rpx;
|
||||
font-weight: 400;
|
||||
|
||||
&.act {
|
||||
background: url($imgurl + "index/checkTab3.png") no-repeat 0 0 / 100% 100%;
|
||||
|
||||
>text {
|
||||
font-weight: 600;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
}
|
||||
animation: tabActivate 0.3s ease-out;
|
||||
}
|
||||
|
||||
&.unact {
|
||||
background: url($imgurl + "index/uncheckTab3.png") no-repeat 0 0 / 100% 100%;
|
||||
|
||||
>text {
|
||||
font-weight: 600;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(2);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tabActivate {
|
||||
0% {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.benefits-container {
|
||||
width: 672rpx;
|
||||
height: 760rpx;
|
||||
|
|
@ -300,6 +335,11 @@ export default {
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.benefits-swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.benefits-scroll {
|
||||
height: 760rpx;
|
||||
}
|
||||
|
|
@ -310,6 +350,24 @@ export default {
|
|||
background-color: #F8F8F8;
|
||||
margin-bottom: 36rpx;
|
||||
border-radius: 16rpx;
|
||||
animation: slideIn 0.5s ease-out;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(30rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.benefit-title {
|
||||
|
|
@ -336,9 +394,21 @@ export default {
|
|||
position: absolute;
|
||||
top: 20rpx;
|
||||
right: 24rpx;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:active {
|
||||
transform: scale(0.9);
|
||||
background-color: darken(#D8FD24, 5%);
|
||||
}
|
||||
|
||||
&.ended {
|
||||
background-color: #333333;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.9);
|
||||
background-color: lighten(#333333, 5%);
|
||||
}
|
||||
|
||||
text {
|
||||
color: #D8FD24;
|
||||
|
|
@ -358,6 +428,7 @@ export default {
|
|||
position: absolute;
|
||||
left: 24rpx;
|
||||
top: 112rpx;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.goods-item {
|
||||
|
|
@ -365,6 +436,23 @@ export default {
|
|||
height: 80rpx;
|
||||
display: inline-block;
|
||||
margin-right: 36rpx;
|
||||
transition: transform 0.3s ease;
|
||||
animation: scaleIn 0.5s ease-out;
|
||||
|
||||
&:active {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
|
|
@ -402,6 +490,18 @@ export default {
|
|||
position: absolute;
|
||||
left: 24rpx;
|
||||
bottom: 16rpx;
|
||||
animation: slideInLeft 0.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.fire-icon {
|
||||
|
|
@ -421,6 +521,18 @@ export default {
|
|||
position: absolute;
|
||||
right: 24rpx;
|
||||
bottom: 18rpx;
|
||||
animation: slideInRight 0.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
|
|
@ -444,6 +556,13 @@ export default {
|
|||
height: 72rpx;
|
||||
background-color: #D8FD24;
|
||||
border-radius: 16rpx;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
background-color: darken(#D8FD24, 5%);
|
||||
}
|
||||
|
||||
text {
|
||||
font-weight: 600;
|
||||
|
|
@ -451,4 +570,15 @@ export default {
|
|||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container title="福利屋详情" :showBack="true">
|
||||
<view class="relative"
|
||||
<view class="relative header-info" :class="{ 'show': headerShow }"
|
||||
style="width: 686rpx; height: 152rpx; background-color: #FFFFFF; border-radius: 16rpx; margin: 0 auto;">
|
||||
|
||||
<image style="width: 108rpx; height: 108rpx;position: absolute; left: 24rpx; top: 22rpx;"
|
||||
|
|
@ -20,19 +20,18 @@
|
|||
<text style="font-size: 16rpx; color: #999999; margin-left: 8rpx;">{{ bonusData.popularity }}</text>
|
||||
</view>
|
||||
<button open-type="share" class="button"
|
||||
style="position: absolute; top: 50rpx; right: 24rpx;width: 50rpx; height: 50rpx;">
|
||||
|
||||
style="position: absolute; top: 50rpx; right: 24rpx; width: 50rpx; height: 50rpx; border: none; padding: 0; margin: 0; line-height: 1; ">
|
||||
</button>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<view class=""
|
||||
<view class="content-area" :class="{ 'show': contentShow }"
|
||||
style="width: 686rpx; height: 1010rpx; background-color: #FFFFFF; border-radius: 16rpx; margin: 24rpx auto 0;">
|
||||
|
||||
<view class="tab">
|
||||
<view class="tab-item center relative" v-for="(item, i) in tabList" :key="i"
|
||||
:class="currentTab == i ? 'act' : 'unact'" @click="handleTabChange(i)">
|
||||
:class="[currentTab == i ? 'act' : 'unact', { 'show': tabsShow[i] }]" @click="handleTabChange(i)">
|
||||
<text>{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -75,7 +74,9 @@
|
|||
|
||||
|
||||
<scroll-view v-if="currentTab == 1" scroll-y="true" style="width: 100%; height: 890rpx; padding: 24rpx;">
|
||||
<view class="row align-center" v-for="(item, index) in participantList" :key="index"
|
||||
<view class="row align-center participant-row"
|
||||
:class="{ 'show': participantRowsShow[index] }"
|
||||
v-for="(item, index) in participantList" :key="index"
|
||||
style="height: 76rpx; margin-bottom: 24rpx;">
|
||||
|
||||
<view class="center" style="width: 30rpx;">
|
||||
|
|
@ -95,7 +96,9 @@
|
|||
</view>
|
||||
</scroll-view>
|
||||
<scroll-view v-if="currentTab == 2" scroll-y="true" style="width: 100%; height: 890rpx; padding: 24rpx;">
|
||||
<view class="row align-center relative" v-for="(item, index) in awardRecordList" :key="index"
|
||||
<view class="row align-center award-row"
|
||||
:class="{ 'show': awardRowsShow[index] }"
|
||||
v-for="(item, index) in awardRecordList" :key="index"
|
||||
style="height: 76rpx; margin-bottom: 24rpx;">
|
||||
|
||||
<view class="center" style="width: 30rpx;">
|
||||
|
|
@ -119,8 +122,9 @@
|
|||
<view class="column align-center"
|
||||
style="width: 100%; height: 198rpx; background-color: #fff; margin-top: 8rpx;">
|
||||
|
||||
<view class="participation-button"
|
||||
@click="handleButtonClick">
|
||||
<view class="participation-button"
|
||||
:class="{ 'show': buttonShow, 'pulse': buttonPulse }"
|
||||
@click="handleButtonPulse">
|
||||
<text class="button-text">{{ buttonText }}</text>
|
||||
</view>
|
||||
<text style="color: #8A8A8A; font-size: 20rpx; font-weight: 400; margin-top: 12rpx;">{{ remainingTime
|
||||
|
|
@ -135,28 +139,25 @@
|
|||
|
||||
|
||||
<!-- 条件不足弹窗 -->
|
||||
<uni-popup ref="condition" type="center">
|
||||
<uni-popup ref="condition" type="center" :animation="true" :mask-click="true">
|
||||
|
||||
<view style="width: 636rpx; height: 422rpx; background-color: #FFFFFF; border-radius: 16rpx;">
|
||||
<view
|
||||
style="width: 100%;height: 80rpx;border-radius:24rpx;display: flex;justify-content: center;align-items: center;font-size: 35rpx;">
|
||||
<view class="popup-container">
|
||||
<view class="popup-title">
|
||||
参与提示
|
||||
</view>
|
||||
<view style="padding: 0rpx 24rpx;">
|
||||
<view class="popup-content">
|
||||
提示:需在指定时间{{ bonusData.start_time }}-{{ bonusData.end_time }}消耗达到{{ bonusData.choujiang_xianzhi
|
||||
}}钻石,即可加入房间,还需{{ remainingDiamond }}钻石.
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="flex row" style="width: 636rpx; justify-content: space-around; margin-top: 32rpx;">
|
||||
<view class="center" @click="$refs.condition.close()"
|
||||
style="width: 200rpx; height: 68rpx; background-color: #FFFFFF; border-radius: 16rpx;">
|
||||
<text style="font-size: 24rpx; color: #333333; font-weight: 600;">取消</text>
|
||||
<view class="popup-buttons">
|
||||
<view class="popup-button cancel-button" @click="$refs.condition.close()">
|
||||
<text>取消</text>
|
||||
</view>
|
||||
|
||||
<view class="center" @click="toHome()"
|
||||
style="width: 200rpx; height: 68rpx; background-color: #CDEF27;border-radius: 16rpx;">
|
||||
<text style="font-size: 24rpx; color: #333333; font-weight: 600;">去抽赏</text>
|
||||
<view class="popup-button confirm-button" @click="toHome()">
|
||||
<text>去抽赏</text>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
|
@ -222,7 +223,18 @@ export default {
|
|||
useMoney2: false,
|
||||
isAgree: true,
|
||||
loading: false,
|
||||
user_count: 0 //用户已经购买的次数
|
||||
user_count: 0, //用户已经购买的次数
|
||||
|
||||
// 动画状态控制变量
|
||||
headerShow: false,
|
||||
contentShow: false,
|
||||
buttonShow: false,
|
||||
tabsShow: [false, false, false],
|
||||
participantRowsShow: [],
|
||||
awardRowsShow: [],
|
||||
|
||||
// 按钮脉冲动画
|
||||
buttonPulse: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -241,6 +253,11 @@ export default {
|
|||
console.log(options)
|
||||
this.goods_id = options.goods_id
|
||||
await this.load(options.goods_id)
|
||||
|
||||
// 添加页面加载动画
|
||||
setTimeout(() => {
|
||||
this.applyPageTransitions();
|
||||
}, 100);
|
||||
},
|
||||
methods: {
|
||||
handleSwiperChange(e) {
|
||||
|
|
@ -493,6 +510,12 @@ export default {
|
|||
} catch (error) {
|
||||
console.error("加载参与人数列表失败", error);
|
||||
}
|
||||
|
||||
if (this.currentTab === 1) {
|
||||
setTimeout(() => {
|
||||
this.animateListItems('participant-row');
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
async loadAwardRecords(goods_id) {
|
||||
|
|
@ -518,12 +541,51 @@ export default {
|
|||
} catch (error) {
|
||||
console.error("加载赏品记录失败", error);
|
||||
}
|
||||
|
||||
if (this.currentTab === 2) {
|
||||
setTimeout(() => {
|
||||
this.animateListItems('award-row');
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
handleTabChange(index) {
|
||||
this.currentTab = index
|
||||
this.currentTab = index;
|
||||
// 添加延迟加载动画
|
||||
if (index === 1 && this.participantList.length > 0) {
|
||||
this.animateListItems('participant-row');
|
||||
} else if (index === 2 && this.awardRecordList.length > 0) {
|
||||
this.animateListItems('award-row');
|
||||
}
|
||||
},
|
||||
|
||||
// 添加列表项动画方法
|
||||
animateListItems(className) {
|
||||
// 根据列表类型初始化动画状态数组
|
||||
if (className === 'participant-row') {
|
||||
this.participantRowsShow = Array(this.participantList.length).fill(false);
|
||||
|
||||
// 逐个显示列表项
|
||||
for (let i = 0; i < this.participantList.length; i++) {
|
||||
((index) => {
|
||||
setTimeout(() => {
|
||||
this.$set(this.participantRowsShow, index, true);
|
||||
}, index * 50);
|
||||
})(i);
|
||||
}
|
||||
} else if (className === 'award-row') {
|
||||
this.awardRowsShow = Array(this.awardRecordList.length).fill(false);
|
||||
|
||||
// 逐个显示列表项
|
||||
for (let i = 0; i < this.awardRecordList.length; i++) {
|
||||
((index) => {
|
||||
setTimeout(() => {
|
||||
this.$set(this.awardRowsShow, index, true);
|
||||
}, index * 50);
|
||||
})(i);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateButtonState() {
|
||||
const currentDate = new Date(this.currentServerTime);
|
||||
|
|
@ -546,6 +608,17 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
handleButtonPulse() {
|
||||
// 添加动画类
|
||||
this.buttonPulse = true;
|
||||
setTimeout(() => {
|
||||
this.buttonPulse = false;
|
||||
}, 400); // 动画时长结束后移除类
|
||||
|
||||
// 调用原始点击处理程序
|
||||
this.handleButtonClick();
|
||||
},
|
||||
|
||||
handleButtonClick() {
|
||||
if (this.buttonText === "未开始") {
|
||||
uni.showToast({
|
||||
|
|
@ -623,8 +696,23 @@ export default {
|
|||
uni.reLaunch({
|
||||
url: '/pages/shouye/index'
|
||||
});
|
||||
},
|
||||
|
||||
applyPageTransitions() {
|
||||
// 头部信息
|
||||
this.headerShow = true;
|
||||
|
||||
// 标签
|
||||
setTimeout(() => { this.tabsShow[0] = true; }, 100);
|
||||
setTimeout(() => { this.tabsShow[1] = true; }, 200);
|
||||
setTimeout(() => { this.tabsShow[2] = true; }, 300);
|
||||
|
||||
// 内容区
|
||||
setTimeout(() => { this.contentShow = true; }, 200);
|
||||
|
||||
// 按钮
|
||||
setTimeout(() => { this.buttonShow = true; }, 300);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -635,6 +723,8 @@ export default {
|
|||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10rpx 60rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
|
||||
.tab-item {
|
||||
|
|
@ -642,6 +732,11 @@ export default {
|
|||
height: 68rpx;
|
||||
position: relative;
|
||||
margin-right: 25rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
&.act {
|
||||
font-weight: 400;
|
||||
|
|
@ -657,6 +752,8 @@ export default {
|
|||
width: 48rpx;
|
||||
height: 4rpx;
|
||||
background: #333333;
|
||||
transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
||||
animation: fadeInWidth 0.3s forwards;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -664,10 +761,31 @@ export default {
|
|||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #CCCCCC;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0;
|
||||
height: 4rpx;
|
||||
background: #333333;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInWidth {
|
||||
from {
|
||||
width: 0;
|
||||
}
|
||||
to {
|
||||
width: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 124rpx);
|
||||
|
|
@ -682,11 +800,69 @@ export default {
|
|||
.grid-item {
|
||||
width: 142rpx;
|
||||
height: 150rpx;
|
||||
transition: all 0.3s ease;
|
||||
padding: 8rpx;
|
||||
border-radius: 12rpx;
|
||||
position: relative;
|
||||
|
||||
&:active {
|
||||
transform: translateY(-6rpx) scale(1.05);
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
image {
|
||||
transition: all 0.25s ease;
|
||||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&:active image {
|
||||
box-shadow: 0 8rpx 12rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
text {
|
||||
transition: color 0.25s ease;
|
||||
}
|
||||
|
||||
&:active text {
|
||||
color: #666 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
background-image: url($imgurl + 'checkin/ic_share.png');
|
||||
background-size: 100% 100%;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
|
||||
&::after {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -5rpx;
|
||||
right: -5rpx;
|
||||
bottom: -5rpx;
|
||||
left: -5rpx;
|
||||
border-radius: 50%;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.9) rotate(15deg);
|
||||
}
|
||||
|
||||
&:active::before {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.swiper-container {
|
||||
|
|
@ -743,14 +919,98 @@ export default {
|
|||
border-radius: 16rpx;
|
||||
margin-top: 32rpx;
|
||||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
// 页面加载动画
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
transition: transform 0.5s ease, opacity 0.5s ease, background-color 0.2s ease, box-shadow 0.2s ease;
|
||||
transition-delay: 0.3s;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
&.pulse {
|
||||
animation: buttonPulse 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
}
|
||||
|
||||
.button-text {
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.popup-container {
|
||||
width: 636rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
transform: scale(0.9);
|
||||
opacity: 0;
|
||||
animation: popIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 35rpx;
|
||||
background-color: #f9f9f9;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 10%;
|
||||
width: 80%;
|
||||
height: 1px;
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
padding: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.popup-buttons {
|
||||
display: flex;
|
||||
width: 636rpx;
|
||||
justify-content: space-around;
|
||||
margin-top: 32rpx;
|
||||
animation: slideUp 0.4s ease-out forwards;
|
||||
animation-delay: 0.1s;
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
}
|
||||
|
||||
.popup-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 200rpx;
|
||||
height: 68rpx;
|
||||
border-radius: 16rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
transition: all 0.25s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
background-color: #c5e822;
|
||||
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&::after {
|
||||
|
|
@ -760,7 +1020,7 @@ export default {
|
|||
left: 50%;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
background-color: rgba(255, 255, 255, 0.4);
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 0;
|
||||
|
|
@ -768,14 +1028,140 @@ export default {
|
|||
}
|
||||
|
||||
&:active::after {
|
||||
transform: translate(-50%, -50%) scale(5);
|
||||
transform: translate(-50%, -50%) scale(3);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.button-text {
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
.cancel-button {
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #eee;
|
||||
|
||||
text {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
background-color: #CDEF27;
|
||||
box-shadow: 0 4rpx 8rpx rgba(205, 239, 39, 0.3);
|
||||
|
||||
text {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #b9d721;
|
||||
box-shadow: 0 2rpx 4rpx rgba(205, 239, 39, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes popIn {
|
||||
from {
|
||||
transform: scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.participant-row {
|
||||
opacity: 0;
|
||||
transform: translateX(-20rpx);
|
||||
transition: all 0.4s ease;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.award-row {
|
||||
opacity: 0;
|
||||
transform: translateX(-20rpx);
|
||||
transition: all 0.4s ease;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.header-info {
|
||||
opacity: 0;
|
||||
transform: translateY(-20rpx);
|
||||
transition: all 0.5s ease;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
opacity: 0;
|
||||
transform: translateY(10rpx);
|
||||
transition: all 0.4s ease;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.content-area {
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
transition: all 0.5s ease;
|
||||
transition-delay: 0.2s;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes buttonPulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
40% {
|
||||
transform: scale(0.92);
|
||||
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
80% {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 6rpx 10rpx rgba(0, 0, 0, 0.15);
|
||||
background-color: #e0ff3a;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<template>
|
||||
<page-container title="签到" :showBack="true" >
|
||||
<banner :type-id="7" :height="328"></banner>
|
||||
<view class=""
|
||||
<view class="checkin-container"
|
||||
style="width: 686rpx; height: 838rpx; background-color: #fff; margin: 40rpx auto 0; border-radius: 16rpx;">
|
||||
|
||||
<view class="center" style="padding-top: 24rpx;">
|
||||
|
|
@ -14,14 +14,13 @@
|
|||
<view style="width: 100%; overflow: hidden;">
|
||||
<scroll-view class="relative" scroll-x="true"
|
||||
style="white-space: nowrap; margin-left: 58rpx; margin-top: 24rpx;">
|
||||
<view class=""
|
||||
<view class="progress-line"
|
||||
style="width: 100%; height: 4rpx; background-color: #F3F3F3;position: absolute; top: 42rpx; left: 10rpx;">
|
||||
</view>
|
||||
<view class="relative total-checkin-item"
|
||||
style="width: 71.7rpx; height: 102rpx;display: inline-block; margin-right: 94rpx;"
|
||||
v-for="(item, index) in checkinData.TotalCheckinList" :key="index"
|
||||
@tap="showTips(item, $event, index)">
|
||||
|
||||
<image :src="item.icon"
|
||||
style="width: 71.7rpx; height: 72rpx; position: absolute;" mode=""></image>
|
||||
|
||||
|
|
@ -69,7 +68,7 @@
|
|||
<!-- 签到按钮 -->
|
||||
<view class="justify-center" style="width: 100%; height: 198rpx; background-color: #fff; margin-top: -10rpx;">
|
||||
<view class="align-center column">
|
||||
<view class="center" @click="sign"
|
||||
<view class="sign-btn center" @click="sign"
|
||||
style="width: 340rpx; height: 84rpx; background-color: #D8FD24; margin-top: 32rpx;">
|
||||
<text style="color: #333333; font-size: 32rpx; font-weight: 600;">{{ !is_sign ? "今日已签到" : "每日签到"
|
||||
}}</text>
|
||||
|
|
@ -179,7 +178,7 @@ export default {
|
|||
data.continuous_configs.forEach(item => {
|
||||
let t = {
|
||||
Days: item.day,
|
||||
isClaim: item.is_sign === 2 ? true : false,
|
||||
isClaim: item.is_sign === 1 ? true : false,
|
||||
tips: item.description || '',
|
||||
icon:item.icon
|
||||
};
|
||||
|
|
@ -224,6 +223,21 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.checkin-container {
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 140rpx);
|
||||
|
|
@ -234,11 +248,20 @@ export default {
|
|||
width: 140rpx;
|
||||
height: 172rpx;
|
||||
position: relative;
|
||||
animation: scaleIn 0.5s ease-out;
|
||||
animation-fill-mode: both;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
>image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.day {
|
||||
|
|
@ -248,6 +271,7 @@ export default {
|
|||
top: 12rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.reward {
|
||||
|
|
@ -258,6 +282,74 @@ export default {
|
|||
bottom: 10rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.total-checkin-item {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation: slideIn 0.5s ease-out;
|
||||
animation-fill-mode: both;
|
||||
|
||||
&:active {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.sign-btn {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
background-color: darken(#D8FD24, 5%);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
animation: ripple 0.6s ease-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ripple {
|
||||
0% {
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: translate(-50%, -50%) scale(2);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +357,7 @@ export default {
|
|||
position: fixed;
|
||||
z-index: 999;
|
||||
transform: translateX(-50%);
|
||||
animation: tooltipFadeIn 0.3s ease-out;
|
||||
|
||||
.tooltip-content {
|
||||
min-width: 80rpx;
|
||||
|
|
@ -286,4 +379,33 @@ export default {
|
|||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tooltipFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(10rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个签到项添加延迟动画
|
||||
.grid-item {
|
||||
@for $i from 1 through 30 {
|
||||
&:nth-child(#{$i}) {
|
||||
animation-delay: #{$i * 0.05}s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 为累计签到项添加延迟动画
|
||||
.total-checkin-item {
|
||||
@for $i from 1 through 10 {
|
||||
&:nth-child(#{$i}) {
|
||||
animation-delay: #{$i * 0.1}s;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<page-container title="福利">
|
||||
<banner :type-id="6" :height="326"></banner>
|
||||
<view class="grid-container" style="width: 100%; padding: 0 32rpx; margin-top: 40rpx;">
|
||||
<view class="grid-item" v-for="(item) in list" :key="item.id" @click="toPage(item)" style="height: 184rpx;">
|
||||
<view class="grid-item" v-for="(item, index) in list" :key="item.id" @click="toPage(item)" style="height: 184rpx;">
|
||||
<image v-if="item.image" :src="item.image" mode="aspectFill" class="grid-item-bg"></image>
|
||||
<text v-if="!item.image">{{ item.name }}</text>
|
||||
</view>
|
||||
|
|
@ -51,6 +51,8 @@
|
|||
//跳转页面
|
||||
toPage(item) {
|
||||
if (item.url) {
|
||||
console.log(item);
|
||||
uni.setStorageSync('fuliwu_title', item.name)
|
||||
this.$c.to({
|
||||
url: item.url
|
||||
});
|
||||
|
|
@ -79,17 +81,67 @@
|
|||
/* 三列,每列宽度相等 */
|
||||
gap: 40rpx 42rpx;
|
||||
/* 网格之间的间隔 */
|
||||
animation: fadeIn 0.5s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
position: relative;
|
||||
background-color: #D8D8D8;
|
||||
|
||||
text-align: center;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
animation: scaleIn 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation-fill-mode: both;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%) scale(0);
|
||||
opacity: 0;
|
||||
transition: transform 0.6s ease-out, opacity 0.6s ease-out;
|
||||
}
|
||||
|
||||
&:active::after {
|
||||
transform: translate(-50%, -50%) scale(2);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.grid-item-bg {
|
||||
|
|
@ -99,11 +151,23 @@
|
|||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.grid-item text {
|
||||
z-index: 2;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
transition: all 0.3s ease;
|
||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
// 为每个网格项添加延迟动画
|
||||
.grid-item {
|
||||
@for $i from 1 through 10 {
|
||||
&:nth-child(#{$i}) {
|
||||
animation-delay: #{$i * 0.1}s;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
46
pages/shouye/danye.vue
Normal file
46
pages/shouye/danye.vue
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<page-container :title="title" :showBack="true">
|
||||
<view v-html="content">
|
||||
|
||||
</view>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageContainer from '@/components/page-container/page-container.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PageContainer
|
||||
},
|
||||
onLoad(options) {
|
||||
console.log(options)
|
||||
if (options.advert) {
|
||||
this.load(options.advert)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
let title = '';
|
||||
// uni.getStorageSync('title')
|
||||
title = uni.getStorageSync('fuliwu_title')
|
||||
return {
|
||||
title,
|
||||
content: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async load(advert) {
|
||||
const { status, data, msg } = await this.$request.get('getDanye', { type: advert });
|
||||
if (status == 1) {
|
||||
// this.list = data;
|
||||
if (this.title == '') {
|
||||
this.title = data.title;
|
||||
}
|
||||
this.content = data.content
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user