reserveCard.vue 6.93 KB
<!--
 * @Date: 2024-01-24 16:38:13
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2024-01-24 17:00:48
 * @FilePath: /xysBooking/src/components/reserveCard.vue
 * @Description: 文件描述
-->
<template>
  <div class="booking-list-item" @click="goToDetail(props.data)">
    <div class="booking-list-item-header">
      <div>{{ props.data.booking_time }}</div>
      <div :class="[formatStatus(props.data.status)?.key, 'status']">{{ formatStatus(props.data.status)?.value }}</div>
    </div>
    <div class="booking-list-item-body">
      <div class="booking-num">
        <div class="num-body">预约人数:<span>{{ props.data.total_qty }} 人</span></div>
        <div><van-icon name="arrow" /></div>
      </div>
      <div class="booking-price">支付金额:<span>¥ {{ props.data.total_amt }}</span></div>
      <div class="booking-time">下单时间:<span>{{ props.data.order_time }}</span></div>
    </div>
    <div class="booking-list-item-footer">
      <div style="display: flex; justify-content: space-between; padding: 0 1rem 1rem 1rem; align-items: center;">
        <div v-if="pay_show" style="font-size: 0.85rem; color: red;">
          <span>支付剩余时间&nbsp;</span>
          <span>{{ formatTime(remain_time) }}</span>
        </div>
        <div v-if="showBtn">
          <van-button v-if="pay_show" @click="payOrder()" type="primary" color="#A67939" size="small">重新支付</van-button>
          <div v-if="delay_pay_show" style="font-size: 23rpx; color: red; font-size: 0.85rem;">支付超时,请重新下单!</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'

import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js'
//import { } from '@/utils/generateModules.js'
//import { } from '@/utils/generateIcons.js'
//import { } from '@/composables'
const $route = useRoute();
const $router = useRouter();
useTitle($route.meta.title);

const props = defineProps({
  data: {
    type: Object,
    default: {},
  },
});


/**
 * 1=待支付(下单就立即支付,所以理论上不存在待支付的数据),
 * 2=支付中(支付前先把状态打成2;支付回调后应立即变更状态,支付中的状态不会持续很久),
 * 3=预约成功(已支付,且一个码都未被使用),
 * 5=已取消(用户手动取消成功,退款成功回调后打成5,否则打成3),
 * 7=已取消(支付超时或失败自动取消),
 * 9=已使用(明细里有一个码被使用),
 * 11=退款中(取消预约时先把状态打成11)
 */
const CodeStatus = {
  APPLY: '1',
  PAYING: '2',
  SUCCESS: '3',
  CANCEL: '5',
  CANCELED: '7',
  USED: '9',
  REFUNDING: '11'
}

const formatStatus = (status) => {
  switch (status) {
    case CodeStatus.APPLY:
      return {
        key: 'cancel',
        value: '待支付'
      }
    case CodeStatus.PAYING:
      return {
        key: 'success',
        value: '支付中'
      }
    case CodeStatus.SUCCESS:
      return {
        key: 'success',
        value: '预约成功'
      }
    case CodeStatus.CANCEL:
      return {
        key: 'cancel',
        value: '已取消'
      }
    case CodeStatus.CANCELED:
      return {
        key: 'cancel',
        value: '已取消'
      }
    case CodeStatus.USED:
      return {
        key: 'used',
        value: '已使用'
      }
    case CodeStatus.REFUNDING:
      return {
        key: 'cancel',
        value: '退款中'
      }
  }
}


const goToDetail = (item) => {
  if (item.status === CodeStatus.SUCCESS || item.status === CodeStatus.USED || item.status === CodeStatus.CANCEL) {
    go('/bookingDetail', { pay_id: item.pay_id })
  }
}

/**
 * 格式化时间
 * @param {*} seconds
 */
function formatTime(seconds) {
  const hours = Math.floor(seconds / 3600); // 计算小时数
  const minutes = Math.floor((seconds % 3600) / 60); // 计算分钟数
  const remainingSeconds = seconds % 60; // 计算剩余的秒数

  const formattedHours = String(hours).padStart(2, "0"); // 格式化小时数,保证两位数
  const formattedMinutes = String(minutes).padStart(2, "0"); // 格式化分钟数,保证两位数
  const formattedSeconds = String(remainingSeconds).padStart(2, "0"); // 格式化剩余的秒数,保证两位数

  return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
}

// 显示操作按钮的条件判断
const showBtn = computed(() => {
  return props.data.status === CodeStatus.APPLY;
});

const remain_time = ref(0); // 剩余时间秒数

// 控制待支付状态下的显示
const pay_show = computed(() => {
  let flag = false;
  if (props.data.status === CodeStatus.APPLY && remain_time.value) {
    // 倒计时进行时
    flag = true;
  } else if (props.data.status === CodeStatus.APPLY && !remain_time.value) {
    // 倒计时结束
    flag = false;
  }
  return flag;
});

// 支付超时显示
const delay_pay_show = computed(() => {
  // return props.data.status === CodeStatus.APPLY && !remain_time.value;
  return props.data.status === CodeStatus.SUCCESS && !remain_time.value;
});

let timeId = null;

onMounted(() => {
  remain_time.value = 5;
  // 进入页面后,开始倒计时
  timeId = setInterval(() => {
    remain_time.value ? (remain_time.value -= 1) : 0;
  }, 1000);
  onUnmounted(() => {
    timeId && clearInterval(timeId);
  });
});

const payOrder = () => {
  const pay_url = `/srv/?f=reserve&a=icbc_pay&pay_id=${props.data.pay_id}`;
  location.href = pay_url; // 跳转支付页面
}
</script>

<style lang="less" scoped>
  .booking-list-item {
    background-color: #FFF;
    border-radius: 8px;
    margin-bottom: 1rem;
    .booking-list-item-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 1rem;
      border-bottom: 1px dashed #f0f0f0;
      .status {
        font-size: 0.75rem;
        padding: 5px 8px;
        border-radius: 5px;
      }
      .success {
        color: #A67939;
        background-color: #FBEEDC;
      }
      .cancel {
        color: #929292;
        background-color: #E6E6E6;
      }
      .used {
        color: #477F3D;
        background-color: #E5EFE3;
      }
    }
    .booking-list-item-body {
      padding: 1rem;
      line-height: 1.7;
      .booking-num {
        display: flex;
        justify-content: space-between;
        .num-body {
          color: #959595;
          span {
            color: #1E1E1E;
          }
        }
      }
      .booking-price {
        color: #959595;
        span {
          color: #1E1E1E;
        }
      }
      .booking-time {
        color: #959595;
        span {
          color: #1E1E1E;
        }
      }
    }
  }

  .no-qrcode {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    img {
      margin-top: 1rem;
      margin-bottom: 1rem;
      width: 10rem;
    }
    .no-qrcode-title {
      color: #A67939;
      font-size: 1.05rem;
    }
  }
</style>