index.vue 4.58 KB
<!--
 * @Date: 2024-01-16 13:19:23
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-01-24 12:46:06
 * @FilePath: /xyxBooking-weapp/src/pages/bookingDetail/index.vue
 * @Description: 预约记录详情
-->
<template>
  <view class="booking-detail-page">
    <qrCode ref="qr_code_ref" :status="qrCodeStatus" type="detail" :payId="pay_id"></qrCode>
    <view v-if="billInfo.pay_id" class="detail-wrapper">
      <view class="detail-item">
        <view>参访时间:</view>
        <view>{{ billInfo?.datetime }}</view>
      </view>
      <view class="detail-item">
        <view>参访人数:</view>
        <view>{{ billInfo?.total_qty }} 人</view>
      </view>
      <view class="detail-item">
        <view>支付金额:</view>
        <view>¥ {{ billInfo?.total_amt }}</view>
      </view>
      <view class="detail-item">
        <view>下单时间:</view>
        <view>{{ billInfo?.order_time }}</view>
      </view>
      <view class="detail-item">
        <view>订单编号:</view>
        <view>{{ billInfo?.pay_id }}</view>
      </view>
      <view class="detail-item">
        <view>订单状态:</view>
        <view>{{ qrCodeStatusText }}</view>
      </view>
    </view>
    <view style="height: 160rpx"></view>
    <view
      v-if="billInfo.status === CodeStatus.SUCCESS && billInfo.show_cancel_reserve === 1"
      class="cancel-wrapper"
    >
      <view @tap="cancelBooking" class="cancel-btn">取消预约</view>
    </view>
  </view>
</template>

<script setup>
import { ref, computed } from 'vue'
import Taro, { useDidShow, useDidHide, useRouter as useTaroRouter } from '@tarojs/taro'
import qrCode from '@/components/qrCode'
import { billInfoAPI, icbcRefundAPI } from '@/api/index'
import { formatDatetime, get_bill_status_text } from '@/utils/tools'
import { refresh_offline_booking_cache } from '@/composables/useOfflineBookingCache'

const router = useTaroRouter()

const pay_id = ref('')
const qrCodeStatus = ref('')
const billInfo = ref({})
const qr_code_ref = ref(null)

/**
 * @description 预约码状态枚举(与后端约定)
 * @readonly
 */
const CodeStatus = {
  APPLY: '1',
  PAYING: '2',
  SUCCESS: '3',
  CANCEL: '5',
  CANCELED: '7',
  USED: '9',
  REFUNDING: '11'
}

/**
 * @description 订单状态文案
 * @returns {string} 状态文案
 */
const qrCodeStatusText = computed(() => {
  return get_bill_status_text(billInfo.value?.status)
})

/**
 * @description 取消预约
 * - 成功后刷新离线缓存(保证弱网/离线模式数据一致)
 * @returns {Promise<void>} 无返回值
 */
const cancelBooking = async () => {
  const { confirm } = await Taro.showModal({
    title: '温馨提示',
    content: '是否取消预约?',
    confirmColor: '#A67939'
  })

  if (confirm) {
    Taro.showLoading({ title: '取消中...' })
    const { code, data } = await icbcRefundAPI({ pay_id: pay_id.value })
    Taro.hideLoading()
    if (code) {
      Taro.showToast({ title: '取消成功' })
      try {
        await refresh_offline_booking_cache({ force: true })
      } catch (e) {}
      Taro.navigateBack()
    } else {
      Taro.showToast({ title: '取消失败', icon: 'none' })
    }
  }
}

useDidShow(async () => {
  qr_code_ref.value?.start_polling?.()
  pay_id.value = router.params.pay_id
  if (pay_id.value) {
    const { code, data } = await billInfoAPI({ pay_id: pay_id.value })
    if (code) {
      data.datetime = data && formatDatetime(data)
      data.order_time = data.created_time ? data.created_time.slice(0, -3) : ''
      billInfo.value = data
    }
  }
})

useDidHide(() => {
  qr_code_ref.value?.stop_polling?.()
})
</script>

<style lang="less">
.booking-detail-page {
  min-height: 100vh;
  background-color: #f6f6f6;
  padding: 32rpx;

  .detail-wrapper {
    background-color: #fff;
    border-radius: 16rpx;
    padding: 32rpx;
    margin-top: 32rpx;
    box-shadow: 0 0 29rpx 0 rgba(106, 106, 106, 0.1);

    .detail-item {
      display: flex;
      justify-content: space-between;
      margin-bottom: 26rpx;
      color: #333;
      font-size: 30rpx;

      &:last-child {
        margin-bottom: 0;
      }

      view:first-child {
        color: #999;
        width: 160rpx;
      }
      view:last-child {
        flex: 1;
        text-align: right;
      }
    }
  }

  .cancel-wrapper {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 750rpx;
    background-color: #fff;
    padding: 32rpx;
    box-sizing: border-box;

    .cancel-btn {
      background-color: #fff;
      color: #a67939;
      border: 2rpx solid #a67939;
      text-align: center;
      padding: 26rpx 0;
      border-radius: 16rpx;
      font-size: 35rpx;
    }
  }
}
</style>