preview.vue 9.49 KB
<template>
  <div class="preview-page">
    <div class="app-time">
      预约时间
    </div>
    <div @click="handleCheck(item)" v-for="(item, index) in shortcut" :key="index" class="d-checkbox">
      <div class="icon-box">
        <van-icon v-if="item.checked" name="https://cdn.ipadbiz.cn/bieyuan/dui@2x.png" />
      </div>
      <div class="text">{{ item.date }}</div>
      <div>
        剩余名额&nbsp;&nbsp;<span style="font-size: 1.5rem; font-weight: bold;">{{ item.rest_count }}</span>&nbsp;&nbsp;人
      </div>
    </div>
    <div class="more-box">
      <div @click="showMore" class="more">
        <van-icon size="1.25rem" name="https://cdn.ipadbiz.cn/bieyuan/rili@2x.png"
          style="vertical-align: sub;" />&nbsp;&nbsp;更多
      </div>
    </div>

    <div class="bookingBox">
      <van-row>
        <van-col span="6" class="text">预约人数</van-col>
        <van-col span="18" class="control">
          <van-row style="line-height: 3rem;" gutter="10">
            <van-col span="4" style="text-align: center;">
              <div @click="clickMinus" class="minus">
              <van-icon size="0.85rem" name="https://cdn.ipadbiz.cn/bieyuan/-@2x.png" />
            </div>
            </van-col>
            <van-col span="12" style="text-align: center;">
              <input v-model="num" type="number" class="input_num">
            </van-col>
            <van-col span="4" style="text-align: center;">
              <span>人</span>
            </van-col>
            <van-col span="4" style="text-align: center;">
              <div @click="clickPlus" class="plus">
              <van-icon size="0.85rem" name="https://cdn.ipadbiz.cn/bieyuan/+@2x.png" />
            </div>
            </van-col>
          </van-row>
        </van-col>
      </van-row>
    </div>

    <div style="padding-bottom: 2rem;">
      <div @click="clickNext" class="next-btn">下一步</div>
    </div>

    <van-calendar
      v-model:show="show"
      :default-date="defaultDate"
      type="multiple"
      :max-range="7"
      :formatter="formatter"
      :max-date="maxDate"
      color="#93663D"
      @confirm="onConfirm"
    />
  </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 dayjs from 'dayjs';
//import { } from '@/utils/generateModules.js'
//import { } from '@/utils/generateIcons.js'
//import { } from '@/composables'
import { showSuccessToast, showFailToast } from 'vant';
import { orderRestCountAPI } from '@/api/index'
const $route = useRoute();
const $router = useRouter();
useTitle($route.meta.title);

function getDaysInMonth(year, month) {
  return new Date(year, month, 0).getDate();
}

onMounted(async () => {
  let dates = $route.query.dates && JSON.parse($route.query.dates);
  if (localStorage.getItem('save_selected_dates')) { // 如果缓存过以缓存为先
    dates = JSON.parse(localStorage.getItem('save_selected_dates'));
  }
  const { data } = await orderRestCountAPI({ dates:  dates.join(',')});
  shortcut.value = data;
  // 上一页选择的预约人数
  num.value = $route.query.count ? +$route.query.count : 1;
  // 默认选中所有日期项
  shortcut.value.forEach((item, index) => {
    item.checked = true;
  });
  // 获取默认日期集合
  selectedDates.value = shortcut.value.map(item => item.date);
  // 默认勾选日历信息
  let default_date = JSON.parse($route.query.dates);
  defaultDate.value = [];
  default_date.forEach((date) => {
    defaultDate.value.push(dayjs(date).toDate())
  });
});

const defaultDate = ref(null);
const shortcut = ref([]);

const handleCheck = (value) => {
  value.checked = !value.checked;
  // 同步日历显示
  defaultDate.value = [];
  const arr = [];
  shortcut.value.forEach((item) => {
    if (item.checked) {
      defaultDate.value.push(dayjs(item.date).toDate())
      arr.push(item.date);
    }
  });
  // 缓存修改日期
  localStorage.setItem('save_selected_dates', JSON.stringify(arr));
}

const num = ref(1);
const show = ref(false);
const selectedDates = ref([]);

watch(
  () => num.value,
  (val) => {
    // 控制输入值为 3 位
    const maxLength = 3;
    if (val.toString().length > maxLength) {
      num.value = num.value.toString().slice(0, maxLength);
    }
  }
);

const asyncData = ref();
const showMore = async () => {
  show.value = true;
  const { data } = await orderRestCountAPI({ start_date: dayjs().format('YYYY-MM-DD'), end_date: dayjs(maxDate.value).format('YYYY-MM-DD') });
  asyncData.value = data;
  asyncData.value.forEach(item => {
    item.format = item.date.split('-')
  });
  // 同步日历显示
  defaultDate.value = [];
  // shortcut.value.forEach((item) => {
  //   if (item.checked) {
  //     defaultDate.value.push(dayjs(item.date).toDate())
  //   }
  // });
  const arr = JSON.parse(localStorage.getItem('save_selected_dates'));
  arr.forEach((item) => {
    defaultDate.value.push(dayjs(item).toDate())
  });
}

