uniapp 简易自定义日历

注:此日历是根据接口返回的日期自动对应星期的,返回的数据中也包含星期,其实就是一个div自定义,可根据自己需求更改;
在这里插入图片描述
1、组件代码 gy-calendar-self.vue

<template>
  <view class="calendar">
	<view class="selsct-date">
		请选择预约日期
	</view>
    <!-- 日历头部,显示星期 -->
    <view class="weekdays">
      <view v-for="day in weekDays" :key="day" class="weekday">{{ day }}</view>
    </view>

    <!-- 日历主体 -->
    <view class="calendar-body">
      <view v-for="(week, weekIndex) in calendarData" :key="weekIndex" class="week">
        <view
          v-for="(day, dayIndex) in week"
          :key="dayIndex"
          @click="selectDate(day)"
          :class="{'has-schedule': day.schState !== 0 }"
          class="day"
          :style="{ width: cellWidth + 'rpx' }"
        >
          <view class="day-label">{{ day.dateLabel }}</view>
          <view v-if="day.day"
			class="day-status-has"
			:class="[day.info == '有' ? 'day-status-has' : day.info == '满' ? 'day-status-over' : 'day-status-none']"
			>
			  {{day.info}}
		  </view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  props: {
    scheduleData: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      weekDays: ["日", "一", "二", "三", "四", "五", "六"],
      calendarData: [],
      selectedDate: null,
      cellWidth: 100, // 单位为rpx
    };
  },
  created() {
    this.generateCalendar();
  },
  methods: {
    generateCalendar() {
      const startDate = new Date(this.scheduleData[0].dateWork);
      const endDate = new Date(this.scheduleData[this.scheduleData.length - 1].dateWork);

      let currentDate = new Date(startDate);
      let week = [];

      if (currentDate.getDay() !== 0) {
        for (let i = 0; i < currentDate.getDay(); i++) {
          week.push({});
        }
      }

      while (currentDate <= endDate) {
        const dateWork = currentDate.toISOString().split('T')[0];
		const schState = this.getScheduleState(dateWork);
		const weekDay = currentDate.getDay();
		const day = currentDate.getDate();
	
		const dayObject = { date: dateWork, dateLabel: this.formatDateLabel(currentDate), schState, weekDay, day };
	
		week.push(dayObject);
	
		if (currentDate.getDate() === new Date().getDate()) {
		  // Check if the current date matches the current date
		  this.selectedDate = dayObject;
		}
	
		if (currentDate.getDay() === 6) {
		  this.calendarData.push(week);
		  week = [];
		}
	
		currentDate.setDate(currentDate.getDate() + 1);
      }

       if (week.length > 0) {
          this.calendarData.push(week);
        }
      
        // Check if the last week array has fewer than 7 elements
        const lastWeek = this.calendarData[this.calendarData.length - 1];
        const remainingCells = 7 - lastWeek.length;
      
        if (remainingCells > 0) {
          // Add empty objects to fill the remaining cells
          for (let i = 0; i < remainingCells; i++) {
            lastWeek.push({});
          }
        }
      
        this.calendarData.forEach((item) => {
          if (item && item.length > 0) {
            item.forEach((s) => {
              s.info = s.schState == 1 ? "有" : s.schState == 0 ? "满" : "无";
			  s.pkSchs = s.pkSchs
            });
          }
        });
	  console.log(this.calendarData, 'this.calendarData')
    },
    getScheduleState(date) {
      const scheduleItem = this.scheduleData.find(item => item.dateWork === date);
      return scheduleItem ? scheduleItem.schState : 0;
    },
    selectDate(day) {
      this.selectedDate = day;
	  const additionalData = this.scheduleData.find(item => item.dateWork === day.date);
	  console.log(additionalData, 'additionalData')
	  this.$emit('selceted', additionalData);
      // this.$emit('selceted', day)
    },
    isDateSelected(day) {
      return this.selectedDate && day.date === this.selectedDate.date;
    },
    formatDateLabel(date) {
	  const month = date.getMonth() + 1;
	  const day = date.getDate();
	  return `${this.padZero(month)}-${this.padZero(day)}`;
	},
	padZero(num) {
	  return num < 10 ? `0${num}` : `${num}`;
	},
  },
};
</script>

<style scoped lang="scss">
.calendar {
  display: flex;
  flex-direction: column;
  font-family: Arial, sans-serif;
  .selsct-date {
	  text-align: center;
	  margin: 20rpx auto;
  }
}

.weekdays {
  display: flex;
  justify-content: space-around;
  // background-color: #f2f2f2;
  padding: 10rpx;
  // border-bottom: 1px solid #ccc;

  .weekday {
    text-align: center;
    padding: 5rpx;
    font-weight: bold;
    flex: 1;
  }
}

.calendar-body {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  padding: 0 10rpx;
}

.day {
  position: relative;
  text-align: center;
  padding: 10rpx 0;
  cursor: pointer;
  box-sizing: border-box;
  flex: 1;

  .day-label {
    font-size: 28rpx;
    // font-weight: bold;
  }
  
  .day-status-has {
	width: 40rpx;
	height: 40rpx;
	color: #4AB039;
	opacity: 0.8;
	background-color: #EDF8EC;
	border-radius: 50%;
	text-align: center;
	line-height: 40rpx;
	border-radius: 50%;
	box-sizing: border-box;
	margin: auto;
  }
  
  .day-status-over {
	width: 40rpx;
	height: 40rpx;
	color: #EA4070;
	opacity: 0.8;
	background-color: #EFEFEF;
	border-radius: 50%;
	text-align: center;
	line-height: 40rpx;
	border-radius: 50%;
	box-sizing: border-box;
	margin: auto;
  }
  
  .day-status-none {
	width: 40rpx;
	height: 40rpx;
	color: rgb(102, 102, 102);
	opacity: 0.8;
	background-color: #EFEFEF;
	border-radius: 50%;
	text-align: center;
	line-height: 40rpx;
	border-radius: 50%;
	box-sizing: border-box;
	margin: auto;
  }

  &.selected {
    background-color: #85af8b;
    color: #fff;
  }
}

.week {
  display: flex;
  flex-wrap: wrap;
}
</style>

2、引入

<view class="calendar-box" v-if="showCalendar">
	<u-popup v-model="showCalendar" safe-area-inset-bottom mode="bottom">
		<data-calendar :scheduleData="selectedList" @selceted="selcetedDate"></data-calendar>
	</u-popup>
</view>

最后附上返回的数据格式:
只需要 dateWork 和 week
在这里插入图片描述

在这里插入图片描述

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱喝冰可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值