Jelajahi Sumber

feat:增加我的预约逻辑

aamin 1 tahun lalu
induk
melakukan
1b3e3c8b84

+ 2 - 0
components.d.ts

@@ -13,6 +13,8 @@ declare module 'vue' {
     RouterView: typeof import('vue-router')['RouterView']
     SearchInput: typeof import('./src/components/SearchInput/index.vue')['default']
     VanField: typeof import('vant/es')['Field']
+    VanRadio: typeof import('vant/es')['Radio']
+    VanRadioGroup: typeof import('vant/es')['RadioGroup']
     VanSearch: typeof import('vant/es')['Search']
     VanSwipe: typeof import('vant/es')['Swipe']
     VanSwipeItem: typeof import('vant/es')['SwipeItem']

+ 1 - 1
src/api/api/sceneBooking/index.ts

@@ -1,5 +1,5 @@
 import axiosInstance from '@/api/request'
 export const sceneBookingApi = {
   getDisableDateAPi: () => axiosInstance.get(''),
-  getBookingTimeAPI: () => axiosInstance.get('')
+  getBookingTimeAPI: (date:string) => axiosInstance.get(`show/book/config?date=${date}`)
 }

TEMPAT SAMPAH
src/assets/images/booking-card.png


TEMPAT SAMPAH
src/assets/images/delect.png


+ 14 - 0
src/router/index.ts

@@ -58,6 +58,20 @@ const routes = [
   },
 
   {
+    path: '/booking/selectTime',
+    name: 'selectTime',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/ExhibitionService/BookingTime.vue')
+  },
+
+  {
+    path: '/booking/selectTime/bookInputInfo',
+    name: 'bookInputInfo',
+    //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏
+    component: () => import('@/views/ExhibitionService/bookInputInfo.vue')
+  },
+
+  {
     path: '/activeBooking',
     name: 'activeBooking',
     //使用import可以路由懒加载,如果不使用,太多组件一起加载会造成白屏

+ 2 - 0
src/stores/index.ts

@@ -6,6 +6,8 @@ export const useStore = defineStore('home', {
     return {
       // 原始数据
       dataAll: {} as any,
+      selectDate: '' as any,
+      selectTime: '' as any,
     }
   },
   // 相当于计算属性

+ 246 - 0
src/views/ExhibitionService/BookingTime.vue

@@ -0,0 +1,246 @@
+<script setup lang='ts'>
+import { sceneBookingApi } from '@/api/api/sceneBooking';
+import router from '@/router';
+import { useStore } from '@/stores';
+import { showToast } from 'vant';
+
+const dateArray = ref([] as any)
+const store = useStore()
+
+const getFutureDates = (numDays: number) => {
+  const datesArray = [];
+  const today = new Date();
+  const dateFormat = 'yyyy-MM-dd 星期X'; // 新增星期格式
+
+  for (let i = 0; i <= numDays; i++) {
+    const futureDate = new Date(today.getTime());
+    futureDate.setDate(today.getDate() + i);
+    const formattedDate = formatDate(futureDate, dateFormat);
+    datesArray.push({
+      date: formattedDate,
+      isDisabled: false
+    });
+  }
+  return datesArray;
+}
+
+const formatDate = (date: any, format: any) => {
+  const year = date.getFullYear();
+  const month = String(date.getMonth() + 1).padStart(2, '0');
+  const day = String(date.getDate()).padStart(2, '0');
+  const weekDay = getWeekDay(date);
+
+  return format.replace('yyyy', year)
+    .replace('MM', month)
+    .replace('dd', day)
+    .replace('X', weekDay);
+}
+
+const getWeekDay = (date: any) => {
+  const daysOfWeek = ['日', '一', '二', '三', '四', '五', '六'];
+  return daysOfWeek[date.getDay()];
+}
+
+
+const selectDate = ref('' as string)
+const selectTime = ref('' as string)
+
+const bookingTimeList = ref([] as any)
+const disableTimeList = ref([] as any)
+
+const noticeText = ref('' as any)
+
+
+// 获得可预约时间段
+const getBookingTime = async () => {
+  const res: any = await sceneBookingApi.getBookingTimeAPI(selectDate.value.slice(0, 10))
+  if (res.code == 0) {
+    bookingTimeList.value = res.data.time
+    disableTimeList.value = res.data.stopDate
+    noticeText.value = res.notice
+  } else {
+    showToast(res.msg)
+  }
+}
+
+watch(selectDate, () => {
+  // 获取time
+  getBookingTime()
+})
+
+watch(disableTimeList, () => {
+  dateArray.value = dateArray.value.map((item: any) => {
+    return {
+      ...item,
+      isDisabled: disableTimeList.value.includes(item.date.slice(0, 10))
+    }
+  })
+  console.log('发生变化', dateArray.value, disableTimeList.value)
+}, { immediate: true })
+
+const selectDateFu = (item: any) => {
+  if (item.isDisabled) {
+    showToast('该日期不可预约,请选择其他日期')
+  } else {
+    selectDate.value = item.date
+    selectTime.value = ''
+  }
+}
+
+const selectTimeFu = (item: any) => {
+  // router.go(0)
+  if (item.pcs === 0) {
+    showToast('该时段预约已满,请选择其他时段进行预约')
+  } else {
+    selectTime.value = item.time
+  }
+}
+
+const goInpitInfo = async () => {
+  const res: any = await sceneBookingApi.getBookingTimeAPI(selectDate.value.slice(0, 10))
+  if (res.code == 0) {
+    const selectTimeItem = res.data.time.filter((item: any) => {
+      return item.time === selectTime.value
+    })
+    if (selectTimeItem.length > 0 && selectTimeItem[0].pcs > 0) {
+
+      store.selectDate = selectDate.value
+      store.selectTime = selectTime.value
+
+      router.push({ name: 'bookInputInfo'});
+
+      // router.push({
+      //   name: 'bookInputInfo'
+      // })
+    } else {
+      router.go(0)
+    }
+  } else {
+    showToast(res.msg)
+  }
+
+}
+
+onBeforeMount(() => {
+  dateArray.value = getFutureDates(13)
+  console.log(store.selectDate)
+  if (store.selectDate != '' && store.selectTime != '') {
+    selectDate.value = store.selectDate
+    selectTime.value = store.selectTime
+  } else {
+    selectDate.value = dateArray.value[0].date
+  }
+})
+</script>
+
+<template>
+  <div class='time-box'>
+    <div class="date-select-box">
+      <div class="date-select-item" v-for="(item, index) in dateArray" :key="index"
+        :class="{ active: item.date === selectDate, disAble: item.isDisabled }" @click="selectDateFu(item)">
+        {{
+          item.date.slice(5) }}</div>
+    </div>
+    <div class="time-select-box">
+      <div class="time-select-item" v-for="(item, index) in bookingTimeList" :key="index"
+        :class="{ active: item.time === selectTime }" :style="{ color: item.pcs == 0 ? '#9D4F0B' : '' }"
+        @click="() => { selectTimeFu(item) }">
+        <div>{{ item.time }}</div>
+        <div>{{ item.pcs == 0 ? `预约已满` : `剩余${item.pcs}` }}</div>
+      </div>
+    </div>
+  </div>
+  <div class="online-box" v-if="selectDate != '' && selectTime != ''" @click="goInpitInfo()">发起预约</div>
+</template>
+
+<style lang='less' scoped>
+.time-box {
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  z-index: 2;
+  top: 0px;
+  left: 0px;
+  display: flex;
+  justify-content: start;
+  align-items: center;
+  background: #F1E9D4;
+  margin: 0;
+  box-sizing: border-box;
+  font-family: 'SourceHanSansCN-Regular';
+
+
+  .date-select-box {
+    width: 35%;
+    height: 100%;
+    overflow: auto;
+
+    .date-select-item {
+      width: 100%;
+      height: 80px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      color: #88866F;
+      margin-bottom: 3px;
+      background: #F7F3E8;
+    }
+
+    .active {
+      background: #E4DCC5;
+      color: #333333;
+    }
+
+    .disAble {
+      background: #E4DCC5;
+      color: rgba(51, 51, 51, 0.2);
+    }
+  }
+
+  .time-select-box {
+    width: 65%;
+    height: 100%;
+    overflow: auto;
+    padding: 15px;
+    box-sizing: border-box;
+
+    .time-select-item {
+      width: 100%;
+      height: 50px;
+      background: #F7F3E8;
+      border-radius: 5px;
+      color: #88866F;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 10px 15px;
+      box-sizing: border-box;
+      margin-bottom: 20px;
+    }
+
+    .active {
+      background: #E4DCC5;
+      color: #333333;
+    }
+  }
+}
+
+.online-box {
+  width: 80%;
+  height: 60px;
+  border-radius: 50px;
+  background: url(@/assets/images/onlineBg.png);
+  background-size: 100% 100%;
+  color: #F1E9D4;
+  position: fixed;
+  left: 50%;
+  transform: translateX(-50%);
+  bottom: 3vh;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  letter-spacing: 2px;
+  font-weight: bold;
+  z-index: 2;
+}
+</style>

+ 172 - 0
src/views/ExhibitionService/bookInputInfo.vue

@@ -0,0 +1,172 @@
+<script setup lang='ts'>
+import { useStore } from '@/stores';
+
+const store = useStore()
+const personList = ref([
+  {
+    bookDate: store.selectDate,
+    name: '',
+    num: '',
+    phone: '',
+    time: store.selectTime,
+    type: '身份证'
+  }
+])
+
+const deleteFu = (index: number) => {
+  personList.value.splice(index, 1)
+}
+
+const addPerson = () => {
+  personList.value.push({
+    bookDate: store.selectDate,
+    name: '',
+    num: '',
+    phone: '',
+    time: store.selectTime,
+    type: '身份证'
+  })
+}
+
+const submit = () => {
+
+}
+
+</script>
+
+<template>
+  <div class='input-box'>
+    <div class="input-card" v-for="(item, index) in personList" :key="index">
+      <div class="top">
+        <div>{{ '参观日期:' + item.bookDate.slice(0, 10) + ' ' + item.time }}</div>
+        <img @click="deleteFu(index)" src="@/assets/images/delect.png" alt="">
+      </div>
+      <div class="content">
+        <div>
+          <div class="label">参观人姓名:</div><input type="text" v-model="item.name" placeholder="请输入内容,不超过6个字">
+        </div>
+        <div>
+          <div class="label">参观人电话:</div><input type="text" v-model="item.phone" placeholder="请输入11个数字">
+        </div>
+        <div>
+          <div class="label">证件号:</div><van-radio-group v-model="item.type" direction="horizontal" shape="dot">
+            <van-radio name="身份证" checked-color="#9D4F0B">身份证</van-radio>
+            <van-radio name="社保卡" checked-color="#9D4F0B">社保卡</van-radio>
+          </van-radio-group>
+        </div>
+        <div>
+          <div class="label"></div><input type="text" v-model="item.num" placeholder="请输入18位证件编码">
+        </div>
+
+
+      </div>
+    </div>
+  </div>
+  <div class="btns">
+    <div class="add" @click="addPerson()">添加参观人</div>
+    <div class="submit" @click="submit()">提交</div>
+  </div>
+</template>
+
+<style lang='less' scoped>
+* {
+  box-sizing: border-box;
+}
+
+.input-box {
+  width: 100%;
+  min-height: 100%;
+  background: #F7F3E8;
+  padding: 20px 10px;
+
+  .input-card {
+    width: 100%;
+    padding: 20px 10px;
+    background: #9D4F0B;
+    border-radius: 15px;
+    font-family: 'SourceHanSansCN-Regular';
+    margin-bottom: 20px;
+
+    .top {
+      display: flex;
+      width: 100%;
+      justify-content: space-between;
+      color: #F7F3E8;
+      margin-bottom: 15px;
+
+      img {
+        width: 25px;
+      }
+    }
+
+    .content {
+      padding: 20px 15px;
+      background: url(@/assets/images/booking-card.png);
+      background-size: 100% 100%;
+
+      div {
+        display: flex;
+        height: 50px;
+        align-items: center;
+        color: #88866F;
+
+        .label {
+          width: 30%;
+          text-align: center;
+          color: #333333;
+          font-family: 0.9em;
+        }
+
+        input {
+          width: 70%;
+          background: #FFFDF6;
+          border: 1px solid #9D4F0B;
+          color: #88866F;
+          border-radius: 5px;
+          height: 75%;
+          padding: 0 5px;
+          font-size: 0.9em;
+        }
+      }
+
+    }
+
+  }
+
+}
+
+.btns {
+  width: 90%;
+  position: fixed;
+  bottom: 20px;
+  display: flex;
+  justify-content: space-between;
+  left: 50%;
+  transform: translateX(-50%);
+
+  div {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .add {
+    width: 35%;
+    height: 5vh;
+    background: #FFFDF6;
+    border: 1px solid #9D4F0B;
+    border-radius: 50px;
+    color: #88866F;
+  }
+
+  .submit {
+    width: 60%;
+    height: 5vh;
+    background: url(@/assets/images/onlineBg.png);
+    background-size: 100% 100%;
+    // border: 1px solid #9D4F0B;
+    border-radius: 50px;
+    color: #F7F3E8;
+  }
+}
+</style>

+ 164 - 10
src/views/ExhibitionService/bookedList.vue

@@ -1,24 +1,178 @@
 <script setup lang='ts'>
-import BookingTime from './components/BookingTime.vue'
+import { useStore } from '@/stores';
+
+// import { json } from 'stream/consumers';
+// import BookingTime from './BookingTime.vue'
 
 const bookedList = ref([] as any)
 
+const router = useRouter()
+const store = useStore()
 // 立即预约-时段选择
-const showBookingTime = ref(false)
+const goSelectTime = () => {
+  router.push({
+    name:'selectTime'
+  })
+}
+
+onMounted(() => {
+  // 清除之前的预约选择记录
+  store.selectDate = ''
+  store.selectTime = ''
+  bookedList.value = [
+    {
+      bookDate: '2024-04-16',
+      bookId: '1',
+      createTime: '2024-04-16 16:46:00',
+      creatorId: null,
+      creatorName: '',
+      id: 1,
+      name: '小明',
+      pcs: 2,
+      phone: '',
+      rtf: JSON.parse('[{"bookDate":"2024-02-01","name":"小明","num":"1111111","time":"9:00-1:00","type":"身份证"},{"bookDate":"2024-02-01","name":"小明2","num":"222222","time":"9:00-1:00","type":"社保卡"}]'),
+      status: 0,
+      time: '9:00-1:00',
+      updateTime: '2024-04-16 16:46:00'
+    },
+    {
+      bookDate: '2024-04-16',
+      bookId: '1',
+      createTime: '2024-04-16 16:46:00',
+      creatorId: null,
+      creatorName: '',
+      id: 1,
+      name: '小明',
+      pcs: 2,
+      phone: '12333',
+      rtf: JSON.parse('[{"bookDate":"2024-02-01","name":"小明","num":"1111111","time":"9:00-1:00","type":"身份证"},{"bookDate":"2024-02-01","name":"小明2","num":"222222","time":"9:00-1:00","type":"社保卡"}]'),
+      status: 1,
+      time: '9:00-1:00',
+      updateTime: '2024-04-16 16:46:00'
+    },
+    
+  ]
+})
 </script>
 
 <template>
   <div class='booked-box'>
-    <div>我的预约</div>
-    <div v-if="bookedList.length == 0">暂无预约</div>
+    <div class="title">
+      <img src="@/assets/images/cicle.png" alt="">
+      <div class="title-content">我的预约</div>
+    </div>
+    <div class="no-data" v-if="bookedList.length == 0">暂无预约</div>
     <div v-else>
-      <!-- <div class="booking-card" v-for="(item, index) in bookedList" :key="index" >
-        <div>{{ item. }}</div>
-      </div> -->
+      <div class="booking-card" v-for="(item, index) in bookedList" :key="index" @click="go">
+        <div>参观日期:{{ `${item.bookDate} ${item.time}` }}</div>
+        <div>当前状态:<span :style="{color:item.status == 0 ?'' :'#E3C956'}" >{{ item.status == 0 ? '未验证' : '已验证' }}</span></div>
+        <div class="info-box">
+          <div>参观人姓名:{{ item.name }}</div>
+          <div>参观人电话:{{ bookedList[index].rtf[0].phone }}</div>
+          <div>{{ `${bookedList[index].rtf[0].type}号:${bookedList[index].rtf[0].num}` }}</div>
+        </div>
+      </div>
     </div>
-    <div class="booking-btn" @click="showBookingTime = true">发起预约</div>
-    <BookingTime v-show="showBookingTime" />
+    <div class="online-box" @click="goSelectTime">发起预约</div>
+    <!-- <BookingTime v-show="showBookingTime" /> -->
   </div>
 </template>
 
-<style lang='less' scoped></style>
+<style lang='less' scoped>
+* {
+  box-sizing: border-box;
+}
+
+.booked-box {
+  width: 100%;
+  min-height: 100%;
+  background: #F7F3E8;
+  padding: 40px 20px;
+
+  .title {
+    font-size: 1.4em;
+    color: #333333;
+    font-weight: bold;
+    position: relative;
+    // line-height: 1.6em;
+    display: flex;
+    align-items: flex-end;
+    margin-bottom: 10px;
+
+    img {
+      position: absolute;
+      left: 0;
+      top: 0;
+      height: 1.6em;
+    }
+
+    .title-content {
+      // position: absolute;
+      position: relative;
+      left: 0;
+      top: 0;
+      height: 1.4em;
+      z-index: 2;
+      line-height: 1.6em;
+      color: #333333;
+      margin-top: 1%;
+      font-family: SourceHanSansCN-Bold;
+
+    }
+
+  }
+
+  .no-data {
+    color: #88866F;
+    font-family: SourceHanSansCN-Regular;
+  }
+
+  .booking-card {
+    width: 100%;
+    border-radius: 15px;
+    padding: 15px;
+    color: #F7F3E8;
+    font-family: SourceHanSansCN-Regular;
+    line-height: 1.5em;
+    background: #9D4F0B;
+    margin-bottom: 15px;
+
+    div {
+      height: 40px;
+      font-family: SourceHanSansCN-Regular;
+    }
+
+    .info-box {
+      width: 100%;
+      height: auto;
+      padding: 20px 10px;
+      background: url(@/assets/images/booking-card.png);
+      background-size: 100% 100%;
+      color: #333333;
+      // margin-top: 10px;
+
+
+    }
+  }
+
+  .online-box {
+    width: 80%;
+    height: 60px;
+    border-radius: 50px;
+    background: url(@/assets/images/onlineBg.png);
+    background-size: 100% 100%;
+    color: #F1E9D4;
+    position: fixed;
+    left: 50%;
+    transform: translateX(-50%);
+    bottom: 3vh;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    letter-spacing: 2px;
+    font-weight: bold;
+    z-index: 2;
+  }
+
+}
+</style>

+ 0 - 91
src/views/ExhibitionService/components/BookingTime.vue

@@ -1,91 +0,0 @@
-<script setup lang='ts'>
-import { sceneBookingApi } from '@/api/api/sceneBooking';
-
-const dateArray = ref([] as any)
-
-
-const getFutureDates = (numDays: number) => {
-  const datesArray = [];
-  const today = new Date();
-  const dateFormat = 'yyyy-MM-dd 星期X'; // 新增星期格式
-
-  for (let i = 0; i <= numDays; i++) {
-    const futureDate = new Date(today.getTime());
-    futureDate.setDate(today.getDate() + i);
-    const formattedDate = formatDate(futureDate, dateFormat);
-    datesArray.push({
-      date: formattedDate
-    });
-  }
-
-  return datesArray;
-}
-
-const formatDate = (date: any, format: any) => {
-  const year = date.getFullYear();
-  const month = String(date.getMonth() + 1).padStart(2, '0');
-  const day = String(date.getDate()).padStart(2, '0');
-  const weekDay = getWeekDay(date);
-
-  return format.replace('yyyy', year)
-    .replace('MM', month)
-    .replace('dd', day)
-    .replace('X', weekDay);
-}
-
-const getWeekDay = (date: any) => {
-  const daysOfWeek = ['日', '一', '二', '三', '四', '五', '六'];
-  return daysOfWeek[date.getDay()];
-}
-
-// 获取禁止预约日期,并加上字段
-const getDisableDate = async () => {
-  const res = await sceneBookingApi.getDisableDateAPi()
-  if (res.data.code === 0) {
-    // 遍历禁止日期
-    res.data.forEach((item: any) => {
-      dateArray.value.forEach((dateItem: any) => {
-        if (item === dateItem.date) {
-          dateItem.disable = true
-        }
-      })
-    })
-  }
-}
-
-// const bookingTimeList = ref([] as any)
-
-// 获得可预约时间段
-// const getBookingTime = async () => {
-//   const res = await sceneBookingApi.getBookingTimeAPI()
-
-// }
-
-onBeforeMount(() => {
-  dateArray.value = getFutureDates(13)
-  getDisableDate()
-  // console.log(getFutureDates(13))
-})
-</script>
-
-<template>
-  <div class='time-box'>
-
-  </div>
-</template>
-
-<style lang='less' scoped>
-.time-box {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0px;
-  left: 0px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  background: gray;
-  margin: 0;
-  box-sizing: border-box;
-}
-</style>