546 lines
14 KiB
Vue
546 lines
14 KiB
Vue
<template>
|
||
<view>
|
||
<up-popup
|
||
:show="show"
|
||
bgColor="transparent"
|
||
:safeAreaInsetBottom="false"
|
||
@close="close"
|
||
mode="center"
|
||
>
|
||
<view class="container">
|
||
<view
|
||
class="content"
|
||
:style="contentStyle"
|
||
:class="`content${currentPage}`"
|
||
>
|
||
<!-- 顶部标题图 -->
|
||
<view class="top">
|
||
<image class="image" :src="imageList.gift" mode="widthFix"></image>
|
||
</view>
|
||
|
||
<!-- 优惠券列表 -->
|
||
<view class="list">
|
||
<view
|
||
class="item"
|
||
:style="kuangStyle"
|
||
v-for="(item, index) in couponList"
|
||
:key="index"
|
||
>
|
||
<!-- <view class="kuang">
|
||
<image
|
||
class="kuang-img"
|
||
:src="imageList.kuang"
|
||
mode="aspectFit"
|
||
></image>
|
||
</view> -->
|
||
<!-- 优惠券金额 -->
|
||
<view>
|
||
<template
|
||
v-if="
|
||
item.couponInfo.couponType == 3 ||
|
||
item.couponInfo.couponType == 1
|
||
"
|
||
>
|
||
<text class="big-title">{{
|
||
returnTitle(item.couponInfo)
|
||
}}</text>
|
||
<text class="u-m-l-12 small-title">
|
||
{{ returnSmallTitle(item.couponInfo) }}
|
||
</text>
|
||
</template>
|
||
<template v-else>
|
||
<text class="big-title" style="font-size: 48rpx">{{
|
||
returnTitle(item.couponInfo)
|
||
}}</text>
|
||
</template>
|
||
</view>
|
||
<!-- 优惠券名称与领取按钮 -->
|
||
<view class="u-flex u-row-between u-m-t-16 u-col-center">
|
||
<view>
|
||
<text class="title">{{ item.couponInfo.title }}</text>
|
||
<text class="num">x{{ item.num }}</text>
|
||
</view>
|
||
<button class="lingqu" @click="handleReceive(item)">
|
||
立即领取
|
||
</button>
|
||
</view>
|
||
<!-- 有效期(替换硬编码,用接口返回数据) -->
|
||
<view class="u-m-t-10 time">
|
||
有效期至:{{ formatDate(item.couponInfo.validStartTime) }}-{{
|
||
formatDate(item.couponInfo.validEndTime)
|
||
}}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 分页控制(左右箭头+页码) -->
|
||
<view
|
||
class="u-flex u-row-center u-m-t-16"
|
||
v-if="allCoupons.length > 3"
|
||
>
|
||
<!-- 左箭头:当前页>1可点击 -->
|
||
<view
|
||
@click="handlePrevPage"
|
||
class="page-arrow"
|
||
:class="{ disabled: currentPage === 1 }"
|
||
>
|
||
<up-icon
|
||
name="arrow-left"
|
||
size="12"
|
||
:color="currentPage === 1 ? '#999' : '#000'"
|
||
></up-icon>
|
||
</view>
|
||
<!-- 页码列表:点击切换+当前页高亮 -->
|
||
<view class="u-flex page-nums">
|
||
<view
|
||
v-for="(num, index) in pageNums"
|
||
:key="index"
|
||
class="item"
|
||
:class="{ active: currentPage === num }"
|
||
@click="handleClickPage(num)"
|
||
>
|
||
{{ num }}
|
||
</view>
|
||
</view>
|
||
<!-- 右箭头:当前页<总页数可点击 -->
|
||
<view
|
||
@click="handleNextPage"
|
||
class="page-arrow"
|
||
:class="{ disabled: currentPage === totalPages }"
|
||
>
|
||
<up-icon
|
||
name="arrow-right"
|
||
size="12"
|
||
:color="currentPage === totalPages ? '#999' : '#000'"
|
||
></up-icon>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部一键领取按钮 -->
|
||
<view class="btn-wrap" :class="{ 'u-m-t-18': allCoupons.length > 3 }">
|
||
<image
|
||
@click="handleReceiveAll"
|
||
class="btn-img"
|
||
:src="imageList.btn"
|
||
mode="widthFix"
|
||
></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</up-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import _ from "lodash";
|
||
import dayjs from "dayjs";
|
||
import { onMounted, ref, reactive, computed } from "vue";
|
||
import * as birthdayGiftApi from "@/common/api/market/birthdayGift.js";
|
||
|
||
// 1. 分页核心配置
|
||
const currentPage = ref(1); // 当前页码
|
||
const pageSize = ref(3); // 每页显示条数
|
||
const allCoupons = ref([]); // 存储全部优惠券(用于分页截取)
|
||
const couponList = ref([]); // 当前页优惠券列表
|
||
const pageNums = ref([]); // 页码数组(如[1,2,3])
|
||
const totalPages = computed(() => {
|
||
// 计算总页数:向上取整(如5条数据→2页)
|
||
return Math.ceil(allCoupons.value.length / pageSize.value);
|
||
});
|
||
|
||
// 2. 图片资源(修复bg2地址缺失的"g")
|
||
const imageList = reactive({
|
||
btn: "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/493b459f8c944057be72750c12c4cd1a.png",
|
||
gift: "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/112d2433378349b4a26ab311b8d3bac4.png",
|
||
kuang:
|
||
"https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/bb5e2d5ed73c455d9b6e9b4ac0e86192.png",
|
||
bg1: "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/847f9aea44d64b15b35caf8967f3d63f.png",
|
||
bg2: "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/2f704eef2e3d484d8862673131ae3989.png", // 修复:.pn→.png
|
||
bg3: "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/4/7ab43d1ef2fc490d80165d18795a93f3.png",
|
||
});
|
||
|
||
// 3. 背景图(随当前页切换)
|
||
const bgUrl = ref(imageList.bg1);
|
||
const contentStyle = computed(() => ({
|
||
backgroundImage: `url(${bgUrl.value})`,
|
||
backgroundSize: "100% 100%", // 确保背景图铺满容器
|
||
}));
|
||
const kuangStyle = computed(() => ({
|
||
backgroundImage: `url(${imageList.kuang})`,
|
||
}));
|
||
|
||
// 4. 弹窗状态与props
|
||
const show = ref(false);
|
||
const props = defineProps({
|
||
getMode: {
|
||
type: String,
|
||
default: "eat",
|
||
},
|
||
});
|
||
|
||
// ---------------------- 分页核心逻辑 ----------------------
|
||
/**
|
||
* 1. 生成页码数组(如总数据5条→[1,2])
|
||
*/
|
||
const generatePageNums = () => {
|
||
pageNums.value = Array.from({ length: totalPages.value }, (_, i) => i + 1);
|
||
};
|
||
|
||
/**
|
||
* 2. 更新当前页优惠券列表(根据当前页截取数据)
|
||
*/
|
||
const updateCouponList = () => {
|
||
const startIdx = (currentPage.value - 1) * pageSize.value;
|
||
const endIdx = startIdx + pageSize.value;
|
||
couponList.value = allCoupons.value.slice(startIdx, endIdx);
|
||
// 同步切换背景图(当前页对应bg1/bg2/bg3)
|
||
bgUrl.value = imageList[`bg${currentPage.value}`] || imageList.bg1;
|
||
};
|
||
|
||
/**
|
||
* 3. 上一页切换
|
||
*/
|
||
const handlePrevPage = () => {
|
||
if (currentPage.value > 1) {
|
||
currentPage.value--;
|
||
updateCouponList();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 4. 下一页切换
|
||
*/
|
||
const handleNextPage = () => {
|
||
if (currentPage.value < totalPages.value) {
|
||
currentPage.value++;
|
||
updateCouponList();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* 5. 点击页码切换
|
||
*/
|
||
const handleClickPage = (num) => {
|
||
currentPage.value = num;
|
||
updateCouponList();
|
||
};
|
||
|
||
// ---------------------- 数据与交互逻辑 ----------------------
|
||
/**
|
||
* 1. 格式化日期(YYYY.MM.DD)
|
||
*/
|
||
const formatDate = (dateStr) => {
|
||
return dateStr ? dayjs(dateStr).format("YYYY.MM.DD") : ""; // 默认兜底日期
|
||
};
|
||
|
||
/**
|
||
* 2. 单个优惠券领取
|
||
*/
|
||
const handleReceive = async (item) => {
|
||
close();
|
||
uni.showToast({ title: "领取成功!去「我的优惠券」查看", icon: "none" });
|
||
};
|
||
|
||
/**
|
||
* 3. 底部一键领取(领取当前页所有优惠券)
|
||
*/
|
||
const handleReceiveAll = async () => {
|
||
if (couponList.value.length === 0) {
|
||
uni.showToast({ title: "当前页无优惠券可领", icon: "none" });
|
||
return;
|
||
}
|
||
close();
|
||
uni.showToast({ title: "领取成功!去「我的优惠券」查看", icon: "none" });
|
||
};
|
||
|
||
/**
|
||
* 4. 初始化获取优惠券数据
|
||
*/
|
||
const getCouponPopupAjax = async () => {
|
||
try {
|
||
const shopId = uni.cache.get("shopId");
|
||
const res = await birthdayGiftApi.config({ shopId });
|
||
if (res&&res.length) {
|
||
// 处理有效期格式(固定有效期规则)
|
||
allCoupons.value = res.map((item) => {
|
||
if (item.validType === "fixed") {
|
||
item.validStartTime = dayjs()
|
||
.add(item.daysToTakeEffect, "day")
|
||
.format("YYYY-MM-DD HH:mm:ss");
|
||
item.validEndTime = dayjs()
|
||
.add(+item.daysToTakeEffect + +item.validDays, "day")
|
||
.format("YYYY-MM-DD HH:mm:ss");
|
||
}
|
||
return item;
|
||
});
|
||
// 初始化分页:生成页码→更新列表→显示弹窗
|
||
generatePageNums();
|
||
updateCouponList();
|
||
show.value = true;
|
||
}else{
|
||
close();
|
||
}
|
||
} catch (error) {
|
||
console.error("获取优惠券失败:", error);
|
||
}
|
||
};
|
||
|
||
// 页面挂载时初始化
|
||
onMounted(() => {
|
||
getCouponPopupAjax();
|
||
});
|
||
|
||
function returnTitle(coupon) {
|
||
if (coupon.couponType == 1) {
|
||
return `¥${coupon.discountAmount}`;
|
||
}
|
||
if (coupon.couponType == 2) {
|
||
return `商品兑换券`;
|
||
}
|
||
if (coupon.couponType == 3) {
|
||
const discountRate = coupon.discountRate / 10;
|
||
return `${discountRate}折券`;
|
||
}
|
||
if (coupon.couponType == 4) {
|
||
return `第二件半价券`;
|
||
}
|
||
if (coupon.couponType == 6) {
|
||
return `买一送一券`;
|
||
}
|
||
}
|
||
|
||
function returnSmallTitle(coupon) {
|
||
if (coupon.couponType == 1) {
|
||
return `满${coupon.fullAmount || 0}可用`;
|
||
}
|
||
if (coupon.couponType == 3) {
|
||
return `满${coupon.fullAmount || 0}可用`;
|
||
}
|
||
}
|
||
|
||
const emit = defineEmits(["close"]);
|
||
|
||
function close() {
|
||
show.value = false;
|
||
emit("close");
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
// 基础容器样式
|
||
.container {
|
||
width: 100vw;
|
||
height: 100vh;
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 52rpx;
|
||
|
||
.content {
|
||
width: 100%;
|
||
position: relative;
|
||
margin: auto;
|
||
min-height: 836rpx;
|
||
padding: 0 28rpx 62rpx;
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
|
||
// 分页箭头样式(添加禁用态)
|
||
.page-arrow {
|
||
cursor: pointer;
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
box-sizing: border-box;
|
||
color: #000;
|
||
background-color: #fff;
|
||
border: 1px solid #d9d9d9;
|
||
font-size: 14px;
|
||
line-height: 60rpx;
|
||
padding: 0 14rpx;
|
||
border-radius: 4rpx;
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
margin: 0 16rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-content: center;
|
||
&.disabled {
|
||
cursor: not-allowed;
|
||
}
|
||
}
|
||
|
||
// 页码样式(当前页高亮)
|
||
.page-nums {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
.item {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
box-sizing: border-box;
|
||
color: #000;
|
||
background-color: #fff;
|
||
border: 1px solid #d9d9d9;
|
||
font-size: 14px;
|
||
line-height: 64rpx;
|
||
padding: 0 4rpx;
|
||
border-radius: 4rpx;
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
text-align: center;
|
||
&.active {
|
||
border-color: #1890ff;
|
||
color: #1890ff;
|
||
font-weight: 500;
|
||
}
|
||
&:active:not(.active) {
|
||
background-color: #f5f5f5;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 底部按钮容器
|
||
.btn-wrap {
|
||
margin: 28rpx 0 0;
|
||
margin-top: 30rpx;
|
||
.btn-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
cursor: pointer;
|
||
&:active {
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 顶部标题图
|
||
.top {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 0;
|
||
z-index: 1;
|
||
.image {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
// 优惠券列表样式
|
||
.list {
|
||
margin-top: 332rpx;
|
||
position: relative;
|
||
z-index: 2;
|
||
.item {
|
||
position: relative;
|
||
padding: 32rpx 12rpx 36rpx 36rpx;
|
||
background-size: 100% 100%;
|
||
background-position: center;
|
||
overflow: hidden;
|
||
margin-top: 36rpx;
|
||
box-sizing: border-box;
|
||
|
||
// 优惠券边框图
|
||
.kuang {
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 0;
|
||
bottom: 0;
|
||
z-index: -1;
|
||
.kuang-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
// 金额样式
|
||
.big-title {
|
||
color: #f05a82;
|
||
font-size: 36px;
|
||
font-weight: 600;
|
||
}
|
||
.small-title {
|
||
color: #f05a82;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
// 名称与数量
|
||
.title {
|
||
color: #333;
|
||
font-size: 16px;
|
||
font-weight: 400;
|
||
padding-bottom: 10rpx;
|
||
border-bottom: 4rpx dashed #fd8293;
|
||
}
|
||
.num {
|
||
color: #f05a82;
|
||
font-size: 20px;
|
||
font-weight: 400;
|
||
line-height: 22px;
|
||
margin-left: 16rpx;
|
||
}
|
||
|
||
// 有效期
|
||
.time {
|
||
color: #666; // 调整颜色更柔和
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 领取按钮样式
|
||
.lingqu {
|
||
padding: 12rpx 20rpx; // 加宽内边距,点击区域更大
|
||
border-radius: 14rpx;
|
||
background: #fd8293;
|
||
color: #fff;
|
||
font-size: 28rpx;
|
||
font-weight: 400;
|
||
line-height: 1;
|
||
border: none;
|
||
outline: none;
|
||
margin: 0;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
&:active {
|
||
background: #f07080; // 点击深色反馈
|
||
}
|
||
}
|
||
|
||
// 工具类样式(补充缺失的flex基础样式)
|
||
.u-flex {
|
||
display: flex;
|
||
}
|
||
.u-row-center {
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.u-row-between {
|
||
justify-content: space-between;
|
||
}
|
||
.u-m-t-10 {
|
||
margin-top: 10rpx;
|
||
}
|
||
.u-m-t-16 {
|
||
margin-top: 16rpx;
|
||
}
|
||
.u-m-t-20 {
|
||
margin-top: 20rpx;
|
||
}
|
||
.u-m-t-30 {
|
||
margin-top: 30rpx;
|
||
}
|
||
.u-m-x-16 {
|
||
margin-left: 16rpx;
|
||
margin-right: 16rpx;
|
||
}
|
||
.u-m-l-12 {
|
||
margin-left: 12rpx;
|
||
}
|
||
</style> |