Files
cashier_wx/components/birthday-modal.vue

545 lines
14 KiB
Vue
Raw 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>
<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">
<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;
&: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>