2025-12-19 12:27:55 +00:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="service-records-page">
|
|
|
|
|
|
<!-- 头部区域 -->
|
|
|
|
|
|
<NavHeader title="服务记录" />
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Tab 切换 -->
|
|
|
|
|
|
<view class="tab-bar">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="tab-item"
|
|
|
|
|
|
:class="{ active: currentTab === 'pending_payment' }"
|
|
|
|
|
|
@click="switchTab('pending_payment')"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text class="tab-text">待支付</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="tab-item"
|
|
|
|
|
|
:class="{ active: currentTab === 'pending_verification' }"
|
|
|
|
|
|
@click="switchTab('pending_verification')"
|
|
|
|
|
|
>
|
2026-03-04 15:30:04 +00:00
|
|
|
|
<text class="tab-text">已完成</text>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="tab-item"
|
2026-03-04 15:30:04 +00:00
|
|
|
|
:class="{ active: currentTab === 'chargeback' }"
|
|
|
|
|
|
@click="switchTab('chargeback')"
|
2025-12-19 12:27:55 +00:00
|
|
|
|
>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<text class="tab-text">已退款</text>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="tab-item"
|
|
|
|
|
|
:class="{ active: currentTab === 'cancelled' }"
|
|
|
|
|
|
@click="switchTab('cancelled')"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text class="tab-text">已取消</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 列表内容 -->
|
|
|
|
|
|
<scroll-view
|
|
|
|
|
|
class="record-list"
|
|
|
|
|
|
scroll-y="true"
|
|
|
|
|
|
:refresher-enabled="true"
|
|
|
|
|
|
:refresher-triggered="refreshing"
|
|
|
|
|
|
@refresherrefresh="handleRefresh"
|
|
|
|
|
|
@scrolltolower="handleLoadMore"
|
|
|
|
|
|
:lower-threshold="100"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- 空数据提示 -->
|
|
|
|
|
|
<view class="empty-state" v-if="!loading && currentList.length === 0">
|
|
|
|
|
|
<image
|
|
|
|
|
|
class="empty-icon"
|
|
|
|
|
|
src="/static/home/entry_icon.png"
|
|
|
|
|
|
mode="aspectFit"
|
|
|
|
|
|
></image>
|
|
|
|
|
|
<text class="empty-text">暂无{{ getTabLabel() }}记录</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 记录列表项 -->
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="record-item"
|
|
|
|
|
|
v-for="(item, index) in currentList"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<!-- 头部:门店 + 状态 -->
|
2025-12-19 12:27:55 +00:00
|
|
|
|
<view class="record-header">
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<view class="record-shop-row">
|
|
|
|
|
|
<text class="shop-name">{{ item.shopName }}</text>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
<view class="status-badge" :class="getStatusClass(item.status)">
|
|
|
|
|
|
<text class="status-text">{{ getStatusText(item.status) }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<text class="record-time">{{ formatTime(item.createTime) }}</text>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
|
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<!-- 中部:类似商品卡片 -->
|
|
|
|
|
|
<view class="record-body" @click="handleRecordClick(item)">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="record-goods"
|
|
|
|
|
|
v-for="(goods, gIndex) in getGoodsList(item)"
|
|
|
|
|
|
:key="goods.id || goods.couponId || gIndex"
|
|
|
|
|
|
>
|
|
|
|
|
|
<image
|
|
|
|
|
|
class="goods-image"
|
|
|
|
|
|
:src="
|
|
|
|
|
|
goods.coverUrl ||
|
|
|
|
|
|
goods.couponCoverUrl ||
|
|
|
|
|
|
goods.picUrl ||
|
|
|
|
|
|
'/static/home/entry_icon.png'
|
|
|
|
|
|
"
|
|
|
|
|
|
mode="aspectFill"
|
|
|
|
|
|
></image>
|
|
|
|
|
|
<view class="goods-info">
|
2026-03-05 11:04:23 +00:00
|
|
|
|
<text class="goods-title">{{
|
|
|
|
|
|
goods.couponName || goods.name
|
|
|
|
|
|
}}</text>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<!-- <text class="goods-subtitle">
|
|
|
|
|
|
订单号:{{ item.orderNumber }}
|
|
|
|
|
|
</text> -->
|
|
|
|
|
|
<view class="goods-meta-row">
|
2026-03-05 11:04:23 +00:00
|
|
|
|
<text class="goods-price"
|
|
|
|
|
|
>¥{{ formatFen(goods.salePrice) }}</text
|
|
|
|
|
|
>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<text
|
|
|
|
|
|
class="goods-count"
|
2026-03-05 11:04:23 +00:00
|
|
|
|
v-if="
|
|
|
|
|
|
(goods.num || goods.count || goods.quantity || goods.qty) >
|
|
|
|
|
|
1
|
|
|
|
|
|
"
|
2026-03-04 08:58:40 +00:00
|
|
|
|
>
|
|
|
|
|
|
×{{ goods.num || goods.count || goods.quantity || goods.qty }}
|
|
|
|
|
|
</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-03-05 11:04:23 +00:00
|
|
|
|
<view
|
|
|
|
|
|
class="qr-code-icon-wrapper"
|
|
|
|
|
|
@click.stop="handleQrCode(item, goods)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<image
|
|
|
|
|
|
src="/static/home/qr_code_icon.png"
|
|
|
|
|
|
mode="aspectFill"
|
|
|
|
|
|
class="qr-code-icon"
|
|
|
|
|
|
></image>
|
|
|
|
|
|
</view>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部:合计 + 操作按钮 -->
|
|
|
|
|
|
<view class="record-footer">
|
|
|
|
|
|
<view class="total-info">
|
|
|
|
|
|
<text class="total-label">实付款:</text>
|
2026-03-05 11:04:23 +00:00
|
|
|
|
<text class="total-amount"
|
|
|
|
|
|
>¥{{ formatFen(item.payableAmount) }}</text
|
|
|
|
|
|
>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮区域 -->
|
2026-03-04 15:30:04 +00:00
|
|
|
|
<view class="record-actions" v-if="item.status === 0">
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<button
|
|
|
|
|
|
class="action-btn cancel-btn"
|
|
|
|
|
|
@click.stop="handleCancel(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
取消订单
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button class="action-btn pay-btn" @click.stop="handlePay(item)">
|
|
|
|
|
|
立即支付
|
|
|
|
|
|
</button>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
2026-03-04 15:30:04 +00:00
|
|
|
|
<view class="record-actions" v-else-if="item.status === 1">
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<!-- <button
|
|
|
|
|
|
class="action-btn detail-btn"
|
|
|
|
|
|
@click.stop="handleViewDetail(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
去核销
|
|
|
|
|
|
</button> -->
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
2026-03-04 08:58:40 +00:00
|
|
|
|
<view class="record-actions" v-else-if="item.status === 3">
|
|
|
|
|
|
<!-- <button
|
2025-12-19 12:27:55 +00:00
|
|
|
|
class="action-btn detail-btn"
|
|
|
|
|
|
@click.stop="handleViewDetail(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
查看详情
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="action-btn review-btn"
|
|
|
|
|
|
@click.stop="handleReview(item)"
|
|
|
|
|
|
>
|
|
|
|
|
|
评价
|
2026-03-04 08:58:40 +00:00
|
|
|
|
</button> -->
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="record-actions" v-else-if="item.status === 4">
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="action-btn detail-btn"
|
2026-03-05 11:04:23 +00:00
|
|
|
|
@click.stop="handleDelete(item)"
|
2026-03-04 08:58:40 +00:00
|
|
|
|
>
|
|
|
|
|
|
删除
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</view>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 加载更多提示 -->
|
|
|
|
|
|
<view class="load-more" v-if="currentList.length > 0">
|
|
|
|
|
|
<text v-if="loadingMore" class="load-more-text">加载中...</text>
|
|
|
|
|
|
<text v-else-if="!hasMore" class="load-more-text">没有更多数据了</text>
|
|
|
|
|
|
<text v-else class="load-more-text">上拉加载更多</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
2026-03-05 11:04:23 +00:00
|
|
|
|
|
|
|
|
|
|
<!-- 券码二维码弹窗 -->
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="qr-modal-mask"
|
|
|
|
|
|
v-if="qrModalVisible"
|
|
|
|
|
|
@click="closeQrModal"
|
|
|
|
|
|
></view>
|
|
|
|
|
|
<view class="qr-modal-wrap" v-if="qrModalVisible">
|
|
|
|
|
|
<view class="qr-modal" @click.stop>
|
|
|
|
|
|
<view class="qr-modal-header">
|
|
|
|
|
|
<text class="qr-modal-title">核销码</text>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="qr-modal-status"
|
|
|
|
|
|
:class="getQrUseStatusClass(qrModalData.useStatus)"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ getQrUseStatusText(qrModalData.useStatus) }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="qr-modal-close" @click="closeQrModal">×</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="qr-modal-body">
|
|
|
|
|
|
<view class="qr-code-box" v-if="qrModalData.couponCode">
|
|
|
|
|
|
<image
|
|
|
|
|
|
class="qr-code-image"
|
|
|
|
|
|
:src="qrCodeImageUrl"
|
|
|
|
|
|
mode="aspectFit"
|
|
|
|
|
|
></image>
|
|
|
|
|
|
<!-- <text class="qr-code-text">{{ qrModalData.couponCode }}</text> -->
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<text v-else class="qr-code-empty">暂无券码</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import NavHeader from "@/components/NavHeader/NavHeader.vue";
|
2026-03-05 11:04:23 +00:00
|
|
|
|
import { getLuMyOrderPage, cancelOrder, getPaySign,deleteOrder } from "@/api/service";
|
2025-12-19 12:27:55 +00:00
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
components: {
|
2026-03-04 08:58:40 +00:00
|
|
|
|
NavHeader,
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
currentTab: "pending_payment", // 当前选中的 tab
|
|
|
|
|
|
refreshing: false,
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
loadingMore: false,
|
|
|
|
|
|
hasMore: true,
|
|
|
|
|
|
pageNo: 1,
|
|
|
|
|
|
pageSize: 10,
|
2026-03-04 08:58:40 +00:00
|
|
|
|
// 各状态对应的订单列表
|
|
|
|
|
|
recordsMap: {
|
|
|
|
|
|
pending_payment: [],
|
|
|
|
|
|
pending_verification: [],
|
|
|
|
|
|
completed: [],
|
|
|
|
|
|
cancelled: [],
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
2026-03-05 11:04:23 +00:00
|
|
|
|
qrModalVisible: false,
|
|
|
|
|
|
qrModalData: {
|
|
|
|
|
|
useStatus: 0,
|
|
|
|
|
|
couponCode: "",
|
|
|
|
|
|
},
|
2025-12-19 12:27:55 +00:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
currentList() {
|
2026-03-04 08:58:40 +00:00
|
|
|
|
return this.recordsMap[this.currentTab] || [];
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
2026-03-05 11:04:23 +00:00
|
|
|
|
qrCodeImageUrl() {
|
|
|
|
|
|
const code = this.qrModalData.couponCode || "";
|
|
|
|
|
|
if (!code) return "";
|
|
|
|
|
|
return `https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${encodeURIComponent(code)}`;
|
|
|
|
|
|
},
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
2026-03-04 08:58:40 +00:00
|
|
|
|
onLoad(options) {
|
|
|
|
|
|
// 如果通过参数传入 tab,优先使用传入的 tab 值
|
|
|
|
|
|
if (options && options.tab) {
|
|
|
|
|
|
this.currentTab = options.tab;
|
|
|
|
|
|
}
|
2025-12-19 12:27:55 +00:00
|
|
|
|
this.loadData();
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
2026-03-04 08:58:40 +00:00
|
|
|
|
// 一个订单可能包含多个商品(couponPurchaseRespVOS)
|
|
|
|
|
|
getGoodsList(order) {
|
|
|
|
|
|
const list = (order && order.couponPurchaseRespVOS) || [];
|
|
|
|
|
|
return Array.isArray(list) && list.length ? list : [order || {}];
|
|
|
|
|
|
},
|
|
|
|
|
|
// 金额分转元(去掉后两位)
|
|
|
|
|
|
formatFen(fen) {
|
|
|
|
|
|
const n = Number(fen);
|
|
|
|
|
|
if (!Number.isFinite(n)) return fen || "0.00";
|
|
|
|
|
|
return (n / 100).toFixed(2);
|
|
|
|
|
|
},
|
|
|
|
|
|
// 时间戳转可读时间(支持秒/毫秒)
|
|
|
|
|
|
formatTime(val) {
|
|
|
|
|
|
if (val == null || val === "") return "";
|
|
|
|
|
|
let ts = Number(val);
|
|
|
|
|
|
if (!Number.isFinite(ts)) return val;
|
|
|
|
|
|
if (String(ts).length <= 10) ts *= 1000;
|
|
|
|
|
|
const d = new Date(ts);
|
|
|
|
|
|
const y = d.getFullYear();
|
|
|
|
|
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
|
|
|
|
const day = String(d.getDate()).padStart(2, "0");
|
|
|
|
|
|
const h = String(d.getHours()).padStart(2, "0");
|
|
|
|
|
|
const min = String(d.getMinutes()).padStart(2, "0");
|
|
|
|
|
|
const s = String(d.getSeconds()).padStart(2, "0");
|
|
|
|
|
|
return `${y}-${m}-${day} ${h}:${min}:${s}`;
|
|
|
|
|
|
},
|
|
|
|
|
|
// 根据当前 tab 映射到接口所需的 status 值
|
|
|
|
|
|
getStatusValue() {
|
|
|
|
|
|
const map = {
|
2026-03-04 15:30:04 +00:00
|
|
|
|
pending_payment: 0, // 待支付
|
2026-03-05 11:04:23 +00:00
|
|
|
|
pending_verification: 1, // 已完成
|
2026-03-04 15:30:04 +00:00
|
|
|
|
chargeback: 3, // 已退款
|
2026-03-04 08:58:40 +00:00
|
|
|
|
cancelled: 4, // 已取消
|
|
|
|
|
|
};
|
|
|
|
|
|
return map[this.currentTab];
|
|
|
|
|
|
},
|
2025-12-19 12:27:55 +00:00
|
|
|
|
// 切换 Tab
|
|
|
|
|
|
switchTab(tab) {
|
|
|
|
|
|
if (this.currentTab === tab) return;
|
|
|
|
|
|
this.currentTab = tab;
|
|
|
|
|
|
this.pageNo = 1;
|
|
|
|
|
|
this.hasMore = true;
|
|
|
|
|
|
this.loadData();
|
|
|
|
|
|
},
|
|
|
|
|
|
// 获取 Tab 标签文本
|
|
|
|
|
|
getTabLabel() {
|
|
|
|
|
|
const labels = {
|
|
|
|
|
|
pending_payment: "待支付",
|
|
|
|
|
|
pending_verification: "待核销",
|
|
|
|
|
|
completed: "已完成",
|
|
|
|
|
|
cancelled: "已取消",
|
|
|
|
|
|
};
|
|
|
|
|
|
return labels[this.currentTab] || "";
|
|
|
|
|
|
},
|
|
|
|
|
|
// 获取状态文本
|
|
|
|
|
|
getStatusText(status) {
|
2026-03-04 15:30:04 +00:00
|
|
|
|
return status === 0
|
2026-03-04 08:58:40 +00:00
|
|
|
|
? "待支付"
|
2026-03-04 15:30:04 +00:00
|
|
|
|
: status === 1
|
2026-03-04 08:58:40 +00:00
|
|
|
|
? "已完成"
|
2026-03-04 15:30:04 +00:00
|
|
|
|
: status === 3
|
|
|
|
|
|
? "已退款"
|
2026-03-04 08:58:40 +00:00
|
|
|
|
: status === 4
|
|
|
|
|
|
? "已取消"
|
|
|
|
|
|
: "";
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
|
|
|
|
|
// 获取状态样式类
|
|
|
|
|
|
getStatusClass(status) {
|
2026-03-04 15:30:04 +00:00
|
|
|
|
return status === 0
|
2026-03-04 08:58:40 +00:00
|
|
|
|
? "status-pending"
|
2026-03-04 15:30:04 +00:00
|
|
|
|
: status === 1
|
2026-03-04 08:58:40 +00:00
|
|
|
|
? "status-verification"
|
|
|
|
|
|
: status === 3
|
|
|
|
|
|
? "status-completed"
|
|
|
|
|
|
: status === 4
|
|
|
|
|
|
? "status-cancelled"
|
|
|
|
|
|
: "";
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
2026-03-05 11:04:23 +00:00
|
|
|
|
// 加载数据(真机/预览无数据时请检查:1. 小程序后台「服务器域名」已配置接口域名 2. 真机已登录)
|
2026-03-04 08:58:40 +00:00
|
|
|
|
async loadData(append = false) {
|
|
|
|
|
|
if (this.loading) return;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
this.loading = true;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
const status = this.getStatusValue();
|
|
|
|
|
|
try {
|
|
|
|
|
|
const res = await getLuMyOrderPage({
|
|
|
|
|
|
pageNo: this.pageNo,
|
|
|
|
|
|
pageSize: this.pageSize,
|
|
|
|
|
|
status,
|
|
|
|
|
|
});
|
2026-03-05 11:04:23 +00:00
|
|
|
|
// 兼容多种后端返回结构:list / records / data.list
|
|
|
|
|
|
const rawList =
|
|
|
|
|
|
res.list ||
|
|
|
|
|
|
res.records ||
|
|
|
|
|
|
(res.data && (res.data.list || res.data.records)) ||
|
|
|
|
|
|
[];
|
|
|
|
|
|
const list = Array.isArray(rawList) ? rawList : [];
|
2026-03-04 08:58:40 +00:00
|
|
|
|
|
|
|
|
|
|
const currentList = this.recordsMap[this.currentTab] || [];
|
|
|
|
|
|
this.recordsMap = {
|
|
|
|
|
|
...this.recordsMap,
|
|
|
|
|
|
[this.currentTab]: append ? currentList.concat(list) : list,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 是否还有更多
|
|
|
|
|
|
this.hasMore = list.length >= this.pageSize;
|
|
|
|
|
|
} catch (e) {
|
2026-03-05 11:04:23 +00:00
|
|
|
|
const msg = (e && e.message) ? String(e.message) : "";
|
2026-03-04 08:58:40 +00:00
|
|
|
|
console.error("加载服务记录失败:", e);
|
|
|
|
|
|
uni.showToast({
|
2026-03-05 11:04:23 +00:00
|
|
|
|
title: msg ? `加载失败:${msg}` : "加载服务记录失败",
|
2026-03-04 08:58:40 +00:00
|
|
|
|
icon: "none",
|
2026-03-05 11:04:23 +00:00
|
|
|
|
duration: 2500,
|
2026-03-04 08:58:40 +00:00
|
|
|
|
});
|
|
|
|
|
|
} finally {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
this.loading = false;
|
|
|
|
|
|
this.refreshing = false;
|
|
|
|
|
|
this.loadingMore = false;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
}
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
|
|
|
|
|
// 下拉刷新
|
|
|
|
|
|
handleRefresh() {
|
|
|
|
|
|
this.refreshing = true;
|
|
|
|
|
|
this.pageNo = 1;
|
|
|
|
|
|
this.hasMore = true;
|
|
|
|
|
|
this.loadData();
|
|
|
|
|
|
},
|
|
|
|
|
|
// 上拉加载更多
|
|
|
|
|
|
handleLoadMore() {
|
|
|
|
|
|
if (this.hasMore && !this.loadingMore && !this.loading) {
|
|
|
|
|
|
this.loadingMore = true;
|
|
|
|
|
|
this.pageNo += 1;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
this.loadData(true);
|
2025-12-19 12:27:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// 点击记录项
|
|
|
|
|
|
handleRecordClick(item) {
|
|
|
|
|
|
// 可以跳转到详情页
|
|
|
|
|
|
console.log("点击记录:", item);
|
|
|
|
|
|
},
|
|
|
|
|
|
// 取消订单
|
|
|
|
|
|
handleCancel(item) {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: "提示",
|
|
|
|
|
|
content: "确定要取消该订单吗?",
|
2026-03-04 08:58:40 +00:00
|
|
|
|
success: async (res) => {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
// 这里应该调用接口取消订单,然后刷新列表
|
2026-03-04 08:58:40 +00:00
|
|
|
|
const res = await cancelOrder({
|
|
|
|
|
|
id: item.id,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (res) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: "订单已取消",
|
|
|
|
|
|
icon: "success",
|
2025-12-19 12:27:55 +00:00
|
|
|
|
});
|
2026-03-04 08:58:40 +00:00
|
|
|
|
this.loadData();
|
2025-12-19 12:27:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2026-03-05 11:04:23 +00:00
|
|
|
|
// 删除订单
|
|
|
|
|
|
handleDelete(item) {
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: "提示",
|
|
|
|
|
|
content: "确定要删除该订单吗?",
|
|
|
|
|
|
success: async (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
const resData = await deleteOrder({
|
|
|
|
|
|
id: item.id,
|
|
|
|
|
|
});
|
|
|
|
|
|
if (resData) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: "订单已删除",
|
|
|
|
|
|
icon: "success",
|
|
|
|
|
|
});
|
|
|
|
|
|
this.loadData();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2026-03-04 08:58:40 +00:00
|
|
|
|
// 立即支付(与店铺详情页 handlePay 逻辑一致,跳转收银台小程序)
|
|
|
|
|
|
async handlePay(item) {
|
|
|
|
|
|
if (!item || !item.orderNumber) {
|
|
|
|
|
|
uni.showToast({ title: "订单信息异常", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const couponArray = item.couponPurchaseRespVOS || [];
|
|
|
|
|
|
const couponMap = new Map();
|
|
|
|
|
|
couponArray.forEach((goods) => {
|
|
|
|
|
|
const key = goods.couponId;
|
|
|
|
|
|
if (!key) return;
|
|
|
|
|
|
const currentList = couponMap.get(key) || [];
|
|
|
|
|
|
currentList.push(goods);
|
|
|
|
|
|
couponMap.set(key, currentList);
|
|
|
|
|
|
});
|
|
|
|
|
|
let bodyStr = "";
|
|
|
|
|
|
couponMap.forEach((couponList) => {
|
|
|
|
|
|
bodyStr =
|
|
|
|
|
|
bodyStr +
|
|
|
|
|
|
(couponList[0] && couponList[0].couponName
|
|
|
|
|
|
? couponList[0].couponName
|
|
|
|
|
|
: "商品") +
|
|
|
|
|
|
"x" +
|
|
|
|
|
|
couponList.length +
|
|
|
|
|
|
";";
|
2025-12-19 12:27:55 +00:00
|
|
|
|
});
|
2026-03-04 08:58:40 +00:00
|
|
|
|
|
|
|
|
|
|
const randomstr = Math.floor(Math.random() * 10000000) + "";
|
|
|
|
|
|
const trxamt =
|
|
|
|
|
|
item.payableAmount != null && item.payableAmount !== ""
|
|
|
|
|
|
? String(item.payableAmount)
|
|
|
|
|
|
: "1";
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
appid: "00390105",
|
|
|
|
|
|
body: bodyStr,
|
|
|
|
|
|
cusid: "56479107531MPMN",
|
|
|
|
|
|
notify_url:
|
|
|
|
|
|
"http://e989c692.natappfree.cc/admin-api/member/lu-order/tlNotice",
|
|
|
|
|
|
orgid: "56479107392N35H",
|
|
|
|
|
|
paytype: "W06",
|
|
|
|
|
|
randomstr: randomstr,
|
|
|
|
|
|
orderNumber: item.orderNumber,
|
|
|
|
|
|
remark: "1:" + item.orderNumber + ":" + bodyStr,
|
|
|
|
|
|
reqsn: item.orderNumber,
|
|
|
|
|
|
sign: "",
|
|
|
|
|
|
signtype: "RSA",
|
|
|
|
|
|
trxamt,
|
|
|
|
|
|
version: "12",
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (item.orderNumber) {
|
|
|
|
|
|
uni.setStorageSync("lastOrderNumber", item.orderNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const sign = await getPaySign(params);
|
|
|
|
|
|
params["sign"] = sign;
|
|
|
|
|
|
uni.navigateToMiniProgram({
|
|
|
|
|
|
appId: "wxef277996acc166c3",
|
|
|
|
|
|
extraData: params,
|
|
|
|
|
|
success(res) {
|
|
|
|
|
|
console.log("小程序跳转成功", res);
|
|
|
|
|
|
},
|
|
|
|
|
|
fail(err) {
|
|
|
|
|
|
console.error("小程序跳转失败", err);
|
|
|
|
|
|
uni.showToast({ title: "跳转失败,请稍后重试", icon: "none" });
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error("获取支付签名失败:", e);
|
|
|
|
|
|
uni.showToast({ title: "支付准备失败,请稍后重试", icon: "none" });
|
|
|
|
|
|
}
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
|
|
|
|
|
// 查看详情
|
|
|
|
|
|
handleViewDetail(item) {
|
|
|
|
|
|
uni.showToast({
|
2026-01-13 04:12:48 +00:00
|
|
|
|
title: "该功能正在开发中",
|
2025-12-19 12:27:55 +00:00
|
|
|
|
icon: "none",
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
// 评价
|
|
|
|
|
|
handleReview(item) {
|
|
|
|
|
|
uni.showToast({
|
2026-01-13 04:12:48 +00:00
|
|
|
|
title: "该功能正在开发中",
|
2025-12-19 12:27:55 +00:00
|
|
|
|
icon: "none",
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2026-03-05 11:04:23 +00:00
|
|
|
|
// 点击二维码图标:打开弹窗,展示券状态 + 根据 couponCode 生成二维码
|
|
|
|
|
|
handleQrCode(item, goods) {
|
|
|
|
|
|
const useStatus = goods?.useStatus ?? item?.useStatus ?? 0;
|
|
|
|
|
|
const couponCode =
|
|
|
|
|
|
(goods && (goods.couponCode || goods.couponNo)) ||
|
|
|
|
|
|
item?.couponCode ||
|
|
|
|
|
|
item?.couponNo ||
|
|
|
|
|
|
"";
|
|
|
|
|
|
this.qrModalData = { useStatus, couponCode };
|
|
|
|
|
|
this.qrModalVisible = true;
|
|
|
|
|
|
},
|
|
|
|
|
|
getQrUseStatusText(useStatus) {
|
|
|
|
|
|
const map = { 0: "未使用", 1: "已使用", 3: "已退款", 4: "已取消" };
|
|
|
|
|
|
return map[useStatus] ?? "未使用";
|
|
|
|
|
|
},
|
|
|
|
|
|
getQrUseStatusClass(useStatus) {
|
|
|
|
|
|
const map = {
|
|
|
|
|
|
0: "status-unused",
|
|
|
|
|
|
1: "status-used",
|
|
|
|
|
|
3: "status-refund",
|
|
|
|
|
|
4: "status-cancelled",
|
|
|
|
|
|
};
|
|
|
|
|
|
return map[useStatus] ?? "status-unused";
|
|
|
|
|
|
},
|
|
|
|
|
|
closeQrModal() {
|
|
|
|
|
|
this.qrModalVisible = false;
|
|
|
|
|
|
},
|
2025-12-19 12:27:55 +00:00
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.service-records-page {
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
background: #e2e8f1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Tab 切换栏 */
|
|
|
|
|
|
.tab-bar {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.tab-item {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
height: 88rpx;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
|
|
|
|
.tab-text {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
|
.tab-text {
|
|
|
|
|
|
color: #004294;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&::after {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
transform: translateX(-50%);
|
|
|
|
|
|
width: 60rpx;
|
|
|
|
|
|
height: 4rpx;
|
|
|
|
|
|
background-color: #004294;
|
|
|
|
|
|
border-radius: 2rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 列表区域 */
|
|
|
|
|
|
.record-list {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
height: 0; // 配合 flex: 1 使用
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
|
|
|
|
/* 空数据提示 */
|
|
|
|
|
|
.empty-state {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 200rpx 0;
|
|
|
|
|
|
min-height: 500rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.empty-icon {
|
|
|
|
|
|
width: 200rpx;
|
|
|
|
|
|
height: 200rpx;
|
|
|
|
|
|
margin-bottom: 40rpx;
|
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-text {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 加载更多提示 */
|
|
|
|
|
|
.load-more {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 40rpx 0;
|
|
|
|
|
|
min-height: 80rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.load-more-text {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 记录项 */
|
|
|
|
|
|
.record-item {
|
|
|
|
|
|
background-color: #ffffff;
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
padding: 24rpx 24rpx 20rpx;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
|
|
|
|
|
|
|
|
|
|
|
.record-header {
|
2026-03-04 08:58:40 +00:00
|
|
|
|
margin-bottom: 16rpx;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.record-shop-row {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
margin-bottom: 8rpx;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.shop-name {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
flex: 1;
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 28rpx;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
color: #1a1819;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status-badge {
|
|
|
|
|
|
padding: 6rpx 16rpx;
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.status-text {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.status-pending {
|
|
|
|
|
|
background-color: rgba(255, 107, 0, 0.1);
|
|
|
|
|
|
.status-text {
|
|
|
|
|
|
color: #ff6b00;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.status-verification {
|
|
|
|
|
|
background-color: rgba(0, 66, 148, 0.1);
|
|
|
|
|
|
.status-text {
|
|
|
|
|
|
color: #004294;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.status-completed {
|
|
|
|
|
|
background-color: rgba(76, 175, 80, 0.1);
|
|
|
|
|
|
.status-text {
|
|
|
|
|
|
color: #4caf50;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&.status-cancelled {
|
|
|
|
|
|
background-color: rgba(158, 158, 158, 0.1);
|
|
|
|
|
|
.status-text {
|
|
|
|
|
|
color: #9e9e9e;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.record-time {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.record-content {
|
|
|
|
|
|
margin-bottom: 24rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.record-info-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-label {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #888888;
|
|
|
|
|
|
margin-right: 8rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-value {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
|
|
|
|
&.price {
|
|
|
|
|
|
color: #d51c3c;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.record-body {
|
|
|
|
|
|
background-color: #f8f9fb;
|
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
|
padding: 18rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.record-goods {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.goods-image {
|
|
|
|
|
|
width: 120rpx;
|
|
|
|
|
|
height: 120rpx;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
margin-right: 16rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.goods-info {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.goods-title {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #1a1819;
|
|
|
|
|
|
}
|
2025-12-19 12:27:55 +00:00
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.goods-subtitle {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #888888;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.goods-meta-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
margin-top: 4rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.goods-price {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #d51c3c;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.goods-count {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #666666;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-05 11:04:23 +00:00
|
|
|
|
|
|
|
|
|
|
.qr-code-icon-wrapper {
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
padding: 12rpx;
|
|
|
|
|
|
margin-left: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-code-icon {
|
|
|
|
|
|
width: 44rpx;
|
|
|
|
|
|
height: 44rpx;
|
|
|
|
|
|
}
|
2026-03-04 08:58:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.record-footer {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
margin-top: 4rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.total-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: baseline;
|
|
|
|
|
|
|
|
|
|
|
|
.total-label {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #666666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.total-amount {
|
|
|
|
|
|
margin-left: 4rpx;
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
color: #1a1819;
|
|
|
|
|
|
}
|
2025-12-19 12:27:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.record-actions {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-04 08:58:40 +00:00
|
|
|
|
gap: 16rpx;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
button {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-btn {
|
|
|
|
|
|
min-width: 150rpx;
|
|
|
|
|
|
height: 56rpx;
|
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
box-sizing: border-box;
|
2025-12-19 12:27:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.pay-btn {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
background-color: #004294;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.detail-btn {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
color: #666666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 08:58:40 +00:00
|
|
|
|
.review-btn {
|
2025-12-19 12:27:55 +00:00
|
|
|
|
background-color: #004294;
|
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-05 11:04:23 +00:00
|
|
|
|
|
|
|
|
|
|
/* 券码二维码弹窗 */
|
|
|
|
|
|
.qr-modal-mask {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
|
z-index: 900;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal-wrap {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
z-index: 901;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 36rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-width: 720rpx;
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
border-radius: 28rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal-header {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
padding: 40rpx 32rpx 28rpx;
|
|
|
|
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal-title {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
|
color: #1a1819;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal-status {
|
|
|
|
|
|
padding: 8rpx 20rpx;
|
|
|
|
|
|
border-radius: 24rpx;
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
&.status-unused {
|
|
|
|
|
|
background: rgba(0, 66, 148, 0.1);
|
|
|
|
|
|
color: #004294;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.status-used {
|
|
|
|
|
|
background: rgba(158, 158, 158, 0.15);
|
|
|
|
|
|
color: #9e9e9e;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.status-refund {
|
|
|
|
|
|
background: rgba(76, 175, 80, 0.1);
|
|
|
|
|
|
color: #4caf50;
|
|
|
|
|
|
}
|
|
|
|
|
|
&.status-cancelled {
|
|
|
|
|
|
background: rgba(158, 158, 158, 0.15);
|
|
|
|
|
|
color: #9e9e9e;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal-close {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 20rpx;
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
|
width: 56rpx;
|
|
|
|
|
|
height: 56rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-size: 44rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
line-height: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-modal-body {
|
|
|
|
|
|
padding: 48rpx 32rpx 56rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-code-box {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-code-image {
|
|
|
|
|
|
width: 520rpx;
|
|
|
|
|
|
height: 520rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 2rpx solid #e8e8e8;
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
margin-bottom: 28rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-code-text {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
.qr-code-empty {
|
|
|
|
|
|
font-family: PingFang-SC, PingFang-SC;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
}
|
2025-12-19 12:27:55 +00:00
|
|
|
|
</style>
|