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

相关推荐
工藤学编程15 小时前
零基础学AI大模型之CoT思维链和ReAct推理行动
前端·人工智能·react.js
徐同保15 小时前
上传文件,在前端用 pdf.js 提取 上传的pdf文件中的图片
前端·javascript·pdf
怕浪猫15 小时前
React从入门到出门第四章 组件通讯与全局状态管理
前端·javascript·react.js
博主花神15 小时前
【React】扩展知识点
javascript·react.js·ecmascript
欧阳天风15 小时前
用setTimeout代替setInterval
开发语言·前端·javascript
EndingCoder15 小时前
箭头函数和 this 绑定
linux·前端·javascript·typescript
郑州光合科技余经理15 小时前
架构解析:同城本地生活服务o2o平台海外版
大数据·开发语言·前端·人工智能·架构·php·生活
沐墨染15 小时前
大型数据分析组件前端实践:多维度检索与实时交互设计
前端·elementui·数据挖掘·数据分析·vue·交互
郑州光合科技余经理15 小时前
开发实战:海外版同城o2o生活服务平台核心模块设计
开发语言·git·python·架构·uni-app·生活·智慧城市
xkxnq15 小时前
第一阶段:Vue 基础入门(第 11 天)
前端·javascript·vue.js