uniapp 简易自定义日历

注:此日历是根据接口返回的日期自动对应星期的,返回的数据中也包含星期,其实就是一个div自定义,可根据自己需求更改;

1、组件代码 gy-calendar-self.vue

javascript 复制代码
<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、引入

javascript 复制代码
<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

相关推荐
吃杠碰小鸡19 分钟前
commitlint校验git提交信息
前端
虾球xz1 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇1 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒1 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员1 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐1 小时前
前端图像处理(一)
前端
程序猿阿伟1 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒1 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪2 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背2 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript