675 lines
15 KiB
Vue
675 lines
15 KiB
Vue
<template>
|
||
<view class="navbox">
|
||
<view class="status_bar"></view>
|
||
<uni-nav-bar
|
||
left-icon="left"
|
||
title="我的福利卡"
|
||
@clickLeft="goBack"
|
||
color="#8B2316"
|
||
:border="false"
|
||
backgroundColor="#eeeeee"
|
||
>
|
||
|
||
</uni-nav-bar>
|
||
</view>
|
||
<!-- <navBar :title="'我的福利卡'" /> -->
|
||
|
||
<view class="benefits-page">
|
||
<!-- 顶部红色横幅 -->
|
||
<view class="top-banner" @click="goWelfare" v-if="hasCard">
|
||
<image :src="bgImg" mode="widthFix" class="bg-img"></image>
|
||
<view class="banner-text">
|
||
<view class="line1">已兑换{{ totalCount}}张</view>
|
||
<view class="line2" @click.stop="goWelfare">查看现有权益</view>
|
||
</view>
|
||
<view class="help-btn" @click.stop="showRules">帮助说明</view>
|
||
</view>
|
||
|
||
<!-- 帮助说明模态框(与兑换页一致的居中弹层) -->
|
||
<view v-if="centerVisible" class="center-modal" @click.self="closeCenter">
|
||
<view class="center-modal-content">
|
||
<view class="center-title">帮助说明</view>
|
||
<view class="center-help">
|
||
<text>1、点击“兑换福利卡”,输入密码即可兑换相应权益</text>
|
||
<text>2、每张福利卡仅限兑换一次,兑换后权益可在“我的福利-使用福利”中查看</text>
|
||
<text>3、福利卡长期有效,福利卡不能退换或者折现</text>
|
||
<text>4、查找文献权益不限文献类型,如指南共识、论文、电子书、课件或者视频</text>
|
||
</view>
|
||
<view class="center-actions">
|
||
<button class="center-btn" @click="closeCenter">知道了</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 有卡展示(多张) -->
|
||
<scroll-view
|
||
v-if="hasCard"
|
||
class="scroll-container"
|
||
scroll-y
|
||
:refresher-enabled="true"
|
||
:refresher-triggered="refreshing"
|
||
@refresherrefresh="onRefresh"
|
||
@scrolltolower="onLoadMore"
|
||
:lower-threshold="50"
|
||
>
|
||
<view class="card-wrapper" v-for="(card, cIdx) in cardInfo" :key="card.id">
|
||
<image :src="cardImg" mode="widthFix" class="card-img"></image>
|
||
<view class="cardbox">
|
||
<view class="card-header">
|
||
<image :src="logoImg" mode="widthFix" class="logo-img"></image>
|
||
<view class="headerbox">
|
||
<view>卡号:{{ card.idcard }}</view>
|
||
<view class="time">兑换时间:{{ card.exchange_date }}</view>
|
||
</view>
|
||
</view>
|
||
<view class="card-body">
|
||
<image v-if="card.welfare_list && card.welfare_list.length > 3 && (swiperCurrent[cIdx] || 0) > 0"
|
||
:src="rightImg" mode="widthFix" class="left-img" @click="swipeLeft(cIdx)"></image>
|
||
<view v-else class="left-img-placeholder"></view>
|
||
<!-- 超过3条使用swiper,否则直接显示 -->
|
||
<swiper v-if="card.welfare_list && card.welfare_list.length > 3"
|
||
:class="'welfare-swiper-' + cIdx"
|
||
class="welfare-swiper"
|
||
:indicator-dots="false"
|
||
:autoplay="false"
|
||
:circular="false"
|
||
:display-multiple-items="1"
|
||
:current="swiperCurrent[cIdx] || 0"
|
||
@change="onSwiperChange($event, cIdx)">
|
||
<swiper-item v-for="(page, pageIdx) in getWelfarePages(card.welfare_list)" :key="pageIdx">
|
||
<view class="linebox">
|
||
<view class="benefit-line" v-for="(w, idx) in page" :key="idx">
|
||
<text class="index">{{ pageIdx * 3 + idx + 1 }}、</text>
|
||
<text class="text">{{ w.type_name }}{{ w.num }}{{ w.type_unit }}</text>
|
||
</view>
|
||
</view>
|
||
</swiper-item>
|
||
</swiper>
|
||
<view v-else class="linebox">
|
||
<view class="benefit-line" v-for="(w, idx) in card.welfare_list" :key="idx">
|
||
<text class="index">{{ idx + 1 }}、</text>
|
||
<text class="text">{{ w.type_name }}{{ w.num }}{{ w.type_unit }}</text>
|
||
</view>
|
||
</view>
|
||
<image v-if="card.welfare_list && card.welfare_list.length > 3 && (swiperCurrent[cIdx] || 0) < getWelfarePages(card.welfare_list).length - 1"
|
||
:src="rightImg" mode="widthFix" class="right-img" @click="swipeRight(cIdx)"></image>
|
||
<view v-else class="right-img-placeholder"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 加载提示 -->
|
||
<view class="loadmore-tip" v-if="isLoading || isLastPage">
|
||
<text>{{ isLoading ? '加载中...' : (isLastPage ? '没有更多了' : '') }}</text>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 无卡空状态 -->
|
||
<view v-else class="emptybox">
|
||
<empty />
|
||
</view>
|
||
|
||
<!-- 底部导航栏 -->
|
||
<view class="bottom-nav">
|
||
<view class="nav-item" @click="goPointsDetail">
|
||
<up-image :src="jifenImg" width="34rpx" height="34rpx"></up-image>
|
||
<text class="nav-text">兑换福利卡</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue';
|
||
import jifenImg from "@/static/duihuan.png"
|
||
import emptyImg from "@/static/icon_empty.png"
|
||
import bgImg from '@/static/fulicard_bg.png'
|
||
import cardImg from '@/static/carditem_bg.png'
|
||
import api from '@/api/api';
|
||
import logoImg from '@/static/logo_gdxz.png'
|
||
import rightImg from '@/static/right_selsect_big.png'
|
||
import empty from '@/components/empty/empty.vue'
|
||
import { onLoad,onBackPress } from '@dcloudio/uni-app'
|
||
const totalCount = ref(0);
|
||
const from=ref('');
|
||
onBackPress(() => {
|
||
if(!from.value){
|
||
plus.runtime.quit();
|
||
return true;
|
||
}
|
||
});
|
||
onLoad((options) => {
|
||
from.value = options.from;
|
||
})
|
||
const goWelfare = () => {
|
||
uni.setStorageSync('lookWelfare', 'useWelfare');
|
||
console.log('6789');
|
||
uni.redirectTo({
|
||
url: '/pages_app/myWelfare/myWelfare'
|
||
});
|
||
}
|
||
// 是否有福利卡以及示例卡信息
|
||
const hasCard = ref(true)
|
||
const cardInfo = ref([]);
|
||
// 分页状态
|
||
const pageNum = ref(1)
|
||
const pageSize = ref(10)
|
||
const isLastPage = ref(false)
|
||
const isLoading = ref(false)
|
||
const refreshing = ref(false)
|
||
// 存储每个卡片的swiper当前索引
|
||
const swiperCurrent = ref({})
|
||
|
||
const getMyWelfareCard = (opts = { isRefresh: false }) => {
|
||
if (isLoading.value) return
|
||
isLoading.value = true
|
||
api.myWelfareCard({page: pageNum.value}).then(res => {
|
||
console.log(res)
|
||
if (res.code == 200) {
|
||
const list = Array.isArray(res.data.list) ? res.data.list : []
|
||
if (opts.isRefresh) {
|
||
cardInfo.value = list
|
||
} else {
|
||
cardInfo.value = pageNum.value === 1 ? list : cardInfo.value.concat(list)
|
||
}
|
||
totalCount.value = res.data.total;
|
||
hasCard.value = list.length > 0 || cardInfo.value.length > 0
|
||
isLastPage.value = !!res.data.isLastPage
|
||
}
|
||
})
|
||
.finally(() => {
|
||
isLoading.value = false
|
||
refreshing.value = false
|
||
})
|
||
}
|
||
|
||
const goBack = () => {
|
||
console.log('我的福利卡goBack');
|
||
console.log(from.value)
|
||
if(!from.value){
|
||
plus.runtime.quit();
|
||
}else{
|
||
uni.navigateBack();
|
||
}
|
||
}
|
||
onMounted(() => {
|
||
getMyWelfareCard()
|
||
})
|
||
|
||
// scroll-view 下拉刷新
|
||
const onRefresh = () => {
|
||
refreshing.value = true
|
||
pageNum.value = 1
|
||
isLastPage.value = false
|
||
getMyWelfareCard({ isRefresh: true })
|
||
}
|
||
|
||
// scroll-view 上拉加载更多
|
||
const onLoadMore = () => {
|
||
if (isLastPage.value || isLoading.value) return
|
||
pageNum.value += 1
|
||
getMyWelfareCard()
|
||
}
|
||
|
||
// 方法
|
||
|
||
const centerVisible = ref(false)
|
||
const showRules = () => {
|
||
centerVisible.value = true
|
||
};
|
||
const closeCenter = () => {
|
||
centerVisible.value = false
|
||
};
|
||
|
||
const goPointsDetail = () => {
|
||
console.log('goPointsDetail')
|
||
uni.navigateTo({ url: '/pages_app/myWelfareCard/exchange?num='+totalCount.value })
|
||
};
|
||
|
||
const goMyWelfare = () => {
|
||
uni.navigateTo({ url: '/pages_app/myWelfare/myWelfare' })
|
||
}
|
||
|
||
// 将福利列表分组,每组最多3条
|
||
const getWelfarePages = (welfareList) => {
|
||
if (!welfareList || welfareList.length === 0) return []
|
||
const pages = []
|
||
for (let i = 0; i < welfareList.length; i += 3) {
|
||
pages.push(welfareList.slice(i, i + 3))
|
||
}
|
||
return pages
|
||
}
|
||
|
||
// swiper切换事件
|
||
const onSwiperChange = (e, cardIndex) => {
|
||
swiperCurrent.value[cardIndex] = e.detail.current
|
||
}
|
||
|
||
// 向左滑动
|
||
const swipeLeft = (cardIndex) => {
|
||
const current = swiperCurrent.value[cardIndex] || 0
|
||
if (current > 0) {
|
||
swiperCurrent.value[cardIndex] = current - 1
|
||
}
|
||
}
|
||
|
||
// 向右滑动
|
||
const swipeRight = (cardIndex) => {
|
||
const current = swiperCurrent.value[cardIndex] || 0
|
||
const card = cardInfo.value[cardIndex]
|
||
if (card && card.welfare_list) {
|
||
const pages = getWelfarePages(card.welfare_list)
|
||
if (current < pages.length - 1) {
|
||
swiperCurrent.value[cardIndex] = current + 1
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
// 变量定义
|
||
$bg-color: #f5f6f7;
|
||
$text-primary: #333333;
|
||
$text-secondary: #666666;
|
||
$text-light: #999999;
|
||
$border-color: #e5e5e5;
|
||
$white: #ffffff;
|
||
$theme-color: #e74c3c;
|
||
$divider-color: #cccccc;
|
||
$nav-height: 140rpx; // 导航栏高度
|
||
$segmented-height: 80rpx; // 分段控制器高度
|
||
$bottom-nav-height: 120rpx; // 底部导航高度
|
||
|
||
// 混合器
|
||
@mixin flex-center {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
@mixin flex-between {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
@mixin shadow {
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.benefits-page {
|
||
height: 100vh;
|
||
.scroll-container {
|
||
position: fixed;
|
||
top: calc(var(--status-bar-height) + 44px + 286rpx);
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 100rpx;
|
||
height: calc(100vh - var(--status-bar-height) - 44px - 286rpx - 100rpx);
|
||
box-sizing: border-box;
|
||
}
|
||
.emptybox{
|
||
display: flex;
|
||
height: 100vh;
|
||
flex-direction:column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 100vh;
|
||
.empty_desc{
|
||
font-size: 30rpx;
|
||
color:#999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.status-bar {
|
||
height: 44rpx;
|
||
background-color: $white;
|
||
@include flex-between;
|
||
padding: 0 30rpx;
|
||
font-size: 24rpx;
|
||
color: $text-primary;
|
||
|
||
.status-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
|
||
.time {
|
||
font-weight: 500;
|
||
}
|
||
|
||
.butterfly {
|
||
font-size: 20rpx;
|
||
}
|
||
}
|
||
|
||
.status-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
|
||
.network-info,
|
||
.signal,
|
||
.wifi,
|
||
.battery {
|
||
font-size: 22rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.header {
|
||
height: 88rpx;
|
||
background-color: $white;
|
||
@include flex-between;
|
||
padding: 0 30rpx;
|
||
border-bottom: 1rpx solid $border-color;
|
||
|
||
.header-left {
|
||
.back-btn {
|
||
font-size: 48rpx;
|
||
color: $theme-color;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.header-center {
|
||
.title {
|
||
font-size: 36rpx;
|
||
color: $text-primary;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.header-right {
|
||
.rules-btn {
|
||
font-size: 28rpx;
|
||
color: $text-primary;
|
||
}
|
||
}
|
||
}
|
||
|
||
.segmented-control {
|
||
position: fixed;
|
||
top: $nav-height;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 10;
|
||
height: 80rpx;
|
||
background-color: $white;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 30rpx;
|
||
border-bottom: 1rpx solid $border-color;
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
@include flex-center;
|
||
height: 100%;
|
||
position: relative;
|
||
|
||
.tab-text {
|
||
font-size: 28rpx;
|
||
color: $text-secondary;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
&.active {
|
||
.tab-text {
|
||
color: #8B2316;
|
||
|
||
font-size: 30rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.divider {
|
||
width: 2rpx;
|
||
height: 40rpx;
|
||
background-color: $divider-color;
|
||
}
|
||
}
|
||
|
||
.benefits-list {
|
||
|
||
|
||
.benefit-card {
|
||
background: $white;
|
||
border-radius: 20rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 30rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
border:2rpx solid #fff;
|
||
|
||
.card-bg {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 20rpx;
|
||
left:20rpx;
|
||
z-index:0;
|
||
|
||
|
||
}
|
||
|
||
.card-content {
|
||
margin-top: 30rpx;
|
||
background:url("@/static/fljifen_big.png") 0 0 no-repeat;
|
||
background-size: 100% 100%;
|
||
position: relative;
|
||
height: 220rpx;
|
||
z-index: 1;
|
||
|
||
.card-title {
|
||
font-size: 32rpx;
|
||
color: $white;
|
||
font-weight: 600;
|
||
margin-bottom: 30rpx;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.card-details {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding:0 40rpx;
|
||
height: 220rpx;
|
||
.left-section,
|
||
.right-section {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8rpx;
|
||
|
||
.condition,
|
||
.reward-type {
|
||
font-size: 24rpx;
|
||
color: rgba(255, 255, 255, 11);
|
||
}
|
||
|
||
.requirement,
|
||
.reward-value {
|
||
font-size: 36rpx;
|
||
color: $white;
|
||
font-weight: bold;
|
||
}
|
||
.requirement{
|
||
margin-top: 40rpx;
|
||
}
|
||
}
|
||
|
||
.right-section {
|
||
align-items: flex-end;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 顶部横幅与卡片样式 */
|
||
.top-banner{
|
||
position: fixed;
|
||
height: 286rpx;
|
||
width:100%;
|
||
top: calc(var(--status-bar-height) + 44px);
|
||
.bg-img{
|
||
position: absolute;
|
||
width: 100%;
|
||
z-index:0;
|
||
height: 286rpx;
|
||
}
|
||
.banner-text{
|
||
position: absolute;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
top: 80rpx;
|
||
z-index:1;
|
||
color: #fff;
|
||
.line1{font-size: 44rpx;}
|
||
.line2{font-size: 36rpx;margin-top: 12rpx;}
|
||
}
|
||
.help-btn{
|
||
position: absolute;
|
||
right: 30rpx;
|
||
top: 20rpx;
|
||
background: rgba(255,255,255,.95);
|
||
color: #e04835;
|
||
border-radius: 999rpx;
|
||
padding: 10rpx 24rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
|
||
.card-wrapper{
|
||
position: relative;
|
||
margin: 24rpx 30rpx;
|
||
|
||
border-radius: 16rpx;
|
||
|
||
overflow: hidden;
|
||
.cardbox{
|
||
position: relative;
|
||
z-index:2;
|
||
}
|
||
.card-img{
|
||
position: absolute;
|
||
width: 100%;
|
||
z-index:0;
|
||
height: 336rpx;
|
||
}
|
||
.card-header{
|
||
|
||
color: #fff;
|
||
padding: 4rpx 28rpx;
|
||
font-size: 26rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
.headerbox{
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
}
|
||
.time{opacity:.95}
|
||
.logo-img{
|
||
width:94rpx;
|
||
height: 94rpx;
|
||
border-radius: 50%;
|
||
overflow: hidden;
|
||
margin-right: 20rpx;
|
||
}
|
||
}
|
||
.card-body{
|
||
height: 240rpx;
|
||
display: flex;
|
||
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding:0rpx 28rpx;
|
||
.left-img{
|
||
width:28rpx;
|
||
height: 50rpx;
|
||
transform: rotate(180deg);
|
||
cursor: pointer;
|
||
}
|
||
.right-img{
|
||
width:28rpx;
|
||
height: 50rpx;
|
||
cursor: pointer;
|
||
}
|
||
.left-img-placeholder,
|
||
.right-img-placeholder{
|
||
width:28rpx;
|
||
height: 50rpx;
|
||
}
|
||
.welfare-swiper{
|
||
flex: 1;
|
||
height: 100%;
|
||
}
|
||
.linebox{
|
||
min-width: 500rpx;
|
||
display: flex;
|
||
flex-flow: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding:0 20rpx;
|
||
height: 100%;
|
||
}
|
||
.benefit-line{
|
||
font-size: 30rpx;
|
||
width:355rpx;
|
||
color: #8B2316;
|
||
line-height: 56rpx;
|
||
text-align: left;
|
||
.index{color:#8B2316;}
|
||
.text{
|
||
|
||
text-align: left;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.bottom-nav {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 10;
|
||
height: 100rpx;
|
||
background-color: #00cbc0;
|
||
border-top: 1rpx solid $border-color;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-around;
|
||
padding: 0 20rpx;
|
||
|
||
.nav-item {
|
||
@include flex-center;
|
||
flex-direction: flex;
|
||
gap: 8rpx;
|
||
|
||
.nav-icon {
|
||
font-size: 40rpx;
|
||
}
|
||
|
||
.nav-text {
|
||
font-size: 32rpx;
|
||
color: #fff;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 底部加载提示 */
|
||
.loadmore-tip{
|
||
text-align: center;
|
||
color: #999;
|
||
font-size: 24rpx;
|
||
padding: 20rpx 0 120rpx; // 给底部按钮留出空间
|
||
}
|
||
|
||
/* 居中模态框样式(复用兑换页风格) */
|
||
.center-modal{position: fixed;left:0;right:0;top:0;bottom:0;background: rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;z-index: 9999;}
|
||
.center-modal-content{width: 640rpx;background:#fff;border-radius:24rpx;overflow:hidden;}
|
||
.center-title{font-size: 32rpx;color:#333;text-align:center;padding:28rpx 24rpx 12rpx;font-weight:600;}
|
||
.center-help{padding: 0 32rpx;display:flex;flex-direction:column;align-items:center;gap: 16rpx;color:#333;font-size:28rpx;line-height:1.6;}
|
||
.center-actions{padding: 24rpx 24rpx 28rpx;}
|
||
.center-btn{width:100%;height:88rpx;border-radius:999rpx;background:#e93b2d;color:#fff;font-size:30rpx;}
|
||
</style> |