select-datepicker.vue 6.43 KB
<template>
  <view class="select-datepicker">
    <view class="grid">
      <view class="grid-scroll">
        <template v-for="(item, key) in dateList">
          <view :class="['grid-item', activeTab.includes(item.value) && 'grid-item-selected']" :key="key" @click="handleDate(item)">
            <text class="grid-title">{{item.title}}</text>
            <text class="grid-subtitle">{{item.subtitle}}</text>
            <text class="grid-info">{{item.info}}</text>
          </view>
        </template>
      </view>
      <view class="grid-item grid-item-more" @click="handleDate">
        <image class="grid-overlay" :src="formatImagePath('zz')"/>
        <image class="grid-icon" src="https://zeyi-tms-product.oss-cn-hangzhou.aliyuncs.com/app/revision/date2.png"/>
        <text class="grid-more">更多</text>
      </view>
    </view>
    <u-calendar 
      :show="show" 
      :showMark="false" 
      :showSubtitle="false"
      :defaultDate="defaultDate"
      :monthNum="4"
      mode="range"
      color="#2673FB" 
      title="选择日期" 
      :confirmText="confirmText" 
      round="13" 
      closeOnClickOverlay
      @confirm="handleConfirm" 
      @close="hanldeClose"
    ></u-calendar>
  </view>
</template>

<script>
import dayjs from 'dayjs'
import { getWeek } from '@/utils/dayjs-ext'

export default {
  props: {
    // [开始日期, 结束日期]
    value: {
      type: Array,
      default: () => []
    },
    // 货源数量
    counts: {
      type: Object,
      default: () => ({})
    },
    // 开始日期
    startDate: String,
    // 结束日期
    endDate: String,
  },
  data() {
    return {
      show: false,
      defaultDate: [],
      activeTab: [],
    }
  },
  watch: {
    value(v) {
      if (v?.length) {
        // 深拷贝,防止循环引用
        this.defaultDate = this.activeTab = [...v];
        // 日期排序
        this.hanldeSort(this.activeTab);
      }
    }
  },
  computed: {
    dateList({ counts }) {
      const list = [];
      while(list.length < 7){
        const date = dayjs().add(list.length, 'day');
        list.push({
          title: date.format('MM-DD'),
          subtitle: list.length < 3 ? { 0: '今天', 1: '明天', 2: '后天' }[list.length] : getWeek(date.day()),
          info: counts[date.format('YYYY-MM-DD')] ? counts[date.format('YYYY-MM-DD')] + '单' : '',
          value: date.format('YYYY-MM-DD')
        })
      }
      return list
    },
    confirmText({ activeTab, counts }) {
      const count = activeTab.reduce((pre, date) =>{
        return pre += counts[date] || 0;
      }, 0)
      return '确定' + (count ? '(' + count + '单) ' : '')
    }
  },
  methods: {
    handleDate(item) {
      if (!item.value) {
        wx.hideTabBar();
        this.show = true;
        return 
      }
      this.activeTab = [item.value];
      // if (this.activeTab.length >= 2) {
      //   this.activeTab = [item.value];
      // } else if (this.activeTab.includes(item.value)){
      //   // 双击取消
      //   const index = this.activeTab.findIndex(v => v === item.value);
      //   index > -1 && this.activeTab.splice(index, 1);
      // } else {
      //   // 单击选中
      //   this.activeTab.push(item.value);
      // }
      if (this.activeTab.length >= 1 || this.activeTab.length === 0) {
        this.hanldeSort(this.activeTab);
        this.handleEmit(this.activeTab);
      }
    },
    handleConfirm(dateList) {
      this.handleEmit(dateList);
      this.hanldeClose();
    },
    hanldeClose() {
      this.show = false;
      setTimeout(wx.showTabBar, 200);
    },
    hanldeSort(dateList) {
      if(!Array.isArray(dateList)) return [];
      if (dateList.length >= 2) {
        // 日期排序
        dateList.sort((a, b) => dayjs(a).unix() - dayjs(b).unix());
        // 日期补位
        const diff = dayjs(dateList[dateList.length - 1]).diff(dateList[0], 'day');
        if (diff > 1) {
          let i = 0
          while(dateList.length < diff + 1) {
            const date = dayjs(dateList[i]).add(1, 'day').format('YYYY-MM-DD');
            dateList.splice(++i, 0, date);
          }
        }
      }
    },
    handleEmit(dateList) {
      const startDate = dateList[0];
      const endDate = dateList[dateList.length - 1];
      this.$emit('update:startDate', startDate);
      this.$emit('update:endDate', endDate);
      this.$emit('input', dateList);
      this.$emit('click');
    }
  }
}
</script>

<style lang="scss">
.select-datepicker {
  padding: 0 6px 17px 12px;
  background: #2673FB;
  .grid {
    display: flex;
    align-items: flex-end;
    .grid-scroll {
      flex: 1;
      height: 58px;
      overflow-y: auto;
      display: flex;
      align-items: flex-end;
    }
    .grid-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      width: 60px;
      min-width: 60px;
      height: 40px;
      background: #4A8AFB;
      border-radius: 7px;
      position: relative;
      margin-right: 7px;
      border: 1px solid #4A8AFB;
      &:last-child {
        margin-right: 0;
      }
    }
    .grid-item-selected {
      background: #FFFFFF;
      border: 1px solid #2673FB;
      .grid-title  {
        color: #2B2A27;
      }
      .grid-subtitle {
        color: #2B2A27;
      }
    }
    .grid-item-more {
      width: 40px;
      min-width: 40px;
      background: transparent;
      border: 1px solid transparent;
    }
    .grid-title {
      font-size: 12px;
      font-family: PingFangSC, PingFang SC;
      font-weight: 600;
      color: white;
      line-height: 17px;
    }
    .grid-subtitle {
      font-size: 10px;
      font-family: PingFangSC, PingFang SC;
      font-weight: 600;
      color: white;
      line-height: 14px;
    }
    .grid-info {
      padding: 0 4px;
      font-size: 10px;
      font-family: PingFangSC, PingFang SC;
      font-weight: 400;
      color: #604300;
      line-height: 16px;
      border-radius: 8px 8px 8px 0;
      background: linear-gradient(180deg, #FFF013 0%, #FFDD08 100%);
      box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(38,115,251,0.04);
      position: absolute;
      top: -14px;
      right: 0;
      min-width: 20px;
    }
    .grid-overlay {
      position: absolute;
      left: -13px;
      width: 13px;
      height: 70px;
    }
    .grid-icon {
      width: 21px;
      height: 21px;
      margin-bottom: 4px;
    }
    .grid-more {
      font-size: 10px;
      font-family: PingFangSC, PingFang SC;
      font-weight: 400;
      color: #FFFFFF;
      line-height: 10px;
    }
  }
}
</style>