242 lines
7.3 KiB
Vue
242 lines
7.3 KiB
Vue
<template>
|
||
<uni-popup
|
||
ref="popupRef"
|
||
type="bottom"
|
||
:safe-area="false"
|
||
@maskClick="handleClose"
|
||
@change="handlePopupChange"
|
||
>
|
||
<view class="refund-popup bg-F5F7FA border-box">
|
||
<view class="border-box flex flex-items-center justify-between pt-12 pb-12 relative">
|
||
<view class="flex flex-col flex-items-center flex-full ">
|
||
<view class="flex-full font-size-16 text-color-900 text-center">核销凭证</view>
|
||
<view class="flex-full font-size-12 text-color-600 text-center mt-4">请向工作人员出示此码</view>
|
||
</view>
|
||
<!-- 关闭按钮 -->
|
||
<uni-icons class="close absolute" type="close" size="20" color="#CACFD8" @click="handleClose" />
|
||
</view>
|
||
|
||
<view class="bg-white border-box rounded-12 flex flex-col flex-items-center flex-justify-center p-12 mb-12 mx-12">
|
||
|
||
<view class="flex w-full flex-row flex-items-center flex-justify-between py-4">
|
||
<view >
|
||
<view class="font-size-16 font-500 color-000 line-height-24 ellipsis-1">
|
||
{{ selectedVoucher.name }}
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="selectedVoucher" class="flex flex-row">
|
||
<view class="bg-F5F7FA text-color-600 font-size-12 p-4 rounded-4 mr-4">总计{{ selectedVoucher.count }}{{ selectedVoucher.unit }}
|
||
</view>
|
||
<view class="bg-theme-color-50 theme-color-500 font-size-12 p-4 rounded-4">剩{{ selectedVoucher.count - selectedVoucher.writeOffCount }}{{ selectedVoucher.unit }}可用</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="flex flex-col w-full flex-items-center flex-justify-center border-box rounded-8 border pt-16 pb-32 mt-12">
|
||
<view class="flex flex-row flex-justify-between border-box w-full px-12">
|
||
<view class="bg-theme-color-50 theme-color-500 font-size-14 px-12 line-height-24 rounded-12">凭证{{ selectedVoucherList.length > 1 ? currentVoucherIndex + 1 : '' }}</view>
|
||
<view class="text-color-500 font-size-14 px-12 line-height-24 rounded-12">此码仅可核销{{ selectedVoucher.count - selectedVoucher.writeOffCount }}份</view>
|
||
</view>
|
||
|
||
<view class="flex flex-items-center flex-justify-center mt-20 p-20 rounded-12 border borderColor"
|
||
:style="{ borderColor: selectedVoucher?.color }">
|
||
<Qrcode v-if="showQrcode" :size="props.size" :unit="props.unit" :val="qrcodeVal" :loadMake="true"
|
||
:onval="true" />
|
||
</view>
|
||
|
||
<view v-if="false" class="mt-20 bg-theme-color-50 theme-color-500 font-size-14 px-12 line-height-24 rounded-12">
|
||
{{ selectedVoucher.name }}
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="selectedVoucherList.length > 1" class="flex flex-row w-full flex-items-center flex-justify-between mt-16 mb-24">
|
||
<view class="actions-btn" @click.stop="upAction">
|
||
<uni-icons type="left" size="16" color="#171717" />
|
||
</view>
|
||
|
||
<view class="flex flex-col">
|
||
<view class="flex flex-row flex-justify-center flex-items-center">
|
||
<view class="theme-color-500 font-size-16">{{ currentVoucherIndex + 1 }}</view>
|
||
<view class="text-color-600 font-size-12">/{{ selectedVoucherList.length }}</view>
|
||
</view>
|
||
|
||
<view class="text-color-600 font-size-14">扫码后点击下一张</view>
|
||
</view>
|
||
|
||
<view class="actions-btn" @click.stop="downAction">
|
||
<uni-icons type="right" size="16" color="#171717" />
|
||
</view>
|
||
</view>
|
||
<view v-else class="mb-24"></view>
|
||
</view>
|
||
|
||
</view>
|
||
|
||
</uni-popup>
|
||
</template>
|
||
|
||
<script setup>
|
||
import Qrcode from "@/components/Qrcode/index.vue";
|
||
import { defineProps, defineEmits } from "vue";
|
||
import { ref, watch, computed, nextTick } from "vue";
|
||
|
||
const props = defineProps({
|
||
// 弹窗显示状态
|
||
modelValue: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
orderData: {
|
||
type: Object,
|
||
required: true,
|
||
default: () => ({}),
|
||
},
|
||
selectedVoucher: {
|
||
type: Object,
|
||
required: false,
|
||
default: null,
|
||
},
|
||
selectedVoucherIndex: {
|
||
type: Number,
|
||
required: false,
|
||
default: 0,
|
||
},
|
||
size: {
|
||
type: Number,
|
||
default: 132,
|
||
},
|
||
unit: {
|
||
type: String,
|
||
default: "px",
|
||
},
|
||
});
|
||
|
||
// Events定义
|
||
const emit = defineEmits(["close", "update:modelValue", "update:selectedVoucherIndex"]);
|
||
|
||
// 弹窗引用
|
||
const popupRef = ref(null);
|
||
|
||
// 控制二维码渲染
|
||
const showQrcode = ref(false);
|
||
|
||
// 当前选择的凭证索引
|
||
const currentVoucherIndex = ref(props.selectedVoucherIndex || 0);
|
||
|
||
const selectedVoucherList = computed(() => {
|
||
const list = props.orderData?.commodityPackageConfig || [];
|
||
if (!Array.isArray(list)) return [];
|
||
return list.filter((item) => item?.packageStatus === 0);
|
||
});
|
||
|
||
// 二维码内容
|
||
const selectedVoucher = computed(() => {
|
||
const list = selectedVoucherList.value || [];
|
||
if (!list.length) return null;
|
||
const idx = Math.min(Math.max(Number(currentVoucherIndex.value || 0), 0), list.length - 1);
|
||
return list[idx] || null;
|
||
});
|
||
|
||
const qrcodeVal = computed(() => {
|
||
const orderId = props.orderData?.orderId || "";
|
||
const voucherName = selectedVoucher.value?.name || "";
|
||
return orderId ? `${orderId}&${voucherName}` : "";
|
||
});
|
||
|
||
// 方法定义
|
||
const show = () => popupRef.value && popupRef.value.open();
|
||
const hide = () => popupRef.value && popupRef.value.close();
|
||
|
||
const handlePopupChange = ({ show }) => {
|
||
// popup 真实打开后再渲染二维码,避免 canvas 尺寸为 0 报错
|
||
if (show) {
|
||
nextTick(() => {
|
||
showQrcode.value = true;
|
||
});
|
||
} else {
|
||
showQrcode.value = false;
|
||
}
|
||
};
|
||
|
||
// 监听modelValue变化
|
||
watch(
|
||
() => props.modelValue,
|
||
(newVal) => {
|
||
if (newVal) {
|
||
showQrcode.value = false;
|
||
show();
|
||
} else {
|
||
showQrcode.value = false;
|
||
hide();
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
// 同步外部 prop -> 内部 index(初始化/外部变更)
|
||
watch(
|
||
() => props.selectedVoucherIndex,
|
||
(newIdx) => {
|
||
const len = selectedVoucherList.value.length;
|
||
let idx = Number(newIdx || 0);
|
||
if (len && idx >= len) idx = 0;
|
||
currentVoucherIndex.value = idx;
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
// 当可用凭证列表变化时,确保 currentVoucherIndex 不越界
|
||
watch(
|
||
selectedVoucherList,
|
||
(list) => {
|
||
const len = list.length;
|
||
if (len === 0) {
|
||
if (currentVoucherIndex.value !== 0) {
|
||
currentVoucherIndex.value = 0;
|
||
}
|
||
return;
|
||
}
|
||
if (currentVoucherIndex.value >= len) {
|
||
currentVoucherIndex.value = 0;
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
|
||
// 当内部索引变化时,通知父组件(避免无用循环)
|
||
watch(
|
||
() => currentVoucherIndex.value,
|
||
(val, oldVal) => {
|
||
if (val !== props.selectedVoucherIndex) {
|
||
emit("update:selectedVoucherIndex", val);
|
||
}
|
||
}
|
||
);
|
||
|
||
const handleClose = () => {
|
||
emit("update:modelValue", false);
|
||
emit("close");
|
||
};
|
||
|
||
const upAction = () => {
|
||
const len = selectedVoucherList.value.length;
|
||
if (!len) return;
|
||
let idx = Number(currentVoucherIndex.value || 0) - 1;
|
||
if (idx < 0) idx = len - 1;
|
||
currentVoucherIndex.value = idx;
|
||
};
|
||
|
||
const downAction = () => {
|
||
const len = selectedVoucherList.value.length;
|
||
if (!len) return;
|
||
let idx = Number(currentVoucherIndex.value || 0) + 1;
|
||
if (idx >= len) idx = 0;
|
||
currentVoucherIndex.value = idx;
|
||
};
|
||
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import "./styles/index.scss";
|
||
</style>
|