|
|
|
<template>
|
|
|
|
<view class="write-off-container">
|
|
|
|
<scroll-view class="content-scroll" scroll-y>
|
|
|
|
<!-- 核销码展示区域 -->
|
|
|
|
<view class="code-section">
|
|
|
|
<view class="section-title">
|
|
|
|
<text>核销码</text>
|
|
|
|
</view>
|
|
|
|
<view class="code-card">
|
|
|
|
<!-- 二维码 -->
|
|
|
|
<view class="qr-code-container">
|
|
|
|
<img :src="goodsInfo.orderVerification.qrCodeUrl" class="qr-code" />
|
|
|
|
<!-- <canvas canvas-id="qrcode" class="qr-code"></canvas> -->
|
|
|
|
</view>
|
|
|
|
<!-- 兑换码 -->
|
|
|
|
<view class="exchange-code">
|
|
|
|
<text class="code-label">兑换码</text>
|
|
|
|
<text class="code-value">{{
|
|
|
|
(goodsInfo.orderVerification &&
|
|
|
|
goodsInfo.orderVerification.verifyCode) ||
|
|
|
|
""
|
|
|
|
}}</text>
|
|
|
|
<view class="copy-btn" @click="copyCode">
|
|
|
|
<uni-icons type="copy" size="16" color="#667eea" />
|
|
|
|
<text>复制</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 预约信息 -->
|
|
|
|
<view class="reservation-section" v-if="goodsInfo.reservationTime">
|
|
|
|
<view class="section-title">
|
|
|
|
<text>预约信息</text>
|
|
|
|
</view>
|
|
|
|
<view class="reservation-card">
|
|
|
|
<view class="reservation-item">
|
|
|
|
<text class="reservation-label">预约核销日期</text>
|
|
|
|
<text class="reservation-value">{{
|
|
|
|
goodsInfo.reservationTime
|
|
|
|
}}</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 商品信息 -->
|
|
|
|
<view class="goods-section">
|
|
|
|
<view class="section-title">
|
|
|
|
<text>商品信息</text>
|
|
|
|
</view>
|
|
|
|
<view class="goods-card">
|
|
|
|
<image
|
|
|
|
class="goods-image"
|
|
|
|
:src="goodsInfo.goodsImage.split(',')[0]"
|
|
|
|
mode="aspectFill"
|
|
|
|
/>
|
|
|
|
<view class="goods-info">
|
|
|
|
<text class="goods-name">{{ goodsInfo.goodsName || "--" }}</text>
|
|
|
|
<view class="specs-info">
|
|
|
|
<view
|
|
|
|
class="spec-item"
|
|
|
|
v-for="(spec, index) in goodsInfo.orderReservationDetails"
|
|
|
|
:key="index"
|
|
|
|
>
|
|
|
|
<text class="spec-label">第{{ index + 1 }}份规格:</text>
|
|
|
|
<text class="spec-value"
|
|
|
|
>{{ spec.specValueOne }}/{{ spec.specValueTwo }}</text
|
|
|
|
>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 使用说明 -->
|
|
|
|
<view class="instruction-section">
|
|
|
|
<view class="section-title">
|
|
|
|
<text>使用说明</text>
|
|
|
|
</view>
|
|
|
|
<view class="instruction-card">
|
|
|
|
<view class="instruction-item">
|
|
|
|
<text class="instruction-text"
|
|
|
|
>1.
|
|
|
|
<text class="expiry-highlight"
|
|
|
|
>有效期至{{
|
|
|
|
goodsInfo.expireTime || ""
|
|
|
|
}},到期后将自动退款至原支付账户</text
|
|
|
|
></text
|
|
|
|
>
|
|
|
|
</view>
|
|
|
|
<view class="instruction-item">
|
|
|
|
<text class="instruction-text">2. 请在预约时间内到店核销</text>
|
|
|
|
</view>
|
|
|
|
<view class="instruction-item">
|
|
|
|
<text class="instruction-text"
|
|
|
|
>3. 出示此页面或提供兑换码给工作人员</text
|
|
|
|
>
|
|
|
|
</view>
|
|
|
|
<view class="instruction-item">
|
|
|
|
<text class="instruction-text">4. 核销后商品不可退换</text>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
|
|
|
|
<view class="bottom-space"></view>
|
|
|
|
</scroll-view>
|
|
|
|
|
|
|
|
<!-- 底部操作区域 -->
|
|
|
|
<view class="bottom-actions">
|
|
|
|
<button class="cancel-btn" @click="cancelReservation">取消预约</button>
|
|
|
|
</view>
|
|
|
|
</view>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import QRCode from "@/static/js/weapp-qrcode.js";
|
|
|
|
|
|
|
|
export default {
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
orderId: "",
|
|
|
|
goodsInfo: {},
|
|
|
|
};
|
|
|
|
},
|
|
|
|
|
|
|
|
onLoad(options) {
|
|
|
|
// 接收页面参数
|
|
|
|
if (options.orderChildId) {
|
|
|
|
this.orderChildId = options.orderChildId;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onShow() {
|
|
|
|
this.generateExchangeCode();
|
|
|
|
},
|
|
|
|
|
|
|
|
onReady() {
|
|
|
|
// 生成二维码
|
|
|
|
this.generateQRCode();
|
|
|
|
},
|
|
|
|
|
|
|
|
methods: {
|
|
|
|
generateExchangeCode() {
|
|
|
|
this.Post(
|
|
|
|
{
|
|
|
|
orderChildId: this.orderChildId,
|
|
|
|
},
|
|
|
|
"/framework/orderReservation/getCanByOrderChildId",
|
|
|
|
"DES"
|
|
|
|
).then((res) => {
|
|
|
|
if (res.code == 200) {
|
|
|
|
this.goodsInfo = res.data;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// 生成二维码
|
|
|
|
generateQRCode() {
|
|
|
|
const qrData = JSON.stringify({
|
|
|
|
orderId: this.orderId,
|
|
|
|
exchangeCode: this.goodsInfo.exchangeCode,
|
|
|
|
type: "writeOff",
|
|
|
|
});
|
|
|
|
|
|
|
|
// 使用weapp-qrcode生成二维码
|
|
|
|
QRCode({
|
|
|
|
canvasId: "qrcode",
|
|
|
|
text: qrData,
|
|
|
|
width: 200,
|
|
|
|
height: 200,
|
|
|
|
colorDark: "#000000",
|
|
|
|
colorLight: "#ffffff",
|
|
|
|
correctLevel: QRCode.CorrectLevel.M,
|
|
|
|
component: this,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// 复制兑换码
|
|
|
|
copyCode() {
|
|
|
|
uni.setClipboardData({
|
|
|
|
data: this.goodsInfo.orderVerification.verifyCode,
|
|
|
|
success: () => {
|
|
|
|
uni.showToast({
|
|
|
|
title: "兑换码已复制",
|
|
|
|
icon: "success",
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// 取消预约
|
|
|
|
cancelReservation() {
|
|
|
|
uni.showModal({
|
|
|
|
title: "确认取消",
|
|
|
|
content: "确定要取消此次预约吗?取消后将无法恢复。",
|
|
|
|
success: (res) => {
|
|
|
|
if (res.confirm) {
|
|
|
|
this.performCancelReservation();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// 执行取消预约
|
|
|
|
performCancelReservation() {
|
|
|
|
uni.showLoading({
|
|
|
|
title: "取消中...",
|
|
|
|
});
|
|
|
|
|
|
|
|
this.Post(
|
|
|
|
{
|
|
|
|
orderChildId: this.orderChildId,
|
|
|
|
},
|
|
|
|
"/framework/orderReservation/cancel",
|
|
|
|
"DES"
|
|
|
|
)
|
|
|
|
.then((res) => {
|
|
|
|
uni.hideLoading();
|
|
|
|
if (res.code == 200) {
|
|
|
|
uni.showToast({
|
|
|
|
title: "取消成功",
|
|
|
|
icon: "success",
|
|
|
|
});
|
|
|
|
setTimeout(() => {
|
|
|
|
uni.navigateBack();
|
|
|
|
}, 800);
|
|
|
|
} else {
|
|
|
|
uni.showToast({
|
|
|
|
title: res.msg || "取消失败",
|
|
|
|
icon: "none",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
uni.hideLoading();
|
|
|
|
uni.showToast({
|
|
|
|
title: "网络错误",
|
|
|
|
icon: "none",
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
// 主题色彩变量
|
|
|
|
$primary-color: #667eea;
|
|
|
|
$secondary-color: #f8f9fa;
|
|
|
|
$text-primary: #2d3748;
|
|
|
|
$text-secondary: #718096;
|
|
|
|
$text-muted: #a0aec0;
|
|
|
|
$border-color: #e2e8f0;
|
|
|
|
$success-color: #48bb78;
|
|
|
|
$warning-color: #ed8936;
|
|
|
|
$danger-color: #f56565;
|
|
|
|
$bg-light: #f7fafc;
|
|
|
|
|
|
|
|
.write-off-container {
|
|
|
|
height: 100vh;
|
|
|
|
background-color: $bg-light;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
|
|
|
|
|
|
|
.content-scroll {
|
|
|
|
flex: 1;
|
|
|
|
padding: 20rpx;
|
|
|
|
width: 710rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
font-size: 28rpx;
|
|
|
|
color: $text-primary;
|
|
|
|
font-weight: 600;
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 核销码区域
|
|
|
|
.code-section {
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.code-card {
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
padding: 40rpx;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
gap: 30rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.qr-code-container {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.qr-code {
|
|
|
|
width: 250rpx;
|
|
|
|
height: 250rpx;
|
|
|
|
border: 2rpx solid $border-color;
|
|
|
|
border-radius: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.exchange-code {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
gap: 12rpx;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.code-label {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: $text-secondary;
|
|
|
|
}
|
|
|
|
|
|
|
|
.code-value {
|
|
|
|
font-size: 36rpx;
|
|
|
|
color: $text-primary;
|
|
|
|
font-weight: 600;
|
|
|
|
font-family: "SF Mono", "Monaco", "Cascadia Code", monospace;
|
|
|
|
letter-spacing: 4rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.copy-btn {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8rpx;
|
|
|
|
padding: 12rpx 24rpx;
|
|
|
|
background-color: rgba(102, 126, 234, 0.1);
|
|
|
|
border-radius: 20rpx;
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
background-color: rgba(102, 126, 234, 0.2);
|
|
|
|
transform: scale(0.95);
|
|
|
|
}
|
|
|
|
|
|
|
|
text {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: $primary-color;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 商品信息
|
|
|
|
.goods-section {
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-card {
|
|
|
|
display: flex;
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
padding: 24rpx;
|
|
|
|
gap: 20rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-image {
|
|
|
|
width: 120rpx;
|
|
|
|
height: 120rpx;
|
|
|
|
border-radius: 12rpx;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-info {
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 12rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-name {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: $text-primary;
|
|
|
|
font-weight: 600;
|
|
|
|
line-height: 1.4;
|
|
|
|
}
|
|
|
|
|
|
|
|
.specs-info {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.spec-item {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
gap: 8rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.spec-label {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: $text-secondary;
|
|
|
|
}
|
|
|
|
|
|
|
|
.spec-value {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: $text-primary;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 预约信息
|
|
|
|
.reservation-section {
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.reservation-card {
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
padding: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.reservation-item {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
|
|
|
padding: 8rpx 0;
|
|
|
|
|
|
|
|
&:not(:last-child) {
|
|
|
|
border-bottom: 1rpx solid $border-color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.reservation-label {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: $text-secondary;
|
|
|
|
}
|
|
|
|
|
|
|
|
.reservation-value {
|
|
|
|
font-size: 26rpx;
|
|
|
|
color: $text-primary;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 使用说明
|
|
|
|
.instruction-section {
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.instruction-card {
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-radius: 16rpx;
|
|
|
|
padding: 24rpx;
|
|
|
|
}
|
|
|
|
|
|
|
|
.instruction-item {
|
|
|
|
padding: 12rpx 0;
|
|
|
|
border-bottom: 1rpx solid $border-color;
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.instruction-text {
|
|
|
|
font-size: 24rpx;
|
|
|
|
color: $text-secondary;
|
|
|
|
line-height: 1.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
.expiry-highlight {
|
|
|
|
color: #ff6b35;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
|
|
|
|
.bottom-space {
|
|
|
|
height: 120rpx;
|
|
|
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
|
|
|
box-sizing: content-box;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 底部操作区域
|
|
|
|
.bottom-actions {
|
|
|
|
position: fixed;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
padding: 24rpx;
|
|
|
|
background-color: #ffffff;
|
|
|
|
border-top: 1rpx solid $border-color;
|
|
|
|
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.04);
|
|
|
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
|
|
|
z-index: 100;
|
|
|
|
.cancel-btn {
|
|
|
|
width: 100%;
|
|
|
|
background-color: $danger-color;
|
|
|
|
color: #ffffff;
|
|
|
|
border: none;
|
|
|
|
border-radius: 24rpx;
|
|
|
|
padding: 16rpx;
|
|
|
|
font-size: 28rpx;
|
|
|
|
font-weight: 600;
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
transform: scale(0.95);
|
|
|
|
background-color: rgba(245, 101, 101, 0.8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|