<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 小程序
最新推荐文章于 2024-04-22 15:41:13 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)