feat: 核销二维码组件

This commit is contained in:
2026-03-13 16:54:10 +08:00
parent bf3e5de86d
commit 70afd4d19f
4 changed files with 140 additions and 40 deletions

View File

@@ -1,22 +1,50 @@
<template>
<view
class="bg-white border-box rounded-12 flex flex-items-center flex-justify-center p-20 mb-12"
>
<Qrcode
:size="size"
:unit="unit"
:val="val"
:loadMake="true"
:onval="true"
/>
</view>
<uni-popup ref="popupRef" type="bottom" :safe-area="false" @maskClick="handleClose">
<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-items-center flex-justify-center p-20 mb-12 mx-12">
<Qrcode :size="props.size" :unit="props.unit" :val="props.val" :loadMake="true" :onval="true" />
</view>
</view>
</uni-popup>
</template>
<script setup>
import { defineProps } from "vue";
import Qrcode from "@/components/Qrcode/index.vue";
import { defineProps, defineEmits, onMounted } from "vue";
import { ref, watch } 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,
@@ -30,6 +58,43 @@ const props = defineProps({
default: "text",
},
});
// Events定义
const emit = defineEmits(["close", "update:modelValue"]);
// 弹窗引用
const popupRef = ref(null);
// 方法定义
const show = () => popupRef.value && popupRef.value.open();
const hide = () => popupRef.value && popupRef.value.close();
// 监听modelValue变化
watch(
() => props.modelValue,
(newVal) => {
if (newVal) {
show();
} else {
hide();
}
},
{ immediate: true }
);
const handleClose = () => {
emit("update:modelValue", false);
emit("close");
};
onMounted(() => {
props.val = props.orderData.orderId + '&' + props.selectedVoucher?.name;
});
</script>
<style scoped lang="scss"></style>
<style scoped lang="scss">
@import "./styles/index.scss";
</style>

View File

@@ -0,0 +1,9 @@
.refund-popup {
border-radius: 15px 15px 0 0;
padding-bottom: 40px;
}
.close {
top: 14px;
right: 12px;
}

View File

@@ -4,19 +4,39 @@
核销凭证列表
</text>
<view class="flex flex-items-center flex-justify-between py-12 border-bottom">
<view class="flex flex-items-center flex-justify-between py-12 border-bottom"
v-for="(item, index) in props.orderData.commodityPackageConfig" :key="item.name">
<view class="flex flex-col">
<text class="text-color-900 font-size-16">森系天幕租赁(3h)</text>
<text class="text-color-900 font-size-16">{{ item.name }}</text>
<view class="flex flex-row mt-8">
<view class="bg-F5F7FA text-color-600 font-size-12 p-4 rounded-4 mr-4">总计2份</view>
<view class="bg-theme-color-50 theme-color-500 font-size-12 p-4 rounded-4">2份可用</view>
<view class="bg-F5F7FA text-color-600 font-size-12 p-4 rounded-4 mr-4">总计{{ item.count }}{{item.unit}}</view>
<view class="bg-theme-color-50 theme-color-500 font-size-12 p-4 rounded-4">{{ item.count - item.writeOffCount }}{{item.unit}}可用</view>
</view>
</view>
<view class="flex flex-items-center bg-theme-color-500 px-14 py-8 rounded-8" @click="emit('click')">
<view class="flex flex-items-center bg-theme-color-500 px-14 py-8 rounded-8" @click="handleShowQrcode(item, index)">
<text class="color-white font-size-14">出示凭证</text>
</view>
</view>
</view>
</template>
</template>
<script setup>
import {defineProps, defineEmits } from "vue";
const emit = defineEmits(["selected"]);
const props = defineProps({
orderData: {
type: Object,
required: true,
default: () => ({}),
},
});
const handleShowQrcode = (item, index) => {
console.log("显示核销凭证二维码,凭证信息:", item);
emit("selected", { item, index });
};
</script>