手写预约上门取件功能

145 阅读2分钟

本文使用的技术栈是uniapp的vue版本 直接上干货,所有的核心代码讲解已在注释中添加,自取

HTML结构

<template>
  <u-popup :show="show" :round="10" mode="bottom" @close="close" @open="open">
    <view class="content">
      <view class="title" hover-class="none" hover-stop-propagation="false">
        <view
          class="title-text"
          hover-class="none"
          hover-stop-propagation="false"
        >
          选择取件时间
        </view>
        <view class="desc" hover-class="none" hover-stop-propagation="false">
          准时上门
        </view>
        <view class="closeIcon" @click="close">
          <u-icon name="close" size="16" bold color="#000"></u-icon>
        </view>
      </view>
      <view class="bottomView">
        <scroll-view scroll-y class="left">
          <view
            class="left-item"
            :class="[leftItemActive == item.val ? 'left-item-active' : '']"
            v-for="item in leftList"
            :key="item.val"
            @click="leftIteClick(item)"
          >
            {{ item.label }}
          </view>
        </scroll-view>
        <scroll-view scroll-y class="right">
          <view
            class="right-item"
            v-for="item in timeList"
            :key="item"
            @click="rightItemClick(item)"
          >
            <view
              class="item-text"
              :class="[
                rightTimeActive == item
                  ? 'right-item-active'
                  : judgeText(item)
                  ? 'left-item-disable'
                  : '',
              ]"
              >{{ item }}</view
            >
            <view class="item-state"
              ><u-icon
                v-if="!judgeText(item) && rightTimeActive == item"
                name="checkmark-circle"
                color="#15be77"
                size="20"
                style="margin-top: 2px"
              ></u-icon>
              <text
                v-if="judgeText(item)"
                style="color: #c0c0c0; font-size: 0.7rem"
              >
                已过期
              </text></view
            >
          </view>
        </scroll-view>
      </view>
    </view>
  </u-popup>
</template>

方法

import { ref, watch } from "vue";
  import moment from "moment";
  import { onShow } from "@dcloudio/uni-app";
  const show = ref(false);
  const leftList = ref([
    // 左侧选择的时间列表数据集合。
    {
      label: "今天",
      val: 1,
    },
    {
      label: "明天",
      val: 2,
    },
    {
      label: "后天",
      val: 3,
    },
  ]);
  const leftItemActive = ref(); //左侧时间选中列表标志
  const leftTime = ref(); //与右侧时间进行交互
  const timeList = ref([
    //右侧时间列表
    "09:00 ~ 11:00",
    "11:00 ~ 13:00",
    "13:00 ~ 17:00",
    "17:00 ~ 19:00",
  ]);
  const rightTimeActive = ref(); //右侧选中标志
  const emit = defineEmits<{
    (e: "timeClick", value: any);
  }>();
  watch(leftItemActive, (newVal, oldVal) => {
  //切换左侧时间时,清空右侧选择状态
    rightTimeActive.value = "";
  });
  const close = () => {
    show.value = false;
  };
  const open = () => {
    show.value = true;
  };
  const leftIteClick = (item) => {
  //给左侧添加选中样式以及储存选中的变量,与右侧交互时使用
    leftItemActive.value = item.val;
    switch (item.val) {
      case 0:
        leftTime.value = moment(new Date())
          .subtract(1, "days")
          .format("YYYY-MM-DD");
        break;
      case 1:
        leftTime.value = moment(new Date()).format("YYYY-MM-DD");
        break;
      case 2:
        leftTime.value = moment(new Date()).add(1, "days").format("YYYY-MM-DD");
        break;
    }
  };
  const judgeText = (item) => {
  //判断时间是否超时
    let arr = item.split("~");
    //获取预约时间段最早的时刻
    let time = leftTime.value + " " + arr[0];
    与现在的时间比较
    if (moment(time).diff(moment(new Date()), "minutes") < 0) {
      return true;
    } else {
      return false;
    }
  };
  const rightItemClick = (item) => {
    if (judgeText(item)) {
    //终止已过期时间的后续操作
      return;
    }
    //添加右侧选中事件样式
    rightTimeActive.value = item;
    //抛出的数据
    let returnData = leftList.value[Number(leftItemActive.value)-1].label + " " + item;
    emit("timeClick", returnData);
    close()
  };
  onShow(() => {
  //获取每天最晚的预约时间
    let curTime = moment(new Date()).format("YYYY-MM-DD") + " " + "17:00";
    console.log(moment(new Date()).diff(moment(curTime), "minutes"));
   //进入页面自动选中左侧的时间
    if (moment(new Date()).diff(moment(curTime), "minutes") > 0) {
      leftIteClick(leftList.value[1]);
    } else {
      leftIteClick(leftList.value[0]);
    }
  });
  defineExpose({ open });

样式

.title {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: calc(100% - 3rem);
  position: relative;
  padding: 1.5rem;
  .title-text {
    color: black;
    font-size: 1.4rem;
    font-weight: 800;
    margin-bottom: 0.5rem;
  }
  .desc {
    color: $sch-theme-color;
    font-size: 0.8rem;
  }
  .closeIcon {
    position: absolute;
    top: 2rem;
    right: 1.5rem;
  }
}
.bottomView {
  display: flex;
  height: calc(100% - 5.7rem);
  .left {
    width: 30%;
    height: 100%;
    display: flex;
    flex-direction: column;
    .left-item {
      width: 100%;
      height: 3rem;
      background-color: #cec6c62e;
      color: black;
      text-align: center;
      line-height: 3rem;
      font-size: 1rem;
    }
  }
  .right {
    flex: 1;
    .right-item {
      width: calc(100% - 2rem);
      height: 3rem;
      padding: 0 1rem;
      display: flex;
      justify-content: space-between;
      align-items: center;
      border-bottom: 1px solid #acaaaa2e;
    }
  }
}
// 点击样式
.left-item-active {
  background-color: #fff !important;
  color: $sch-theme-color !important;
}
.left-item-disable {
  color: $uni-text-color-disable;
}
.right-item-active {
  color: $sch-theme-color;
}