日历组件 vue 小程序

<template>
    <view>
      <view class="tip-title" v-if="tipShow">{{tipTitle}}view>
      <view class="calendar-month">
        <u-icon name="arrow-left-double" class="uicon-padding" @click="changeDate('beforeYear')"/>
        <u-icon name="arrow-left" class="uicon-padding" @click="changeDate('beforeMonth')"/>
        <view>{{ dynamicDate }}view>
        <u-icon name="arrow-right" class="uicon-padding" @click="changeDate('lastMonth')"/>
        <u-icon name="arrow-right-double"  class="uicon-padding" @click="changeDate('lastYear')"/>
      view>
      <view class="table-header">
        <view
          v-for="(item ,index) in tableHead"
          :key="index"
          :style="[headStyle]"
          class="table-header_col table-content_border table-flex_center"
        >{{ item }}view>
      view>
      <view class="table-header">
        <view
          v-for="(dateItem, index) in dateSource"
          :key="index"
          @click="selectedDate(dateItem)"
          :class="{
            'table-active':selectDate === dateItem.date || dateItem.checked,
            'calendar-pointer':isOpera
          }"
          class="table-header_col table-content_border table-text_align"
        >
          <view>{{ dateItem && dateItem.day || '' }}view>
          <view class="table-range" v-if="rangVal[0] && rangVal[0].date === dateItem.date">开始view>
          <view class="table-range" v-else-if="rangVal[1] && rangVal[1].date === dateItem.date">结束view>
          <view v-if="dateItem">{{ dateItem.range }}view>
        view>
      view>
    view>
template>
<script>
import moment from 'moment'
export default {
  props: {
    // 日期标题
    tipTitle: {
      type: String,
      default: '请选择日期'
    },
    // 表头
    tableHead: {
      type: Array,
      default: () => {
        return ['日', '一', '二', '三', '四', '五', '六']
      }
    },
    // 自定义表头的样式
    headStyle: {
      type: Object,
      default: () => {
        return {
          'background-color': 'rgba(248,248,248)'
        }
      }
    },
    // 初始日期,可传入年月或年月日,默认当前年月
    currentDate: {
      type: String,
      default: moment().format('YYYY-MM')
    },
    // 日期方式,单选 single, 范围 range, 多选 multiple,默认单选
    mode: {
      type: String,
      default: 'single'
    },
    // 日历标题是否显示,默认不显示标题
    tipShow: {
      type: Boolean,
      default: false
    },
    // 是查看还是操作, 默认可操作
    isOpera: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    // 年月变化
    dynamicDate: {
      handler() {
        this.getInitDate()
      },
      immediate: true
    }
  },
  data() {
    return {
      dateSource: [], // 日历数据
      dynamicDate: this.currentDate, // 当前的年月
      selectDate: null, // 选中的日期
      rangVal: [] // 范围值
    }
  },
  created() {
    this.getInitDate()
  },
  methods: {
    // 初始化日期
    getInitDate() {
      let timeList = []
      const endTime = moment(new Date(this.dynamicDate)).endOf('month').format('YYYY-MM-DD')
      let startTime = moment(new Date(this.dynamicDate)).startOf('month').format('YYYY-MM-DD')
      while (startTime <= endTime) {
        timeList.push({
          date: startTime, // 日期
          week: moment(new Date(startTime)).day(), // 星期几
          day: moment(new Date(startTime)).get('date') // 天
        })
        startTime = moment(new Date(startTime)).add(1, 'days').format('YYYY-MM-DD')
      }
      console.log(timeList, 2222)
      switch (timeList[0].week) {
        case 0: // 周日
          break
        case 1: // 周一
          timeList = [null].concat(timeList)
          break
        case 2: // 周二
          timeList = [null, null].concat(timeList)
          break
        case 3: // 周三
          timeList = [null, null, null].concat(timeList)
          break
        case 4: // 周四
          timeList = [null, null, null, null].concat(timeList)
          break
        case 5: // 周五
          timeList = [null, null, null, null, null].concat(timeList)
          break
        case 6: // 周六
          timeList = [null, null, null, null, null, null].concat(timeList)
          break
      }
      this.dateSource = timeList
      console.log(this.dateSource, 111111)
    },
    // 当前年月日期变化
    changeDate(type) {
      switch (type) {
        case 'beforeYear':
          this.dynamicDate = moment(new Date(this.dynamicDate)).subtract(1, 'years').format('YYYY-MM')
          break
        case 'beforeMonth':
          this.dynamicDate = moment(new Date(this.dynamicDate)).subtract(1, 'months').format('YYYY-MM')
          break
        case 'lastMonth':
          this.dynamicDate = moment(new Date(this.dynamicDate)).add(1, 'months').format('YYYY-MM')
          break
        case 'lastYear':
          this.dynamicDate = moment(new Date(this.dynamicDate)).add(1, 'years').format('YYYY-MM')
          break
      }
    },
    // 选择的日期
    selectedDate(data) {
      if (!data) return
      switch (this.mode) {
        case 'single': // 单个日期
          this.selectDate = data.date
          break
        case 'range': // 日期范围
          if (this.rangVal.length === 2 || this.rangVal[0] && this.rangVal[0].date > data.date) {
            this.rangVal = []
          }
          this.rangVal.push(data)
          this.dateSource.map((item) => {
            if (item) { item.checked = false }
            this.rangVal.forEach((itemRange) => {
              if (item && item.date === itemRange.date) {
                item.checked = true
              }
              return item
            })
          })
          this.$forceUpdate()
          break
        case 'multiple': // 选择多个日期
          this.dateSource.map((item) => {
            if (item && data.date === item.date) {
              item.checked = !item.checked
            }
            return item
          })
          this.selectDate = this.dateSource.filter((item) => item && item.checked)
          this.$forceUpdate()
          break
      }
    }
  }
}
script>

<style lang="scss" scoped>
.table-header {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  flex: 100%;
  .table-header_col {
    flex: 0 0 14.2857143%;
    width: 14.2857143%;
    min-height: 80rpx;
  }
  .table-header_col:nth-child(7n) {
    flex: 1;
  }
  .table-content_border {
    // border: 1px solid rgba(187, 187, 187, 0.2);
    box-sizing: border-box;
    // margin:0px -1px -1px 0px;
  }
  .table-active.table-content_border {
    background-color: rgba(41, 121, 255, 0.85);
    color: #fff;
  }
  .table-text_align {
    text-align: center;
    padding: 20rpx 0;
  }
  .table-flex_center {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .table-range {
    font-size: 16rpx;
  }
  .calendar-pointer {
    pointer-events: none;
  }
}
.tip-title {
  text-align: center;
  padding-top: 20rpx;
  font-size: 24rpx;
}
.calendar-month {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 24rpx;
  padding: 20rpx;
  font-weight: bold;
  .uicon-padding {
    padding: 0 12rpx;
  }
}
style>

日历组件 vue 小程序_第1张图片

你可能感兴趣的:(vue.js,小程序,javascript)