1922 lines
55 KiB
Vue
1922 lines
55 KiB
Vue
<template>
|
||
<div class="task" id="taskBoxID">
|
||
<lazyImg :src="taskBgImg" class="task_bg" />
|
||
<Header title="每日签到" headerBg="transparent" class="isHeader" />
|
||
|
||
<div class="task_box overflow-y-auto" ref="taskBoxRef">
|
||
<van-pull-refresh v-model="loading" @refresh="onRefresh">
|
||
<div class="content_topBox">
|
||
<div class="top_content">
|
||
<div class="userinfo">
|
||
<div class="avatar" :class="{ 'avatar--vip': userStore.isVip }">
|
||
<lazyImg :src="userStore.userInfo.portrait" round :key="userStore.userInfo.portrait" />
|
||
</div>
|
||
<div class="name_box">
|
||
<div class="name">
|
||
<div>{{ userStore.userInfo.name }}</div>
|
||
<VipImg :isVip="userStore.userInfo.vipLevel" />
|
||
</div>
|
||
<div class="tip" v-if="!userStore.userInfo.isVip">剩余观看次数:{{ userStore.userInfo.watchCount }}</div>
|
||
<div class="tip" v-else>剩余AI次数:{{ state.freeCount }}</div>
|
||
</div>
|
||
</div>
|
||
<div class="vip_btn" @click="router.push('/member')" v-if="userStore.userInfo.isVip">
|
||
<div class="info">
|
||
<div class="label">VIP限时特惠 畅享全场</div>
|
||
<div class="time">
|
||
{{ userStore.userInfo.vipName }}
|
||
<span>{{ dateFormatYyyyMmDd(userStore.userInfo.vipExpireDate) }}</span>
|
||
</div>
|
||
</div>
|
||
<div v-if="userStore.userInfo.isUpgrade" class="openVip" @click="router.push('/member')">补差价升级<img src="@/assets/images/png/mine/right-icon.png" alt="" /></div>
|
||
<div v-else class="openVip" @click="router.push('/member')">会员中心<img src="@/assets/images/png/mine/right-icon.png" alt="" /></div>
|
||
</div>
|
||
<div class="btn" @click="router.push('/member')" v-else>开通VIP不限次数观看</div>
|
||
</div>
|
||
<div class="tip_text">提示:若状态未更新 请下拉刷新哦</div>
|
||
</div>
|
||
<Loading v-if="state.signLoading" />
|
||
<div class="signContent" :style="signContentStyle" v-else>
|
||
<div class="sign-header">
|
||
<p class="sign-title">每日签到领福利</p>
|
||
<span class="sign-reward-chip" v-if="allMsgObj?.checkin?.doubleReward">
|
||
{{ remainRewardDays > 0 ? `还差${remainRewardDays}天领取翻倍福利` : '已解锁7天翻倍奖励' }}
|
||
</span>
|
||
</div>
|
||
<div class="sign-progress" v-if="checkedDays < 8">
|
||
<div class="progress-track">
|
||
<div class="progress-inner-mask">
|
||
<div class="progress-inner" :style="{ width: `${progressPercent}%` }"></div>
|
||
</div>
|
||
<img
|
||
class="progress-icon"
|
||
:class="{ shake: seventhDayHighlight }"
|
||
src="@/assets/images/png/mine/progress-icon.png"
|
||
alt=""
|
||
:style="{ left: `${progressIconLeft}%` }"
|
||
/>
|
||
</div>
|
||
<span class="progress-percent">{{ progressPercent }}%</span>
|
||
</div>
|
||
<p class="sign-subtitle">
|
||
已连续签到
|
||
<span class="highlight">{{ checkedDays }}</span>
|
||
天 神秘大礼在等你
|
||
</p>
|
||
|
||
<div class="sign-sync-wrap">
|
||
<div class="free-claim-default-bg"></div>
|
||
<div class="vip-claim-default-bg"></div>
|
||
<div class="sign-sync-scroll">
|
||
<div class="sign-sync-content">
|
||
<div class="sign-days-row">
|
||
<div
|
||
v-for="col in signColumns"
|
||
:key="`sign-day-${col.id}`"
|
||
class="day-chip"
|
||
:class="{
|
||
active: checkedDays === col.dayIndex,
|
||
done: checkedDays > col.dayIndex,
|
||
}"
|
||
>
|
||
{{ getDayChipText(col) }}
|
||
</div>
|
||
</div>
|
||
<div class="sign-cards-row sign-cards-row-free">
|
||
<div v-for="col in signColumns" :key="`free-prize-${col.id}`" class="prize-card">
|
||
<div class="item-mask"></div>
|
||
<lazyImg
|
||
v-if="col.freePrize?.image"
|
||
:src="col.freePrize.image"
|
||
class="prize-img"
|
||
:class="{
|
||
'signed-gray': col.freePrize?.isCheckedIn,
|
||
'shake-prize': col.day === currentCheckinDay && seventhPrizeShaking,
|
||
}"
|
||
/>
|
||
<template v-else>
|
||
<img v-if="!col.freePrize?.isCheckedIn" class="prize-img" src="@/assets/images/png/mine/check_in_coin.png" alt="" />
|
||
<img v-else class="prize-img" src="@/assets/images/png/mine/checked_in_coin.png" alt="" />
|
||
</template>
|
||
<span class="prize-name" :class="{ 'signed-white': col.freePrize?.isCheckedIn }">
|
||
{{ col.freePrize?.prizeName || formatPrizeText(col.freePrize) }}
|
||
</span>
|
||
<span class="prize-score" v-if="hasVipTypeGte3">+2</span>
|
||
</div>
|
||
</div>
|
||
<div class="sign-cards-row sign-cards-row-vip" @click="handleVipRowClick">
|
||
<!-- <div class="vip-slash" v-if="!hasVipTypeGte3"></div> -->
|
||
<div
|
||
v-for="(col, index) in bigPrizeList"
|
||
:key="`vip-prize-${col.id || index}`"
|
||
class="prize-card"
|
||
@click.stop="handleClaimVipPrize(col)"
|
||
>
|
||
<div class="item-mask"></div>
|
||
<div class="vip-claim-badge" v-if="col.canClaim">补领</div>
|
||
<div class="prize-img-box">
|
||
<lazyImg
|
||
v-if="col?.image"
|
||
:src="col.image"
|
||
class="prize-img"
|
||
:class="{ 'signed-gray': col.isReceive || col.isExpired }"
|
||
/>
|
||
<template v-else>
|
||
<img v-if="col?.isReceive || col.isExpired" class="prize-img" src="@/assets/images/png/mine/checked_in_coin.png" alt="" />
|
||
<img v-else class="prize-img" src="@/assets/images/png/mine/check_in_coin.png" alt="" />
|
||
</template>
|
||
<img v-if="col.isExpired" class="expired-icon" src="@/assets/images/png/mine/expired.png" alt="" />
|
||
</div>
|
||
<span class="prize-name" :class="{ 'signed-white': col.isReceive }">
|
||
{{ col.prizeName || formatPrizeText(col) }}
|
||
</span>
|
||
<img
|
||
v-if="!hasVipTypeGte3 && !col.isReceive"
|
||
class="vip-lock-icon"
|
||
src="@/assets/images/png/mine/lock.png"
|
||
alt=""
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div class="free-claim-bg">
|
||
<img src="@/assets/images/png/mine/qiandao-free.png" alt="" />
|
||
</div>
|
||
<div class="vip-claim-bg">
|
||
<img src="@/assets/images/png/mine/qiandao-vip.png" alt="" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="touchShowMore">
|
||
<div v-if="!allMsgObj?.checkin?.todayChecked" class="signIn" @click="handleSignTrigger">
|
||
会员打卡领双倍奖励
|
||
<img class="signInIcon" src="@/assets/images/png/signInIcon.png" alt="" />
|
||
</div>
|
||
<div v-else class="signInEnd" @click="handleSignTrigger">今日已签到</div>
|
||
<div
|
||
v-if="allMsgObj?.checkin?.todayChecked && !hasVipTypeGte3"
|
||
class="unlock-vip-tip"
|
||
@click="router.push('/member')"
|
||
>
|
||
<!-- 立即解锁可领
|
||
<span class="unlock-vip-highlight">“免费+豪奖”双重奖励</span>
|
||
<span class="unlock-vip-btn">开通会员</span> -->
|
||
<img src="@/assets/images/png/mine/vip-tips.png" alt="" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- <div class="checkin_rewards" v-if="state.signExtraPrizesList.length">
|
||
<div class="checkin_title">累计打卡白嫖会员</div>
|
||
<div class="checkin_subtitle">100%得VIP会员等你拿</div>
|
||
<div class="reward_cards">
|
||
<div class="reward_card" v-for="(item, index) in state.signExtraPrizesList" :key="index">
|
||
<div class="duration_badge" v-if="item.desc">{{ item.desc }}</div>
|
||
<div class="reward_line" />
|
||
<div class="reward_icon">
|
||
<lazyImg :src="item.image" v-if="item.image" />
|
||
</div>
|
||
<div class="reward_text">{{ item.name }}</div>
|
||
<div class="claim_btn" :class="{ active: item.extraPrizeStatus }" v-if="item.extraPrizeStatus">
|
||
已领取
|
||
</div>
|
||
<div class="claim_btn" v-else>剩余{{ item.finishCondition }}天</div>
|
||
</div>
|
||
</div>
|
||
</div> -->
|
||
</van-pull-refresh>
|
||
<div class="tabs_ltype">
|
||
<div class="record" @click="router.push('/freeRecord')">兑换记录</div>
|
||
<van-tabs
|
||
v-model:active="state.tabActive"
|
||
class="oepnX task_tabs"
|
||
title-active-color="#F68804"
|
||
title-inactive-color="#999"
|
||
animated
|
||
:scrollspy="false"
|
||
swipeable
|
||
shrink
|
||
:lazy-render="true"
|
||
>
|
||
<van-tab title="福利任务">
|
||
<div class="taskBox">
|
||
<div class="score">
|
||
我的积分
|
||
<span>{{ userStore.walletInfo.integral || 0 }}</span>
|
||
</div>
|
||
<div class="taskList" v-if="!state.loading">
|
||
<div class="taskItem flex-center-between" v-for="item in state.dailyTask" :key="item.id">
|
||
<div class="leftBox flex-vcenter">
|
||
<LazyImg :src="item.img" class="taskIcon" :key="item.img" />
|
||
<div class="taskInfo">
|
||
<div class="taskName">
|
||
{{ item.title }}
|
||
<span v-if="item.prize">+{{ item?.prize?.price }}积分</span>
|
||
<span class="countdownTag" v-if="item.countdownType == 1">限时</span>
|
||
</div>
|
||
<div class="taskDesc ellipsis1">{{ getTaskDesc(item) }}</div>
|
||
</div>
|
||
</div>
|
||
<template v-if="item.countdownType == 1">
|
||
<div class="btn receive" v-if="getTaskHongbaoPhase(item) === 'pending'" @click="todo(item, 3)">
|
||
待开启
|
||
</div>
|
||
<div class="btn" v-else-if="getTaskHongbaoPhase(item) === 'active'" @click="todo(item, 3)">
|
||
领红包
|
||
</div>
|
||
</template>
|
||
<template v-else>
|
||
<div class="btn" v-if="item.status == 0" @click="todo(item, 1)">去完成</div>
|
||
<div class="btn receive" v-else-if="item?.status == 1" @click="receive(item, 1)">待领取</div>
|
||
<div class="btn received" v-else-if="item?.status == 2">已领取</div>
|
||
</template>
|
||
</div>
|
||
<div class="taskItem flex-center-between" v-for="item in state.growTasks" :key="item.id">
|
||
<div class="leftBox flex-vcenter">
|
||
<LazyImg :src="item.img" class="taskIcon" :key="item.img" />
|
||
<div class="taskInfo">
|
||
<div class="taskName">
|
||
{{ item.title }}
|
||
<span v-if="item.prize">+{{ item?.prize?.price }}积分</span>
|
||
<span class="countdownTag" v-if="item.countdownType == 1">限时</span>
|
||
</div>
|
||
<div class="taskDesc ellipsis1">{{ getTaskDesc(item) }}</div>
|
||
</div>
|
||
</div>
|
||
<template v-if="item.countdownType == 1">
|
||
<div class="btn receive" v-if="getTaskHongbaoPhase(item) === 'pending'" @click="todo(item, 3)">
|
||
待开启
|
||
</div>
|
||
<div class="btn" v-else-if="getTaskHongbaoPhase(item) === 'active'" @click="todo(item, 3)">
|
||
领红包
|
||
</div>
|
||
</template>
|
||
<template v-else>
|
||
<div class="btn" v-if="item.status == 0" @click="todo(item, 3)">去完成</div>
|
||
<div class="btn receive" v-else-if="item.status == 1" @click="receive(item, 3)">待领取</div>
|
||
<div class="btn received" v-else-if="item.status == 2">已领取</div>
|
||
</template>
|
||
</div>
|
||
<div class="taskItem flex-center-between" v-for="item in state.onceTask" :key="item.id">
|
||
<div class="leftBox flex-vcenter">
|
||
<LazyImg :src="item.img" class="taskIcon" :key="item.img" />
|
||
<div class="taskInfo">
|
||
<div class="taskName">
|
||
{{ item.title }}
|
||
<span v-if="item.prize">+{{ item?.prize?.price }}积分</span>
|
||
<span class="countdownTag" v-if="item.countdownType == 1">限时</span>
|
||
</div>
|
||
<div class="taskDesc ellipsis1">{{ getTaskDesc(item) }}</div>
|
||
</div>
|
||
</div>
|
||
<template v-if="item.countdownType == 1">
|
||
<div class="btn receive" v-if="getTaskHongbaoPhase(item) === 'pending'" @click="todo(item, 3)">
|
||
待开启
|
||
</div>
|
||
<div class="btn" v-else-if="getTaskHongbaoPhase(item) === 'active'" @click="todo(item, 3)">
|
||
领红包
|
||
</div>
|
||
</template>
|
||
<template v-else>
|
||
<div class="btn" v-if="item.status == 0" @click="todo(item, 3)">去完成</div>
|
||
<div class="btn receive" v-else-if="item.status == 1" @click="receive(item, 2)">待领取</div>
|
||
<div class="btn received" v-else-if="item.status == 2">已领取</div>
|
||
</template>
|
||
</div>
|
||
<Empty
|
||
v-if="state.growTasks.length == 0 && state.onceTask.length == 0 && state.dailyTask.length == 0"
|
||
/>
|
||
</div>
|
||
<Loading v-else />
|
||
</div>
|
||
</van-tab>
|
||
<van-tab title="积分兑换">
|
||
<div v-if="!state.integralLoading">
|
||
<div class="score_wrap">
|
||
<div class="score">
|
||
我的积分
|
||
<span>{{ userStore.walletInfo.integral || 0 }}</span>
|
||
</div>
|
||
<div class="list_jf">
|
||
<div class="itemlist" v-for="item in state.integralList" :key="item.id">
|
||
<div class="top">
|
||
<LazyImg :src="item.img" class="itemlistimg" :key="item.img" />
|
||
</div>
|
||
<div class="bot flex-center-between">
|
||
花费{{ item.price }}积分
|
||
<div class="btn flex-center-center" @click="exchangeItem(item)">立即兑换</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<Empty v-if="state.integralList.length == 0" />
|
||
</div>
|
||
</div>
|
||
<Loading v-else />
|
||
</van-tab>
|
||
</van-tabs>
|
||
<!-- <div class="tabs_line" />-->
|
||
<!-- <div class="tabs_record" @click="$router.push('/freeRecord')">兑换记录</div> -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- <div class="submit-box">-->
|
||
<!-- <div class="submit flex-center-center" @click="$router.push('/memberExchange')">前往积分兑换</div>-->
|
||
<!-- </div>-->
|
||
<WorkSignPopup
|
||
v-model:show="showSignPopup"
|
||
:checked-days="checkedDays"
|
||
:remain-days="remainRewardDays"
|
||
:progress-percent="progressPercent"
|
||
:popup-target-day="DOUBLE_REWARD_TARGET_DAY"
|
||
:prize-columns="popupPrizeColumns"
|
||
:redeem-items="allMsgObj?.config?.integerExchangeList || []"
|
||
:has-vip-type-gte3="hasVipTypeGte3"
|
||
@redeem="handleRedeem"
|
||
@continue="showSignPopup = false"
|
||
/>
|
||
<SevenSignRewardPopup
|
||
v-model:show="showSevenRewardPopup"
|
||
:redeem-items="allMsgObj?.config?.integerExchangeList || []"
|
||
:reward-bg-video-url="prizeVideo || ''"
|
||
:reward-bg-h265-url="prizeH265Url || ''"
|
||
@redeem="closeSevenRewardPopup"
|
||
@continue="showSevenRewardPopup = false"
|
||
/>
|
||
<RedeemSuccessPopup
|
||
v-model:show="showRedeemSuccessPopup"
|
||
:redeem-item="currentRedeemItem"
|
||
@continue="handleContinueRedeem"
|
||
@share="handleShareFriend"
|
||
/>
|
||
</div>
|
||
</template>
|
||
<script lang="ts" setup>
|
||
import { reactive, ref, computed, nextTick, onMounted, onUnmounted } from 'vue';
|
||
import { useUserStore } from '@/stores/user';
|
||
import { dateFormatYyyyMmDd, jumpAdv } from '@/utils/index';
|
||
import HomeApi from '@/service/home';
|
||
import { showToast } from 'vant';
|
||
import { useRouter } from 'vue-router';
|
||
import useLoading from '@/hooks/loading';
|
||
import TabPageScroll from '@/utils/resetTabPageScrollTop';
|
||
import WorkSignPopup from './WorkSignPopup.vue';
|
||
import SevenSignRewardPopup from './SevenSignRewardPopup.vue';
|
||
import RedeemSuccessPopup from './RedeemSuccessPopup.vue';
|
||
import UserApi from '@/service/user';
|
||
|
||
/** 福利任务项(仅声明本次接入红包雨倒计时需要的字段,其它字段沿用原 any 兜底) */
|
||
interface BenefitTaskItem {
|
||
id: string;
|
||
title?: string;
|
||
desc?: string;
|
||
img?: string;
|
||
status?: number;
|
||
type?: number;
|
||
prize?: { price?: number };
|
||
/** 1 表示红包雨场次任务,需结合 startAt/endAt 走倒计时文案与按钮态 */
|
||
countdownType?: number;
|
||
/** 红包雨场次开始时间,countdownType=1 时有效 */
|
||
startAt?: string;
|
||
/** 红包雨场次结束时间 */
|
||
endAt?: string;
|
||
subTitle?: string;
|
||
}
|
||
|
||
const tabPageScroll = new TabPageScroll();
|
||
const DOUBLE_REWARD_TARGET_DAY = 7;
|
||
|
||
setTimeout(() => {
|
||
tabPageScroll.add(`#taskBoxID`);
|
||
}, 100);
|
||
|
||
const { openLoading, closeLoading } = useLoading();
|
||
const router = useRouter();
|
||
const userStore = useUserStore();
|
||
const prizeList = ref<any[]>([]);
|
||
const bigPrizeList = ref<any[]>([]);
|
||
const allMsgObj = ref<any>({});
|
||
const showSignPopup = ref(false);
|
||
const showSevenRewardPopup = ref(false);
|
||
const showRedeemSuccessPopup = ref(false);
|
||
const currentRedeemItem = ref<any>(null);
|
||
const prizeVideo = ref('');
|
||
const prizeH265Url = ref('');
|
||
const seventhPrizeShaking = ref(false);
|
||
const vipPrizeClaiming = ref(false);
|
||
const taskBoxRef = ref<HTMLElement | null>(null);
|
||
const state = reactive({
|
||
loading: true,
|
||
signLoading: true,
|
||
integralLoading: true,
|
||
dailyTask: <any>[],
|
||
growTasks: <any>[],
|
||
onceTask: <any>[],
|
||
integralList: <any>[],
|
||
tabActive: 0,
|
||
signExtraPrizesList: <any>[],
|
||
freeCount: 0,
|
||
});
|
||
const taskBgImg = computed(() => allMsgObj.value?.config?.backgroundImage || '');
|
||
const getList = async () => {
|
||
try {
|
||
let req: any = await HomeApi.getTaskList();
|
||
state.loading = false;
|
||
state.dailyTask = req.dailyTask || [];
|
||
state.growTasks = req.growthTasks || [];
|
||
state.onceTask = req.onceTask || [];
|
||
} catch (e) {
|
||
state.loading = false;
|
||
console.log(e);
|
||
}
|
||
};
|
||
const getIntegralList = async () => {
|
||
try {
|
||
let req: any = await HomeApi.getIntegral();
|
||
state.integralLoading = false;
|
||
state.integralList = req || [];
|
||
} catch (e) {
|
||
state.integralLoading = false;
|
||
console.log(e);
|
||
showToast('请求兑换列表失败,请稍后再试');
|
||
}
|
||
};
|
||
|
||
const todo = async (item: any, type: number) => {
|
||
jumpAdv(item);
|
||
if (type == 1 && item.countdownType !== 1) {
|
||
if (item.type == 0) {
|
||
// 广告点击,点击完即可领取
|
||
try {
|
||
let req = {
|
||
taskId: item.id,
|
||
type: 1,
|
||
};
|
||
await HomeApi.taskDo(req);
|
||
item.status = 1;
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
}
|
||
} else {
|
||
if (item.type == 2 && item.countdownType !== 1) {
|
||
// 广告点击,点击完即可领取
|
||
try {
|
||
let req = {
|
||
taskId: item.id,
|
||
type: 2,
|
||
};
|
||
await HomeApi.taskDo(req);
|
||
item.status = 1;
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
const receive = async (item: any, type: number) => {
|
||
try {
|
||
let req = {
|
||
taskId: item.id,
|
||
type: type,
|
||
};
|
||
await HomeApi.taskReceive(req);
|
||
item.status = 2;
|
||
userStore.updateWallet();
|
||
showToast('领取成功');
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
};
|
||
const hasVipTypeGte3 = computed(() => Number(userStore?.vipLevel || 0) >= 1 && userStore.isVip);
|
||
const freePrizeList = computed(() =>
|
||
(prizeList.value || []).filter((item: any) => !item?.checkinType || item?.checkinType === 1),
|
||
);
|
||
const memberPrizeList = computed(() => (prizeList.value || []).filter((item: any) => item?.checkinType === 2));
|
||
const memberDisplayList = computed(() => (memberPrizeList.value.length ? memberPrizeList.value : freePrizeList.value));
|
||
const signDayList = computed(() => (freePrizeList.value.length ? freePrizeList.value : prizeList.value) || []);
|
||
const signColumns = computed(() => {
|
||
const daySource = signDayList.value || [];
|
||
return daySource.map((dayItem: any, index: number) => {
|
||
const dayValue = dayItem?.checkinDays || index + 1;
|
||
const freePrize =
|
||
freePrizeList.value.find((item: any) => (item?.checkinDays || 0) === dayValue) || freePrizeList.value[index];
|
||
const vipPrize =
|
||
memberDisplayList.value.find((item: any) => (item?.checkinDays || 0) === dayValue) ||
|
||
memberDisplayList.value[index];
|
||
return {
|
||
id: dayItem?.id ?? `day-${index}`,
|
||
day: dayValue,
|
||
freePrize,
|
||
vipPrize,
|
||
dayIndex: index,
|
||
};
|
||
});
|
||
});
|
||
const checkedDays = computed(() => allMsgObj.value?.checkin?.continuouslyDays || 0);
|
||
const checkedProgressDays = computed(() => Math.min(DOUBLE_REWARD_TARGET_DAY, checkedDays.value));
|
||
const progressPercent = computed(() => {
|
||
return Math.min(100, Math.max(0, Math.round((checkedProgressDays.value / DOUBLE_REWARD_TARGET_DAY) * 100)));
|
||
});
|
||
const progressIconLeft = computed(() => Math.min(98, Math.max(2, progressPercent.value)));
|
||
const remainRewardDays = computed(() => Math.max(0, DOUBLE_REWARD_TARGET_DAY - checkedDays.value));
|
||
const popupPrizeColumns = computed(() => signColumns.value.slice(0, DOUBLE_REWARD_TARGET_DAY - 1));
|
||
const signBackgroundImage = computed(() => allMsgObj.value?.config?.backgroundImage || '');
|
||
const currentCheckinDay = computed(() => Math.max(1, checkedDays.value));
|
||
const seventhDayHighlight = computed(() => checkedDays.value >= DOUBLE_REWARD_TARGET_DAY - 1);
|
||
const signContentStyle = computed(() => {
|
||
if (!signBackgroundImage.value) return {};
|
||
return {
|
||
backgroundImage: `url(${signBackgroundImage.value})`,
|
||
backgroundSize: '100% 100%',
|
||
backgroundRepeat: 'no-repeat',
|
||
};
|
||
});
|
||
|
||
const formatPrizeText = (item: any) => {
|
||
if (!item) return '--';
|
||
const title = item?.title?.trim?.() || item?.prizeName?.trim?.() || item?.name?.trim?.() || '';
|
||
const score = Number(item?.score ?? item?.price ?? 0);
|
||
const prizeType = item?.prizeType;
|
||
if (title && score <= 0) return title;
|
||
if (prizeType === 1) return `金币${score}`;
|
||
if (prizeType === 2) return `${score}积分`;
|
||
if (prizeType === 3) return `VIP${score}天`;
|
||
return title || (score > 0 ? `${score}积分` : '礼包奖励');
|
||
};
|
||
|
||
const getDayChipText = (col: any) => {
|
||
if (col.dayIndex === 0 && checkedDays.value > 0) return '第1天';
|
||
if (col.dayIndex === checkedDays.value && !allMsgObj.value?.checkin?.todayChecked) return '今天';
|
||
return `第${col.day}天`;
|
||
};
|
||
|
||
const handleVipRowClick = () => {
|
||
if (!hasVipTypeGte3.value) {
|
||
router.push('/member');
|
||
}
|
||
};
|
||
|
||
const checkinPage = async () => {
|
||
try {
|
||
const res: any = await HomeApi.checkinPrize({});
|
||
allMsgObj.value = res || {};
|
||
prizeList.value = res?.prizes || [];
|
||
bigPrizeList.value = res?.bigPrizes || [];
|
||
} catch (e) {
|
||
console.log(e);
|
||
} finally {
|
||
state.signLoading = false;
|
||
}
|
||
};
|
||
|
||
const fnSignIn = async () => {
|
||
if (allMsgObj.value?.checkin?.todayChecked) {
|
||
showToast('今日已签到');
|
||
return false;
|
||
}
|
||
openLoading();
|
||
try {
|
||
const res: any = await HomeApi.checkinClick({});
|
||
prizeVideo.value = res?.prizeVideo || '';
|
||
prizeH265Url.value = res?.h265Url || '';
|
||
showToast(res?.message || '签到成功');
|
||
if (res?.checkin?.doubleReward) {
|
||
showSevenRewardPopup.value = true;
|
||
} else if ((res?.checkin?.continuouslyDays || 0) < DOUBLE_REWARD_TARGET_DAY) {
|
||
showSignPopup.value = true;
|
||
}
|
||
await checkinPage();
|
||
userStore.updateWallet();
|
||
await userStore.updateUserInfo();
|
||
return true;
|
||
} catch (e) {
|
||
console.log(e);
|
||
return false;
|
||
} finally {
|
||
closeLoading();
|
||
}
|
||
};
|
||
|
||
const handleSignTrigger = () => {
|
||
if (allMsgObj.value?.checkin?.todayChecked) {
|
||
showToast('今日已签到');
|
||
return;
|
||
}
|
||
fnSignIn();
|
||
};
|
||
|
||
const handleClaimVipPrize = async (col: any) => {
|
||
if (!hasVipTypeGte3.value) {
|
||
router.push('/member');
|
||
return;
|
||
}
|
||
if (vipPrizeClaiming.value || !col?.canClaim) return;
|
||
vipPrizeClaiming.value = true;
|
||
try {
|
||
await HomeApi.checkinClaimVip({});
|
||
showToast('补领成功');
|
||
await checkinPage();
|
||
userStore.updateWallet();
|
||
await userStore.updateUserInfo();
|
||
} catch (e) {
|
||
console.log(e);
|
||
} finally {
|
||
vipPrizeClaiming.value = false;
|
||
}
|
||
};
|
||
|
||
const scrollTaskBoxToBottom = async () => {
|
||
await nextTick();
|
||
requestAnimationFrame(() => {
|
||
const taskBox = taskBoxRef.value;
|
||
if (!taskBox) return;
|
||
taskBox.scrollTo({
|
||
top: taskBox.scrollHeight,
|
||
behavior: 'smooth',
|
||
});
|
||
});
|
||
};
|
||
|
||
const handleRedeem = () => {
|
||
showSignPopup.value = false;
|
||
state.tabActive = 1;
|
||
void scrollTaskBoxToBottom();
|
||
};
|
||
|
||
const closeSevenRewardPopup = () => {
|
||
showSevenRewardPopup.value = false;
|
||
state.tabActive = 1;
|
||
void scrollTaskBoxToBottom();
|
||
};
|
||
|
||
const handleContinueRedeem = () => {
|
||
showRedeemSuccessPopup.value = false;
|
||
};
|
||
|
||
const handleShareFriend = () => {
|
||
showRedeemSuccessPopup.value = false;
|
||
router.push('/share');
|
||
};
|
||
|
||
const getSign = async () => {
|
||
try {
|
||
await checkinPage();
|
||
} catch (e) {
|
||
console.log(e);
|
||
state.signLoading = false;
|
||
}
|
||
};
|
||
const queryFreeCount = () => {
|
||
UserApi.queryWallet().then((res: any) => {
|
||
state.freeCount = res.aiUndressFreeTimes || 0;
|
||
});
|
||
};
|
||
// 签到
|
||
const init = async () => {
|
||
getList();
|
||
await getIntegralList();
|
||
await getSign();
|
||
await getSignExtraPrizesList();
|
||
queryFreeCount();
|
||
};
|
||
init();
|
||
|
||
const exchangeItem = async (data: any) => {
|
||
let req = {
|
||
id: data.id,
|
||
};
|
||
await exchange(req);
|
||
};
|
||
|
||
const exchange = async (item: any) => {
|
||
try {
|
||
let req = item;
|
||
const res: any = await HomeApi.exchangeIntegral(req);
|
||
userStore.updateWallet();
|
||
// const prize = res?.prize || res;
|
||
// if (prize?.isBigGift) {
|
||
// currentRedeemItem.value = prize;
|
||
// showRedeemSuccessPopup.value = true;
|
||
// } else {
|
||
showToast(res?.msg || '兑换成功');
|
||
// }
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
};
|
||
|
||
const getSignExtraPrizesList = async () => {
|
||
try {
|
||
let req: any = await HomeApi.getSignExtraPrizesList();
|
||
state.signExtraPrizesList = req || [];
|
||
} catch (e) {
|
||
console.log(e);
|
||
}
|
||
};
|
||
const loading = ref(false);
|
||
const onRefresh = async () => {
|
||
await init();
|
||
loading.value = false;
|
||
};
|
||
|
||
// 红包雨任务倒计时:全局秒级时钟,避免每个 task 各自 setInterval
|
||
const now = ref(Date.now());
|
||
let countdownTimer: number | null = null;
|
||
|
||
/** HH:mm:ss 倒计时格式化,与首页活动浮窗保持一致 */
|
||
const formatCountdown = (remainMs: number) => {
|
||
const totalSec = Math.max(0, Math.floor(remainMs / 1000));
|
||
const hour = Math.floor(totalSec / 3600);
|
||
const minute = Math.floor((totalSec % 3600) / 60);
|
||
const second = totalSec % 60;
|
||
return `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')}`;
|
||
};
|
||
|
||
/**
|
||
* 福利任务描述文案:
|
||
* - countdownType !== 1 或缺少 startAt/endAt:原样展示 item.desc
|
||
* - now < startAt:下一场倒计时开启HH:mm:ss
|
||
* - startAt ≤ now < endAt:进行中 倒计时HH:mm:ss
|
||
* - now ≥ endAt:场次已结束,回退到 item.desc
|
||
*/
|
||
const getTaskDesc = (item: BenefitTaskItem) => {
|
||
if (Number(item.countdownType) !== 1) return item.desc || item.subTitle || '';
|
||
const startAt = new Date(item.startAt ?? '').getTime();
|
||
const endAt = new Date(item.endAt ?? '').getTime();
|
||
if (!startAt || !endAt) return item.desc || item.subTitle || '';
|
||
if (now.value < startAt) return `下一场倒计时开启${formatCountdown(startAt - now.value)}`;
|
||
if (now.value < endAt) return `进行中 倒计时${formatCountdown(endAt - now.value)}`;
|
||
return item.desc || item.subTitle || '';
|
||
};
|
||
|
||
/** 任务红包雨阶段:未开始 / 进行中 / 已结束(或无效) */
|
||
const getTaskHongbaoPhase = (item: BenefitTaskItem): 'pending' | 'active' | 'ended' => {
|
||
const startAt = new Date(item.startAt ?? '').getTime();
|
||
const endAt = new Date(item.endAt ?? '').getTime();
|
||
if (!startAt || !endAt) return 'ended';
|
||
if (now.value < startAt) return 'pending';
|
||
if (now.value < endAt) return 'active';
|
||
return 'ended';
|
||
};
|
||
|
||
onMounted(() => {
|
||
countdownTimer = window.setInterval(() => {
|
||
now.value = Date.now();
|
||
}, 1000);
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
if (countdownTimer) {
|
||
clearInterval(countdownTimer);
|
||
countdownTimer = null;
|
||
}
|
||
});
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.task {
|
||
position: relative;
|
||
height: 100%;
|
||
padding-top: 44px;
|
||
.task_bg {
|
||
width: 100%;
|
||
height: auto;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
}
|
||
.task_box {
|
||
height: calc(100vh - 44px);
|
||
padding: 0 0 100px;
|
||
}
|
||
.isHeader {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
z-index: 2;
|
||
}
|
||
.content_topBox {
|
||
width: 100%;
|
||
// height: 166px;
|
||
// background: url('@/assets/images/png/task_bg.png') left -99px no-repeat;
|
||
// background-size: 100% 240px;
|
||
}
|
||
.tip_text {
|
||
color: #999;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
line-height: 18px;
|
||
text-align: center;
|
||
margin-top: 20px;
|
||
margin-bottom: 10px;
|
||
}
|
||
.top_content {
|
||
// display: flex;
|
||
// align-items: center;
|
||
// flex-direction: column;
|
||
padding: 6px 0;
|
||
.userinfo {
|
||
width: 100%;
|
||
height: 60px;
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
padding: 0 16px;
|
||
margin-bottom: 18px;
|
||
//background: url('@/assets/images/png/task_bg.png') right top no-repeat;
|
||
.avatar {
|
||
width: 60px;
|
||
height: 60px;
|
||
border-radius: 50%;
|
||
overflow: hidden;
|
||
margin-right: 12px;
|
||
box-sizing: border-box;
|
||
|
||
&--vip {
|
||
border: 2px solid #ffd84d;
|
||
}
|
||
}
|
||
.name_box {
|
||
.name {
|
||
display: flex;
|
||
align-items: center;
|
||
color: #fff;
|
||
font-size: 18px;
|
||
font-weight: 600;
|
||
line-height: 24px;
|
||
margin-bottom: 4px;
|
||
div {
|
||
max-width: 220px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
:deep(img) {
|
||
margin-left: 4px;
|
||
}
|
||
}
|
||
.tip {
|
||
color: #999;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
line-height: 18px;
|
||
}
|
||
}
|
||
}
|
||
.vip_btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 343px;
|
||
height: 53px;
|
||
margin: 0 auto;
|
||
border-radius: 7.73px;
|
||
background: url('@/assets/images/png/task_vip_bg.png') no-repeat;
|
||
background-size: 100% 100%;
|
||
padding: 6px 20px;
|
||
.label {
|
||
color: #f68804;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
line-height: normal;
|
||
}
|
||
.time {
|
||
display: flex;
|
||
align-items: center;
|
||
color: #fff;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
line-height: 16.028px;
|
||
span {
|
||
height: 18px;
|
||
width: 83px;
|
||
text-align: center;
|
||
line-height: 18px;
|
||
border-radius: 32px;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
color: #999;
|
||
font-size: 11px;
|
||
font-weight: 400;
|
||
margin-left: 4px;
|
||
}
|
||
}
|
||
.openVip {
|
||
width: 84px;
|
||
height: 25px;
|
||
color: #fff;
|
||
font-size: 12px;
|
||
line-height: 25px;
|
||
text-align: center;
|
||
border-radius: 99px;
|
||
background: #F68804;
|
||
// background: url('@/assets/images/png/task_vip_btn.png') no-repeat;
|
||
// background-size: 100% 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
img {
|
||
width: 11px;
|
||
height: 11px;
|
||
}
|
||
}
|
||
}
|
||
.btn {
|
||
display: flex;
|
||
width: 290px;
|
||
height: 40px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border-radius: 30px;
|
||
background: linear-gradient(90deg, #ff9077 0%, #ff6e4e 100%), linear-gradient(90deg, #f0927e 0%, #ea4e74 100%);
|
||
box-shadow: 0 2px 4px 0 rgba(236, 92, 94, 0.6);
|
||
color: #fff;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
line-height: 18px;
|
||
margin: 0 auto;
|
||
}
|
||
}
|
||
.signContent {
|
||
width: 343px;
|
||
min-height: 320px;
|
||
margin: 16px auto 0;
|
||
padding: 12px 10px 16px;
|
||
border-radius: 12px;
|
||
border-top: 0.5px solid #e9d16f;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
box-shadow: 0 0 12px rgba(0, 0, 0, 0.05);
|
||
overflow: hidden;
|
||
position: relative;
|
||
|
||
:deep(.loading_warp),
|
||
:deep(.loading) {
|
||
min-height: 280px;
|
||
}
|
||
|
||
.sign-header {
|
||
display: flex;
|
||
align-items: center;
|
||
min-height: 24px;
|
||
margin: 0 0 9px 0;
|
||
}
|
||
|
||
.sign-title {
|
||
color: #ffdd3a;
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
line-height: 24px;
|
||
letter-spacing: 0;
|
||
}
|
||
|
||
.sign-reward-chip {
|
||
flex-shrink: 0;
|
||
height: 18px;
|
||
border-radius: 12px;
|
||
padding: 0 10px;
|
||
line-height: 18px;
|
||
color: #fff;
|
||
font-size: 9px;
|
||
margin-left: 10px;
|
||
background: linear-gradient(180deg, #ef2a31 0%, #b51015 100%);
|
||
position: relative;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 5px;
|
||
bottom: -5px;
|
||
width: 10px;
|
||
height: 7px;
|
||
background: #b51015;
|
||
clip-path: polygon(0 0, 100% 0, 0 100%);
|
||
}
|
||
}
|
||
|
||
.sign-progress {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 9px;
|
||
height: 42px;
|
||
padding: 0 12px;
|
||
border-radius: 10px;
|
||
background: rgba(255, 255, 255, 0.06);
|
||
margin-bottom: 11px;
|
||
}
|
||
|
||
.progress-track {
|
||
flex: 1;
|
||
height: 4px;
|
||
border-radius: 999px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
overflow: visible;
|
||
position: relative;
|
||
}
|
||
|
||
.progress-inner-mask {
|
||
position: absolute;
|
||
inset: 0;
|
||
border-radius: 999px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.progress-inner {
|
||
height: 100%;
|
||
border-radius: 999px;
|
||
background: #f68804;
|
||
box-shadow: 0 0 10px rgba(255, 217, 0, 0.38);
|
||
}
|
||
|
||
.progress-icon {
|
||
width: 18px;
|
||
height: 18px;
|
||
object-fit: contain;
|
||
position: absolute;
|
||
top: -10px;
|
||
transform: translateX(-50%);
|
||
pointer-events: none;
|
||
z-index: 2;
|
||
}
|
||
|
||
.progress-percent {
|
||
color: #fff;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
line-height: 18px;
|
||
}
|
||
|
||
.sign-subtitle {
|
||
color: rgba(255, 255, 255, 0.6);
|
||
font-size: 14px;
|
||
line-height: 22px;
|
||
margin-bottom: 12px;
|
||
|
||
.highlight {
|
||
color: #f52c56;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
.sign-sync-wrap {
|
||
margin: 0 -10px;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sign-sync-scroll {
|
||
overflow-x: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
padding-bottom: 2px;
|
||
|
||
&::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.sign-sync-content {
|
||
width: max-content;
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
|
||
&::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
position: relative;
|
||
}
|
||
|
||
.sign-days-row,
|
||
.sign-cards-row {
|
||
display: flex;
|
||
gap: 6px;
|
||
padding-left: 10px;
|
||
padding-right: 10px;
|
||
// overflow-x: auto;
|
||
}
|
||
|
||
.sign-cards-row-free {
|
||
height: 120px;
|
||
padding-top: 8px;
|
||
padding-bottom: 8px;
|
||
}
|
||
|
||
.free-claim-default-bg {
|
||
height: 120px;
|
||
padding-top: 8px;
|
||
padding-bottom: 8px;
|
||
// background: url('@/assets/images/png/mine/sign-free-bg.png') no-repeat left top,
|
||
// linear-gradient(to right, transparent 0, transparent 331px, rgba(255, 255, 255, 0.04) 331px);
|
||
background: rgba(255, 255, 255, 0.05);
|
||
// background-size: 331px 84px, 100% 100%;
|
||
border-radius: 12px;
|
||
position: absolute;
|
||
bottom: 134px;
|
||
left: 0;
|
||
width: 100%;
|
||
z-index: 0;
|
||
}
|
||
|
||
.sign-cards-row-vip {
|
||
position: relative;
|
||
height: 120px;
|
||
padding-top: 8px;
|
||
padding-bottom: 8px;
|
||
// background: url('@/assets/images/png/mine/sign-vip-bg.png') no-repeat left top,
|
||
// linear-gradient(to right, transparent 0, transparent 331px, rgba(255, 218, 11, 0.05) 331px);
|
||
// background: rgba(255, 218, 11, 0.08);
|
||
// background-size: 331px 84px, 100% 100%;
|
||
// border-radius: 12px;
|
||
// border-bottom: 1px solid rgba(255, 218, 11, 0.5);
|
||
// box-shadow: 0px -4px 8px 0px rgba(255, 211, 1, 0.29) inset;
|
||
}
|
||
.vip-claim-default-bg {
|
||
height: 120px;
|
||
padding-top: 8px;
|
||
padding-bottom: 8px;
|
||
background: rgba(255, 218, 11, 0.08);
|
||
// background-size: 331px 84px, 100% 100%;
|
||
border-radius: 12px;
|
||
border-bottom: 1px solid rgba(255, 218, 11, 0.5);
|
||
box-shadow: 0px -4px 8px 0px rgba(255, 211, 1, 0.29) inset;
|
||
position: absolute;
|
||
bottom: 4px;
|
||
left: 0;
|
||
width: 100%;
|
||
z-index: 0;
|
||
}
|
||
.vip-claim-badge {
|
||
position: absolute;
|
||
top: 1px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
z-index: 3;
|
||
padding: 1px 4px;
|
||
border-radius: 3px;
|
||
background: #f42b2b;
|
||
color: #fff;
|
||
font-size: 9px;
|
||
line-height: 1.15;
|
||
white-space: nowrap;
|
||
}
|
||
.vip-claim-bg {
|
||
position: absolute;
|
||
bottom: 10px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 331px;
|
||
height: 20px;
|
||
z-index: 1;
|
||
img {
|
||
width: 331px;
|
||
height: 20px;
|
||
}
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: -6px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 319px;
|
||
height: 1px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
}
|
||
.free-claim-bg {
|
||
position: absolute;
|
||
bottom: 140px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 331px;
|
||
height: 20px;
|
||
z-index: 1;
|
||
img {
|
||
width: 331px;
|
||
height: 20px;
|
||
}
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: -6px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 319px;
|
||
height: 1px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
}
|
||
}
|
||
.vip-slash {
|
||
position: absolute;
|
||
left: 21px;
|
||
top: 70%;
|
||
width: 2px;
|
||
height: 35px;
|
||
background: #000;
|
||
border-radius: 1px;
|
||
transform: translateY(-50%) rotate(-70deg);
|
||
}
|
||
|
||
.day-chip {
|
||
flex: 0 0 auto;
|
||
width: 42px;
|
||
height: 20px;
|
||
border-radius: 4px;
|
||
color: #62020e;
|
||
background: #ffd900;
|
||
font-size: 12px;
|
||
line-height: 20px;
|
||
text-align: center;
|
||
opacity: 0.96;
|
||
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.16);
|
||
|
||
&.active {
|
||
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.48) inset;
|
||
}
|
||
|
||
&.done {
|
||
background: #4d4d4d;
|
||
color: rgba(255, 255, 255, 0.55);
|
||
box-shadow: none;
|
||
}
|
||
|
||
&.seventh {
|
||
background: linear-gradient(180deg, #ffe56f 0%, #ffc400 100%);
|
||
}
|
||
|
||
&.shake-day {
|
||
animation: day-shake 0.8s ease-in-out infinite;
|
||
transform-origin: center;
|
||
}
|
||
}
|
||
|
||
.prize-card {
|
||
flex: 0 0 auto;
|
||
width: 42px;
|
||
height: 68px;
|
||
border-radius: 6px;
|
||
padding: 7px 4px 6px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.14) 0%, rgba(255, 255, 255, 0.07) 100%);
|
||
position: relative;
|
||
box-sizing: border-box;
|
||
|
||
.item-mask {
|
||
width: 13px;
|
||
height: 2px;
|
||
border-radius: 20px;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
margin-bottom: 8px;
|
||
}
|
||
.prize-img-box {
|
||
width: 34px;
|
||
height: 34px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.prize-img {
|
||
width: 34px;
|
||
height: 34px;
|
||
overflow: hidden;
|
||
transition: filter 0.2s ease;
|
||
transform-origin: center center;
|
||
will-change: transform;
|
||
object-fit: contain;
|
||
}
|
||
|
||
.prize-img.shake-prize {
|
||
animation: prize-icon-shake 0.65s ease-in-out infinite;
|
||
}
|
||
|
||
.prize-img.signed-gray {
|
||
filter: grayscale(1) brightness(0.85);
|
||
}
|
||
|
||
.expired-icon {
|
||
width: 31px;
|
||
height: 31px;
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
z-index: 2;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.vip-lock-icon {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 18px;
|
||
height: 18px;
|
||
z-index: 2;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.prize-score {
|
||
position: absolute;
|
||
top: 5px;
|
||
right: 0;
|
||
color: #ffd460;
|
||
text-align: right;
|
||
font-family: Impact, sans-serif;
|
||
font-size: 10px;
|
||
font-weight: 400;
|
||
line-height: normal;
|
||
}
|
||
}
|
||
|
||
.prize-name {
|
||
margin-top: 4px;
|
||
width: 100%;
|
||
color: #ffd900;
|
||
font-size: 10px;
|
||
line-height: 14px;
|
||
text-align: center;
|
||
font-weight: 400;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
|
||
&.signed-white {
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
.touchShowMore {
|
||
width: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-top: 26px;
|
||
}
|
||
|
||
.signIn {
|
||
width: 265px;
|
||
height: 38px;
|
||
border-radius: 999px;
|
||
color: #141414;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background: #f68804;
|
||
display: inline-flex;
|
||
}
|
||
|
||
.signInIcon {
|
||
width: 22px;
|
||
height: 22px;
|
||
margin-left: 6px;
|
||
}
|
||
|
||
.signInEnd {
|
||
width: 178px;
|
||
height: 38px;
|
||
border-radius: 999px;
|
||
color: #fff;
|
||
font-size: 15px;
|
||
font-weight: 500;
|
||
justify-content: center;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.3);
|
||
display: inline-flex;
|
||
}
|
||
|
||
.unlock-vip-tip {
|
||
color: #fff;
|
||
font-size: 13px;
|
||
line-height: 22px;
|
||
margin-top: 16px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
justify-content: center;
|
||
img {
|
||
width: 257px;
|
||
height: 18px;
|
||
}
|
||
}
|
||
|
||
.unlock-vip-highlight {
|
||
color: #ffda0b;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.unlock-vip-btn {
|
||
height: 22px;
|
||
line-height: 22px;
|
||
border-radius: 999px;
|
||
padding: 0 10px;
|
||
color: #5b3100;
|
||
background: #ffda0b;
|
||
margin-left: 6px;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
.checkin_rewards {
|
||
width: 343px;
|
||
margin: 20px auto 0;
|
||
// padding: 16px 12px;
|
||
padding: 16px 6px;
|
||
background: rgba(255, 255, 255, 0.05);
|
||
box-shadow: 0 0 12px 0 rgba(15, 15, 15, 0.05);
|
||
border-radius: 6px;
|
||
.checkin_title {
|
||
background: var(---, linear-gradient(135deg, #ffe580 0%, #facc15 100%));
|
||
background-clip: text;
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
line-height: 22px;
|
||
margin-bottom: 8px;
|
||
width: 50%;
|
||
margin-left: 6px;
|
||
}
|
||
.checkin_subtitle {
|
||
color: rgba(255, 255, 255, 0.55);
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
line-height: 20px;
|
||
margin-bottom: 14px;
|
||
margin-left: 6px;
|
||
}
|
||
.reward_cards {
|
||
display: flex;
|
||
overflow-x: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
gap: 8px;
|
||
scrollbar-width: none; /* Firefox */
|
||
&::-webkit-scrollbar {
|
||
display: none; /* Chrome, Safari, Edge */
|
||
}
|
||
.reward_card {
|
||
flex: 0 0 auto;
|
||
width: 72px;
|
||
min-width: 72px;
|
||
height: 86px;
|
||
min-height: 86px;
|
||
position: relative;
|
||
background: linear-gradient(180deg, rgba(141, 0, 2, 0.3) 0%, rgba(0, 7, 139, 0.3) 100%);
|
||
box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.05);
|
||
border-radius: 12px;
|
||
padding: 8px 4px;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
// justify-content: space-between;
|
||
// overflow: hidden;
|
||
.reward_line {
|
||
flex-shrink: 0;
|
||
width: 13px;
|
||
height: 2px;
|
||
background: rgba(249, 192, 137, 0.2);
|
||
margin: 2px 0;
|
||
}
|
||
.duration_badge {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 45px;
|
||
min-width: 30px;
|
||
// max-width: 80px;
|
||
height: 16px;
|
||
line-height: 15px;
|
||
z-index: 1;
|
||
// background: url('@/assets/images/png/duration_badge.png') center center no-repeat;
|
||
// background-size: 100% 100%;
|
||
background: rgba(218, 0, 4, 1);
|
||
color: #fff;
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
white-space: nowrap;
|
||
text-align: center;
|
||
padding: 0 6px;
|
||
border-radius: 99px;
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: -6.2px;
|
||
left: 3px;
|
||
width: 0;
|
||
height: 0;
|
||
border-top: 10px solid rgba(218, 0, 4, 1);
|
||
border-right: 10px solid transparent;
|
||
z-index: 0;
|
||
transform: rotate3d(1, 1, 1, 45deg);
|
||
}
|
||
}
|
||
.reward_icon {
|
||
flex-shrink: 0;
|
||
width: 24px;
|
||
height: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 4px 0;
|
||
:deep(.lazy_img) {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
}
|
||
}
|
||
.reward_text {
|
||
color: #fff;
|
||
font-size: 10px;
|
||
font-weight: 400;
|
||
text-align: center;
|
||
margin-bottom: 4px;
|
||
}
|
||
.claim_btn {
|
||
flex-shrink: 0;
|
||
width: 56px;
|
||
height: 20px;
|
||
border-radius: 10px;
|
||
background: rgba(255, 255, 255, 0.3);
|
||
color: rgba(255, 255, 255, 0.55);
|
||
font-size: 10px;
|
||
font-weight: 400;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
white-space: nowrap;
|
||
//&.active {
|
||
// // background: rgba(54, 112, 255, 1);
|
||
// color: #fff;
|
||
//}
|
||
//&:active {
|
||
// opacity: 0.8;
|
||
//}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.tabs_ltype {
|
||
position: relative;
|
||
width: 343px;
|
||
margin: 22px auto 0 auto;
|
||
.record {
|
||
position: absolute;
|
||
right: 0;
|
||
top: 8px;
|
||
z-index: 1;
|
||
color: #999;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
line-height: 18px;
|
||
}
|
||
.tab_title {
|
||
img {
|
||
width: 60px;
|
||
}
|
||
.active {
|
||
width: 80px;
|
||
}
|
||
}
|
||
}
|
||
.tabs_line {
|
||
position: absolute;
|
||
top: 50px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: calc(100% - 64px);
|
||
height: 1px;
|
||
background: #e8f2ed;
|
||
}
|
||
.tabs_record {
|
||
position: absolute;
|
||
right: 14px;
|
||
top: 20px;
|
||
font-size: 12px;
|
||
color: rgba(0, 0, 0, 0.6);
|
||
}
|
||
.task_tabs {
|
||
overflow: hidden;
|
||
:deep(> .van-tabs__wrap) {
|
||
height: 34px;
|
||
width: 100%;
|
||
margin: 0 auto;
|
||
.van-tabs__nav {
|
||
background: unset;
|
||
justify-content: flex-start;
|
||
column-gap: 18px;
|
||
padding: 0;
|
||
.van-tab {
|
||
flex: 0 0 auto;
|
||
font-size: 16px;
|
||
padding: 0;
|
||
font-weight: 400;
|
||
&.van-tab--active {
|
||
font-size: 18px;
|
||
}
|
||
}
|
||
.van-tabs__line {
|
||
height: 4px;
|
||
width: 16px;
|
||
border-radius: 3px 3px 0 0;
|
||
background: #f68804;
|
||
bottom: 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.taskBox {
|
||
padding: 12px 0;
|
||
|
||
.title {
|
||
padding: 0 10px;
|
||
font-size: 18px;
|
||
font-weight: 550;
|
||
span {
|
||
font-size: 12px;
|
||
color: #999;
|
||
font-weight: 300;
|
||
}
|
||
}
|
||
.subTitle {
|
||
padding: 0 10px;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: #999999;
|
||
margin: 15px 0 20px;
|
||
span {
|
||
padding-right: 20px;
|
||
}
|
||
.exchangeVip {
|
||
height: 28px;
|
||
width: 67px;
|
||
background-color: $themeColor;
|
||
border-radius: 40px;
|
||
text-align: center;
|
||
line-height: 28px;
|
||
font-size: 12px;
|
||
color: #fff;
|
||
}
|
||
}
|
||
.taskList {
|
||
.total_score {
|
||
color: rgba(0, 0, 0, 0.8);
|
||
text-align: center;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
line-height: 18px;
|
||
span {
|
||
color: #ff3d6a;
|
||
}
|
||
}
|
||
.taskItem {
|
||
margin-bottom: 12px;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
background: rgba(255, 255, 255, 0.05);
|
||
.leftBox {
|
||
flex: 1;
|
||
.taskIcon {
|
||
height: 40px;
|
||
width: 40px;
|
||
border-radius: 50%;
|
||
overflow: hidden;
|
||
transform: translateZ(0px);
|
||
margin-right: 6px;
|
||
}
|
||
.taskInfo {
|
||
flex: 1;
|
||
.taskName {
|
||
font-size: 14px;
|
||
color: rgba(255, 255, 255, 0.9);
|
||
line-height: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
span {
|
||
color: #f54570;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
margin-left: 8px;
|
||
}
|
||
.countdownTag {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 14px;
|
||
padding: 0 8px;
|
||
border-radius: 26px;
|
||
border: 0.5px solid #fff1b2;
|
||
background: #ffa800;
|
||
color: #fff !important;
|
||
font-size: 10px !important;
|
||
font-weight: 400;
|
||
line-height: 14px;
|
||
// 与任务标题文字垂直居中对齐
|
||
vertical-align: middle;
|
||
}
|
||
}
|
||
.taskDesc {
|
||
color: rgba(255, 255, 255, 0.55);
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
line-height: 18px;
|
||
}
|
||
}
|
||
}
|
||
.btn {
|
||
height: 28px;
|
||
padding: 0 12px;
|
||
text-align: center;
|
||
line-height: 28px;
|
||
font-size: 12px;
|
||
color: #fff;
|
||
border-radius: 999px;
|
||
background: #f68804;
|
||
}
|
||
.receive {
|
||
color: #692a1f;
|
||
background: #ffd5a8;
|
||
border-radius: 17.053px;
|
||
// border: 1.263px solid #e9dce0;
|
||
}
|
||
.received {
|
||
// opacity: 0.3;
|
||
background: #525252;
|
||
color: rgba(255, 255, 255, 0.9);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.score_wrap {
|
||
padding: 12px 0;
|
||
}
|
||
.score {
|
||
display: flex;
|
||
align-items: center;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
line-height: 20px;
|
||
margin-bottom: 12px;
|
||
span {
|
||
color: #f68804;
|
||
font-size: 24px;
|
||
font-weight: 700;
|
||
line-height: 32px;
|
||
margin-left: 4px;
|
||
}
|
||
}
|
||
.title {
|
||
padding: 24px 0 12px 0;
|
||
box-sizing: border-box;
|
||
font-size: 18px;
|
||
font-weight: 550;
|
||
}
|
||
.list_jf {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
grid-row-gap: 7px;
|
||
grid-column-gap: 9px;
|
||
padding-bottom: 12px;
|
||
.itemlist {
|
||
width: 168px;
|
||
height: 134px;
|
||
padding: 12px 8px;
|
||
overflow: hidden;
|
||
border-radius: 12px;
|
||
background: #303030;
|
||
.top {
|
||
height: 78px;
|
||
padding: 15px 12px;
|
||
box-sizing: border-box;
|
||
position: relative;
|
||
p {
|
||
font-size: 16px;
|
||
margin-bottom: 5px;
|
||
position: relative;
|
||
z-index: 10;
|
||
color: #fff;
|
||
}
|
||
span {
|
||
font-size: 10px;
|
||
color: #cccccc;
|
||
position: relative;
|
||
z-index: 10;
|
||
}
|
||
.itemlistimg {
|
||
position: absolute;
|
||
width: 100%;
|
||
height: 100%;
|
||
top: 0;
|
||
left: 0;
|
||
}
|
||
}
|
||
.bot {
|
||
//height: 36px;
|
||
padding: 0 12px;
|
||
box-sizing: border-box;
|
||
font-size: 12px;
|
||
color: #989898;
|
||
margin-top: 10px;
|
||
.btn {
|
||
font-size: 10px;
|
||
width: 56px;
|
||
height: 22px;
|
||
background: #f68804;
|
||
color: #141414;
|
||
border-radius: 20px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.submit-box {
|
||
position: absolute;
|
||
bottom: 0;
|
||
@include SafeArea('padding', 'bottom', 30px);
|
||
background: #000000;
|
||
width: 100%;
|
||
.submit {
|
||
margin: 0 auto;
|
||
width: 290px;
|
||
height: 40px;
|
||
background: linear-gradient(90deg, #f0927e 0%, #ea4e74 100%), linear-gradient(90deg, #ff9077 0%, #ff6e4e 100%);
|
||
border-radius: 99px;
|
||
color: #fff;
|
||
font-size: 16px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.progress-icon.shake {
|
||
animation: icon-shake 0.72s ease-in-out infinite;
|
||
transform-origin: center bottom;
|
||
}
|
||
|
||
@keyframes icon-shake {
|
||
0% {
|
||
transform: translateX(-50%) rotate(0deg);
|
||
}
|
||
20% {
|
||
transform: translateX(-50%) rotate(-10deg);
|
||
}
|
||
40% {
|
||
transform: translateX(-50%) rotate(9deg);
|
||
}
|
||
60% {
|
||
transform: translateX(-50%) rotate(-7deg);
|
||
}
|
||
80% {
|
||
transform: translateX(-50%) rotate(6deg);
|
||
}
|
||
100% {
|
||
transform: translateX(-50%) rotate(0deg);
|
||
}
|
||
}
|
||
|
||
@keyframes day-shake {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
25% {
|
||
transform: rotate(-6deg);
|
||
}
|
||
50% {
|
||
transform: rotate(5deg);
|
||
}
|
||
75% {
|
||
transform: rotate(-4deg);
|
||
}
|
||
100% {
|
||
transform: rotate(0deg);
|
||
}
|
||
}
|
||
|
||
@keyframes prize-icon-shake {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
20% {
|
||
transform: rotate(-11deg) scale(1.02);
|
||
}
|
||
40% {
|
||
transform: rotate(10deg) scale(1.03);
|
||
}
|
||
60% {
|
||
transform: rotate(-8deg) scale(1.04);
|
||
}
|
||
80% {
|
||
transform: rotate(7deg) scale(1.02);
|
||
}
|
||
100% {
|
||
transform: rotate(0deg) scale(1);
|
||
}
|
||
}
|
||
</style>
|