You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
10 KiB

2 months ago
<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">
<canvas canvas-id="qrcode" class="qr-code"></canvas>
</view>
<!-- 兑换码 -->
<view class="exchange-code">
<text class="code-label">兑换码</text>
<text class="code-value">{{ exchangeCode }}</text>
<view class="copy-btn" @click="copyCode">
<uni-icons type="copy" size="16" color="#667eea" />
<text>复制</text>
</view>
</view>
</view>
</view>
<!-- 商品信息 -->
<view class="goods-section">
<view class="section-title">
<text>商品信息</text>
</view>
<view class="goods-card">
<image class="goods-image" :src="goodsInfo.image" 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 selectedSpecs"
:key="index"
>
<text class="spec-label">{{ index + 1 }}份规格</text>
<text class="spec-value">{{ spec.selectedSpec }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 预约信息 -->
<view class="reservation-section" v-if="selectedDate">
<view class="section-title">
<text>预约信息</text>
</view>
<view class="reservation-card">
<view class="reservation-item">
<text class="reservation-label">预约日期</text>
<text class="reservation-value">{{ selectedDate }}</text>
</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>
</view>
<view class="instruction-item">
<text class="instruction-text"
>2. 出示此页面或提供兑换码给工作人员</text
>
</view>
<view class="instruction-item">
<text class="instruction-text">3. 核销后商品不可退换</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: "WO202412250001",
exchangeCode: "EX8A9B2C3D",
goodsInfo: {
name: "精品咖啡体验券",
image: "https://via.placeholder.com/300x200/4A90E2/FFFFFF?text=Coffee",
description: "享受一杯精心调制的手冲咖啡,感受咖啡豆的独特香气",
},
selectedSpecs: {
size: "大杯",
type: "美式咖啡",
temperature: "热饮",
},
reservationDate: "2024-12-28 14:30",
};
},
onLoad(options) {
// 接收页面参数
if (options.orderId) {
this.orderId = options.orderId;
this.generateExchangeCode();
}
if (options.goodsInfo) {
this.goodsInfo = JSON.parse(decodeURIComponent(options.goodsInfo));
}
if (options.specifications) {
this.selectedSpecs = JSON.parse(
decodeURIComponent(options.specifications)
);
}
if (options.selectedDate) {
this.selectedDate = options.selectedDate;
}
},
onReady() {
// 生成二维码
this.generateQRCode();
},
methods: {
// 生成兑换码
generateExchangeCode() {
// 生成8位随机兑换码
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let code = "";
for (let i = 0; i < 8; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}
this.exchangeCode = code;
},
// 生成二维码
generateQRCode() {
const qrData = JSON.stringify({
orderId: this.orderId,
exchangeCode: this.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.exchangeCode,
success: () => {
uni.showToast({
title: "兑换码已复制",
icon: "success",
});
},
});
},
// 取消预约
cancelReservation() {
uni.showModal({
title: "确认取消",
content: "确定要取消此次预约吗?取消后将无法恢复。",
success: (res) => {
if (res.confirm) {
this.performCancelReservation();
}
},
});
},
// 执行取消预约
performCancelReservation() {
uni.showLoading({
title: "取消中...",
});
this.Post(
{
orderId: this.orderId,
},
"/framework/order/cancel",
"DES"
)
.then((res) => {
uni.hideLoading();
if (res.code == 200) {
uni.showToast({
title: "取消成功",
icon: "success",
});
setTimeout(() => {
uni.redirectTo({
url: "/subPackages/orderQy/list",
});
}, 1500);
} 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;
}
.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: 200rpx;
height: 200rpx;
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;
}
.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;
}
.bottom-space {
height: 120rpx;
}
// 底部操作区域
.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>