const formatter = computed(() => {
  if (!asyncData.value) {
    return (day) => day;
  }
  return (day) => {
    const year = day.date.getFullYear();
    const month = day.date.getMonth() + 1;
    const date = day.date.getDate();

    asyncData.value.forEach(item => {
      const arr = item.format;
      if (year === +arr[0] && month === +arr[1] && date === +arr[2]) {
        // day.topInfo = '剩余';
        day.bottomInfo = item.rest_count;
      }
    });
    return day;
  };
});

const onConfirm = async (dates) => {
  show.value = false;
  selectedDates.value = [];
  dates.forEach((date) => {
    selectedDates.value.push(dayjs(date).format('YYYY-MM-DD'))
    defaultDate.value.push(dayjs(date).toDate())
  });
  // 后台请求数据
  const { data } = await orderRestCountAPI({ dates : selectedDates.value.join(',') });
  shortcut.value = data;
  shortcut.value.forEach(item => {
    item.checked = true;
  });
};

const selectIndex = (idx) => {
  index.value = idx;
}

const clickMinus = () => { // 减少预约数
  num.value = num.value > 1 ? num.value - 1 : 1;
}
const clickPlus = () => { // 新增预约数
  if (num.value.toString().length < 3) {
    num.value =  num.value + 1
  }
}

// 最大日期默认为6个月
const getFutureDate = () => {
  const currentDate = new Date();
  const futureDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 6, currentDate.getDate());
  return futureDate;
}
const maxDate = ref(getFutureDate());

const isPositiveInteger = (value) => {
  // 判断是否为数字
  if (typeof value !== 'number') {
    return false;
  }

  // 判断是否为正整数
  return Number.isInteger(value) && value > 0;
}

const isMinValue = (array, value) => { // 判断输入值是否小于数组中剩余名额数
  let result = array.filter((item) => item.rest_count < value);
  return result.length > 0;
}

const clickNext = () => { // 点击下一步按钮
  if (!isPositiveInteger(num.value)) { // 判断是否是非零整数
    showFailToast('请检查预约人数输入!');
    return false;
  }
  // 勾选的日期项
  const selected_item = shortcut.value.filter(item => {
    if (item.checked) {
      return item
    }
  });
  if (isMinValue(selected_item, num.value)) {
    showFailToast('剩余名额小于预约人数!');
    return false;
  }
  // 选中的日期集合
  const selected_dates = selected_item.map(item => item.date);
  // 跳转更多确认页
  localStorage.setItem('save_selected_dates', JSON.stringify(selected_dates));
  setTimeout(() => {
    $router.push({
      path: '/next',
      query: {
        dates: JSON.stringify(selected_dates),
        count: num.value,
        page: 'multiple'
      }
    });

  }, 100);
}

</script>

<style lang="less" scoped>
.preview-page {
  padding: 1rem 1rem 0;

  .app-time {
    padding-bottom: 0.5rem;
    border-bottom: 1px solid #D7D7D7;
    font-weight: bold;
    font-size: 1.05rem;
  }

  .d-checkbox {
    display: flex;
    padding: 1rem 0;
    border-bottom: 1px solid #D7D7D7;
    align-items: center;
    color: #93663D;

    .icon-box {
      width: 1rem;
      height: 1rem;
      border: 1px solid #93663D;
      margin-right: 1rem;
    }

    .text {
      flex: 1;
      font-size: 1.15rem;
    }
  }

  .more-box {
    display: flex;
    align-items: center;
    justify-content: flex-end;

    .more {
      color: #93663D;
      margin-top: 1rem;
      width: 5rem;
      height: 2rem;
      background: #FBF3F4;
      border: 1px solid #D7D7D7;
      border-radius: 10px 10px 0rem 0rem;
      line-height: 2rem;
      text-align: center;
    }
  }

  .bookingBox {
    padding: 2rem 0 1rem;
    border-bottom: 1px solid #D7D7D7;

    .text {
      line-height: 3.1rem;
      font-weight: bold;
      font-size: 1.05rem;
    }

    .control {
      text-align: right;
    }

    .minus,
    .plus {
      width: 2rem;
      height: 2rem;
      background: #FFFFFF;
      border: 1px solid #D7D7D7;
      border-radius: 50%;
      text-align: center;
      line-height: 2rem;
      display: inline-block;

    }
    // .input-box {
    //   width: 40%;
    //   display: inline-block;
    // }
    .input_num {
      border: 0;
      background-color: #F7F7F7;
      height: 2.5rem;
      // width: 4em;
      width: 70%;
      color: #976C46;
      text-align: center;
      font-weight: bold;
      font-size: 1.5rem;
      // margin: 0 1rem;
    }
  }

  .next-btn {
    background-color: #93663D;
    width: 70%;
    height: 3rem;
    color: white;
    line-height: 3rem;
    text-align: center;
    font-size: 1.25rem;
    margin-left: calc(20% - 1rem);
    margin-top: 5rem;

  }
}
</style>