time-select.vue 5.2 KB
<template>
  <view class="time-select">
    <view class="tab-container">
      <view
        class="tab-item"
        :class="{ active: currentDateType === 'week' }"
        @click="switchDateType('week')"
      >

      </view>
      <view
        class="tab-item"
        :class="{ active: currentDateType === 'month' }"
        @click="switchDateType('month')"
      >

      </view>
    </view>

    <view class="date-stepper">
      <view class="arrow-icon" @click="handlePrev">
        <up-icon name="arrow-left" color="#333" size="12" bold></up-icon>
      </view>
      <view class="date-display"> {{ dateRangeText }} </view>
      <!-- 修改: 根据 isNextDisabled 判断是否隐藏下一个按钮 -->
      <view class="arrow-icon" @click="handleNext" v-if="!isNextDisabled">
        <up-icon name="arrow-right" color="#333" size="12" bold></up-icon>
      </view>
      <view v-else class="occupy"></view>
    </view>
  </view>
</template>

<script setup>
  import { ref, computed } from 'vue';

  // 当前日期类型: 'week' | 'month'
  const currentDateType = ref('week');
  // 基准日期,用于计算范围
  const baseDate = ref(new Date());

  // 格式化日期辅助函数 YYYY/MM/DD
  const formatDate = (date) => {
    const y = date.getFullYear();
    const m = String(date.getMonth() + 1).padStart(2, '0');
    const d = String(date.getDate()).padStart(2, '0');
    return `${y}/${m}/${d}`;
  };

  // 计算显示的日期范围文本
  const dateRangeText = computed(() => {
    const current = new Date(baseDate.value);

    if (currentDateType.value === 'week') {
      // 计算本周的周一和周日
      const day = current.getDay();
      const diffToMonday = day === 0 ? -6 : 1 - day; // 调整到周一

      const startOfWeek = new Date(current);
      startOfWeek.setDate(current.getDate() + diffToMonday);

      const endOfWeek = new Date(startOfWeek);
      endOfWeek.setDate(startOfWeek.getDate() + 6);

      return `${formatDate(startOfWeek)} - ${formatDate(endOfWeek)}`;
    } else {
      // 计算本月的一号和最后一天
      const startOfMonth = new Date(current.getFullYear(), current.getMonth(), 1);
      const endOfMonth = new Date(current.getFullYear(), current.getMonth() + 1, 0);

      return `${formatDate(startOfMonth)} - ${formatDate(endOfMonth)}`;
    }
  });

  // 新增: 计算下一个日期是否不可用(即是否为未来日期)
  const isNextDisabled = computed(() => {
    const newDate = new Date(baseDate.value);
    if (currentDateType.value === 'week') {
      newDate.setDate(newDate.getDate() + 7);
    } else {
      newDate.setMonth(newDate.getMonth() + 1);
    }

    // 重置时分秒进行比较
    const now = new Date();
    now.setHours(0, 0, 0, 0);
    const checkDate = new Date(newDate);
    checkDate.setHours(0, 0, 0, 0);

    return checkDate > now;
  });

  // 切换周/月
  const switchDateType = (type) => {
    currentDateType.value = type;
  };

  // 上一段时间
  const handlePrev = () => {
    const newDate = new Date(baseDate.value);
    if (currentDateType.value === 'week') {
      newDate.setDate(newDate.getDate() - 7);
    } else {
      newDate.setMonth(newDate.getMonth() - 1);
    }
    baseDate.value = newDate;
  };

  // 下一段时间
  const handleNext = () => {
    // 虽然按钮已隐藏,但保留逻辑判断以防直接调用或其他边界情况
    if (isNextDisabled.value) {
      return;
    }

    const newDate = new Date(baseDate.value);
    if (currentDateType.value === 'week') {
      newDate.setDate(newDate.getDate() + 7);
    } else {
      newDate.setMonth(newDate.getMonth() + 1);
    }

    baseDate.value = newDate;
  };
</script>

<style scoped lang="scss">
  .time-select {
    flex-shrink: 0; /* 修改: 防止顶部选择器被压缩 */
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;

    // 周月切换 Tab
    .tab-container {
      width: 100%;
      height: 72rpx;
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 8rpx;
      background-color: #eee;
      border-radius: 12rpx;
      padding: 6rpx;
      box-sizing: border-box;

      .tab-item {
        display: flex;
        align-items: center;
        justify-content: center;
        color: #8c8c8c;
        font-size: 28rpx;
        transition: all 0.2s ease;

        &.active {
          background-color: #ffffff;
          color: #1a1a1a;
          font-weight: 600;
          border-radius: 8rpx;
          box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
        }
      }
    }
    // 日期翻页器
    .date-stepper {
      margin-top: 32rpx;
      display: flex;
      align-items: center;
      justify-content: space-between;
      width: 100%;

      .date-display {
        margin: 0 40rpx;
        font-size: 28rpx;
        font-weight: 500;
        color: #333;
        font-variant-numeric: tabular-nums; // 防止数字切换时抖动
      }

      .arrow-icon {
        width: 56rpx;
        height: 56rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: #fff;
        border-radius: 50%;
        transition: background-color 0.2s;
      }
    }
    .occupy {
      width: 56rpx;
      height: 56rpx;
    }
  }
</style>