2025-10-14 17:46:23 +08:00

497 lines
11 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<uni-nav-bar
left-icon="left"
title="我的福利卡"
@clickLeft="goBack"
fixed
color="#8B2316"
height="180rpx"
:border="false"
backgroundColor="#eeeeee"
></uni-nav-bar>
<view class="benefits-page">
<!-- 顶部红色横幅 -->
<view class="top-banner">
<view class="banner-text">
<view class="line1">已兑换{{ cardInfo.length }}</view>
<view class="line2" @click="goMyWelfare">查看现有权益</view>
</view>
<view class="help-btn" @click="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>
<!-- 有卡展示(多张) -->
<view v-if="hasCard" >
<view class="card-wrapper" v-for="(card, cIdx) in cardInfo" :key="card.id">
<view class="card-header">
<text>卡号:{{ card.idcard }}</text>
<text class="time">兑换时间:{{ card.exchange_date }}</text>
</view>
<view class="card-body">
<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>
</view>
<!-- 加载提示 -->
<view class="loadmore-tip" v-if="isLoading || isLastPage">
<text>{{ isLoading ? '加载中...' : (isLastPage ? '没有更多了' : '') }}</text>
</view>
</view>
<!-- 无卡空状态 -->
<view v-else class="emptybox">
<up-image :src="emptyImg" width="176rpx" height="204rpx"></up-image>
<view class="empty_desc">暂无福利卡</view>
</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 api from '@/api/api';
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
// 是否有福利卡以及示例卡信息
const hasCard = ref(true)
const cardInfo = ref([]);
// 分页状态
const pageNum = ref(1)
const pageSize = ref(10)
const isLastPage = ref(false)
const isLoading = ref(false)
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)
}
hasCard.value = list.length > 0 || cardInfo.value.length > 0
isLastPage.value = !!res.data.isLastPage
}
})
.finally(() => {
isLoading.value = false
uni.stopPullDownRefresh()
})
}
onMounted(() => {
getMyWelfareCard()
})
// 下拉刷新
onPullDownRefresh(() => {
pageNum.value = 1
isLastPage.value = false
getMyWelfareCard({ isRefresh: true })
})
// 上拉加载更多
onReachBottom(() => {
if (isLastPage.value || isLoading.value) return
pageNum.value += 1
getMyWelfareCard()
})
// 方法
const goBack = () => {
uni.navigateBack({
fail() {
uni.redirectTo({
url: '/pages/index/index'
});
}
});
};
const centerVisible = ref(false)
const showRules = () => {
centerVisible.value = true
};
const closeCenter = () => {
centerVisible.value = false
};
const goPointsDetail = () => {
uni.navigateTo({ url: '/pages_app/myWelfareCard/exchange' })
};
const goMyWelfare = () => {
uni.navigateTo({ url: '/pages_app/myWelfare/myWelfare' })
}
</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 {
min-height: 100vh;
background-color: $bg-color;
.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;
}
}
.scrollbox{
position: fixed;
top: calc(#{$nav-height} + #{$segmented-height});
left: 30rpx;
right: 30rpx;
box-sizing: border-box;
bottom: $bottom-nav-height;
margin: 30rpx 0 ;
overflow-y: auto;
}
.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: relative;
height: 280rpx;
background: linear-gradient(180deg,#ff6a4a 0%, #e93b2d 100%);
border-bottom-left-radius: 40rpx;
border-bottom-right-radius: 40rpx;
@include shadow;
.banner-text{
position: absolute;
left: 48rpx;
top: 120rpx;
color: #fff;
.line1{font-size: 44rpx;font-weight: 600;}
.line2{font-size: 36rpx;margin-top: 12rpx;}
}
.help-btn{
position: absolute;
right: 40rpx;
top: 90rpx;
background: rgba(255,255,255,.95);
color: #e04835;
border-radius: 999rpx;
padding: 10rpx 24rpx;
font-size: 24rpx;
}
}
.card-wrapper{
margin: 24rpx 30rpx;
background: #fff;
border-radius: 16rpx;
@include shadow;
overflow: hidden;
.card-header{
background: linear-gradient(90deg,#ff7e4a,#ff4d2e);
color: #fff;
padding: 24rpx 28rpx;
font-size: 26rpx;
display: flex;
justify-content: space-between;
.time{opacity:.95}
}
.card-body{
padding: 34rpx 28rpx 40rpx;
.benefit-line{
font-size: 30rpx;
color: #333;
line-height: 56rpx;
.index{color:#333}
}
}
}
.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>