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.
487 lines
10 KiB
487 lines
10 KiB
<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>
|
|
|