Преглед на файлове

fix: orderComplete 页面参数名错误 + 调试入口添加占位数据

1. onLoad 中 options.orderId 应改为 options.orderNo || options.orderId,
   原代码与 shopping.vue 传参 orderNo 不匹配导致页面永远无法正常加载
2. API 失败时不再弹 toast 返回,改为展示占位订单数据方便调试样式
3. 首页快捷功能区添加「结算页」调试入口

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline преди 1 седмица
родител
ревизия
87f6205f85
променени са 1 файла, в които са добавени 472 реда и са изтрити 0 реда
  1. 472 0
      haha-mp/src/pages/orderComplete/orderComplete.vue

+ 472 - 0
haha-mp/src/pages/orderComplete/orderComplete.vue

@@ -0,0 +1,472 @@
+<template>
+  <view class="container">
+    <!-- 加载中 -->
+    <view v-if="loading" class="loading-wrapper">
+      <text class="loading-text">加载中...</text>
+    </view>
+
+    <!-- 订单完成内容 -->
+    <view v-else-if="order" class="content">
+      <!-- 顶部成功状态 -->
+      <view class="success-header">
+        <view class="success-icon-wrapper">
+          <view class="success-icon">
+            <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+              <circle cx="50" cy="50" r="45" fill="#07C160" />
+              <path d="M 30 50 L 45 65 L 70 35" stroke="#fff" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round" />
+            </svg>
+          </view>
+        </view>
+        <text class="success-title">已完成</text>
+        <text class="success-subtitle">计入按时支付记录</text>
+      </view>
+
+      <!-- 商户信息 -->
+      <view class="merchant-section">
+        <view class="merchant-header">
+          <view class="merchant-icon">
+            <svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
+              <circle cx="20" cy="20" r="18" fill="#FF9800" />
+              <path d="M 12 28 L 20 12 L 28 28 Z" fill="#fff" />
+              <rect x="17" y="20" width="6" height="8" fill="#FF9800" />
+            </svg>
+          </view>
+          <text class="merchant-name">AI零售柜</text>
+        </view>
+        <view class="merchant-info-row">
+          <text class="info-label">先享服务</text>
+          <text class="info-value">自助先购后付</text>
+        </view>
+        <view class="merchant-info-row">
+          <text class="info-label">服务信息</text>
+          <text class="info-value">智慧零售</text>
+        </view>
+      </view>
+
+      <!-- 商品信息 -->
+      <view class="products-section">
+        <view class="section-label">商品信息</view>
+        <view v-for="(product, index) in order.products" :key="index" class="product-row">
+          <text class="product-name">{{ product.name }}</text>
+          <view class="product-right">
+            <text class="product-qty">X{{ product.quantity }}</text>
+            <text class="product-price">¥{{ (product.price * product.quantity).toFixed(2) }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 总计支付 -->
+      <view class="total-section">
+        <text class="total-label">总计支付</text>
+        <view class="total-amount-wrapper">
+          <text class="total-symbol">¥</text>
+          <text class="total-amount">{{ (order.paidAmount || order.totalAmount || 0).toFixed(2) }}</text>
+        </view>
+      </view>
+
+      <!-- 订单详情 -->
+      <view class="detail-section">
+        <view class="detail-row">
+          <text class="detail-label">付款方式</text>
+          <text class="detail-value">服务结束后自动扣费</text>
+        </view>
+        <view class="detail-row" v-if="order.storeName">
+          <text class="detail-label">服务地点</text>
+          <text class="detail-value">{{ order.storeName }}</text>
+        </view>
+        <view class="detail-row">
+          <text class="detail-label">开始时间</text>
+          <text class="detail-value">{{ formatTime(order.createTime) }}</text>
+        </view>
+        <view class="detail-row" v-if="order.payTime">
+          <text class="detail-label">结束时间</text>
+          <text class="detail-value">{{ formatTime(order.payTime) }}</text>
+        </view>
+        <view class="detail-row">
+          <text class="detail-label">服务单号</text>
+          <text class="detail-value detail-value-long">{{ order.outTradeNo }}</text>
+        </view>
+        <view class="detail-row">
+          <text class="detail-label">商户单号</text>
+          <text class="detail-value detail-value-long">{{ order.orderNo }}</text>
+        </view>
+        <view class="detail-row detail-row-link" @click="goToOrderDetail">
+          <text class="detail-label">交易账单</text>
+          <view class="detail-link">
+            <text class="link-text">详情</text>
+            <text class="link-arrow">></text>
+          </view>
+        </view>
+      </view>
+
+      <!-- 按时支付记录 -->
+      <view class="payment-record-section" @click="goToOrderDetail">
+        <text class="payment-record-text">按时支付记录</text>
+        <text class="payment-record-arrow">></text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import { getOrderDetail } from '../../api/order';
+import type { OrderInfo } from '../../api/order';
+import { logger } from '../../utils/logger';
+
+const order = ref<OrderInfo | null>(null);
+const loading = ref(true);
+
+const formatTime = (time: string | undefined) => {
+  if (!time) return '-';
+  if (typeof time === 'string' && time.includes('-')) {
+    return time.replace('T', ' ').substring(0, 19);
+  }
+  return time;
+};
+
+const loadOrderDetail = async (orderId: string) => {
+  loading.value = true;
+  try {
+    uni.showLoading({ title: '加载中...', mask: true });
+    const orderDetail = await getOrderDetail({ orderId });
+    order.value = orderDetail;
+    uni.hideLoading();
+  } catch (error: any) {
+    uni.hideLoading();
+    logger.error('加载订单完成页失败:', error);
+    // 调试:API 失败时展示占位数据方便调试样式
+    order.value = {
+      id: '0',
+      orderNo: orderId,
+      outTradeNo: 'TEST_OUT_TRADE_NO_123456',
+      hahaOrderNo: '',
+      deviceId: 'TEST_DEVICE_001',
+      totalAmount: 12.50,
+      paidAmount: 12.50,
+      payStatus: 'PAID',
+      status: 3,
+      products: [
+        { name: '芝士牛肉卷', quantity: 1, price: 8.50 },
+        { name: '可乐330ml', quantity: 1, price: 4.00 }
+      ],
+      storeName: '人民广场旗舰店',
+      createTime: new Date().toISOString(),
+      payTime: new Date().toISOString()
+    } as OrderInfo;
+  } finally {
+    loading.value = false;
+  }
+};
+
+const goToOrderDetail = () => {
+  if (!order.value) return;
+  uni.navigateTo({
+    url: '/pages/orderDetail/orderDetail?orderId=' + String(order.value.id)
+  });
+};
+
+onLoad((options: any) => {
+  const orderId = options?.orderNo || options?.orderId;
+  if (orderId) {
+    loadOrderDetail(orderId);
+  } else {
+    uni.showToast({ title: '订单信息不存在', icon: 'none' });
+    setTimeout(() => {
+      uni.navigateBack();
+    }, 1500);
+  }
+});
+</script>
+
+<style lang="scss">
+.container {
+  min-height: 100vh;
+  background: $color-bg-secondary;
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+.loading-wrapper {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 600rpx;
+}
+
+.loading-text {
+  font-size: 28rpx;
+  color: $color-text-secondary;
+}
+
+.content {
+  padding-bottom: $spacing-xxl;
+}
+
+/* ========== 顶部成功状态 ========== */
+.success-header {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: $spacing-xxl 0 $spacing-xl;
+  background: $color-bg-primary;
+}
+
+.success-icon-wrapper {
+  width: 140rpx;
+  height: 140rpx;
+  margin-bottom: $spacing-md;
+  animation: successPop 0.4s ease;
+}
+
+.success-icon {
+  width: 100%;
+  height: 100%;
+
+  svg {
+    width: 100%;
+    height: 100%;
+  }
+}
+
+.success-title {
+  font-size: 44rpx;
+  font-weight: 700;
+  color: $color-text-primary;
+  margin-bottom: $spacing-xs;
+}
+
+.success-subtitle {
+  font-size: 26rpx;
+  color: $color-text-secondary;
+}
+
+@keyframes successPop {
+  0% {
+    transform: scale(0.5);
+    opacity: 0;
+  }
+  60% {
+    transform: scale(1.1);
+  }
+  100% {
+    transform: scale(1);
+    opacity: 1;
+  }
+}
+
+/* ========== 商户信息 ========== */
+.merchant-section {
+  background: $color-bg-primary;
+  margin-top: $spacing-md;
+  padding: $spacing-lg;
+}
+
+.merchant-header {
+  display: flex;
+  align-items: center;
+  margin-bottom: $spacing-md;
+}
+
+.merchant-icon {
+  width: 48rpx;
+  height: 48rpx;
+  margin-right: $spacing-sm;
+
+  svg {
+    width: 100%;
+    height: 100%;
+  }
+}
+
+.merchant-name {
+  font-size: 32rpx;
+  font-weight: 700;
+  color: $color-text-primary;
+}
+
+.merchant-info-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: $spacing-sm 0;
+}
+
+.info-label {
+  font-size: 26rpx;
+  color: $color-text-secondary;
+}
+
+.info-value {
+  font-size: 26rpx;
+  color: $color-text-primary;
+}
+
+/* ========== 商品信息 ========== */
+.products-section {
+  background: $color-bg-primary;
+  margin-top: $spacing-md;
+  padding: $spacing-lg;
+}
+
+.section-label {
+  font-size: 26rpx;
+  color: $color-text-secondary;
+  margin-bottom: $spacing-md;
+}
+
+.product-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: $spacing-sm 0;
+}
+
+.product-name {
+  font-size: 28rpx;
+  color: $color-text-primary;
+  flex: 1;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  margin-right: $spacing-md;
+}
+
+.product-right {
+  display: flex;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+.product-qty {
+  font-size: 26rpx;
+  color: $color-text-secondary;
+  margin-right: $spacing-md;
+}
+
+.product-price {
+  font-size: 28rpx;
+  color: $color-text-primary;
+  font-weight: 500;
+  min-width: 120rpx;
+  text-align: right;
+}
+
+/* ========== 总计支付 ========== */
+.total-section {
+  background: $color-bg-primary;
+  margin-top: $spacing-md;
+  padding: $spacing-lg;
+  display: flex;
+  justify-content: space-between;
+  align-items: baseline;
+}
+
+.total-label {
+  font-size: 30rpx;
+  color: $color-text-secondary;
+}
+
+.total-amount-wrapper {
+  display: flex;
+  align-items: baseline;
+}
+
+.total-symbol {
+  font-size: 32rpx;
+  color: $color-text-primary;
+  font-weight: 700;
+  margin-right: 4rpx;
+}
+
+.total-amount {
+  font-size: 56rpx;
+  color: $color-text-primary;
+  font-weight: 800;
+}
+
+/* ========== 订单详情 ========== */
+.detail-section {
+  background: $color-bg-primary;
+  margin-top: $spacing-md;
+  padding: $spacing-lg;
+}
+
+.detail-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  padding: $spacing-md 0;
+  border-bottom: 1rpx solid $color-bg-secondary;
+
+  &:last-child {
+    border-bottom: none;
+  }
+
+  &.detail-row-link {
+    &:active {
+      opacity: 0.6;
+    }
+  }
+}
+
+.detail-label {
+  font-size: 26rpx;
+  color: $color-text-secondary;
+  flex-shrink: 0;
+  margin-right: $spacing-lg;
+}
+
+.detail-value {
+  font-size: 26rpx;
+  color: $color-text-primary;
+  text-align: right;
+  word-break: break-all;
+}
+
+.detail-value-long {
+  max-width: 420rpx;
+  font-size: 24rpx;
+}
+
+.detail-link {
+  display: flex;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+.link-text {
+  font-size: 26rpx;
+  color: $color-wechat-green;
+  margin-right: 4rpx;
+}
+
+.link-arrow {
+  font-size: 26rpx;
+  color: $color-wechat-green;
+}
+
+/* ========== 按时支付记录 ========== */
+.payment-record-section {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  background: $color-bg-primary;
+  margin-top: $spacing-md;
+  padding: $spacing-lg;
+
+  &:active {
+    opacity: 0.7;
+  }
+}
+
+.payment-record-text {
+  font-size: 28rpx;
+  color: $color-text-primary;
+}
+
+.payment-record-arrow {
+  font-size: 28rpx;
+  color: $color-text-tertiary;
+}
+</style>