1.导入calendar.js
function dateToTimestamp(data) {
return Date.parse(data);
}
function pad(i) {
if (i < 10) {
i = '0' + i;
}
return i;
}
/**
* 获取月份的天数
* @param {*} year
* @param {*} month
*/
function getMonthDays(year, month) {
return new Date(year, month, 0).getDate();
}
/**
* 获取某一月的第一天是星期几
* @param {[type]} year 年份
* @param {[type]} month 月份,如果是0 这表示上一年的12月
* @return {[type]} 1表示周一, 7表示周日
*/
function getFirsrtweekend(year, month) {
return new Date(year, month - 1, 0).getDay() + 1;
}
/**
* 获取下一个月份是多少
* @param {*} year
* @param {*} month
*/
function getNextDate(year, month) {
month++;
if (month > 12) {
month = 1;
year++;
}
return {
year,
month,
};
}
/**
* 获取上一个月份是多少
* @param {*} year
* @param {*} month
*/
function getPreDate(year, month) {
month--;
if (month <= 0) {
month = 12;
year--;
}
return {
year,
month,
};
}
function preDaysSolt(year, month) {
var daysSolt = getFirsrtweekend(year, month);
if (daysSolt === 7) {
daysSolt = 0;
}
return daysSolt;
}
function getMonthCurDetail(year, month) {
var monthDetail = [];
var days = getMonthDays(year, month);
var curentTime = new Date();
var currentYear = curentTime.getFullYear();
var currentMonth = curentTime.getMonth() + 1;
var currentDay = curentTime.getDate()
var curentTimeStemp = dateToTimestamp(`${currentYear}-${pad(currentMonth)}-${pad(currentDay)}`)
for (var i = 1; i <= days; i++) {
var timeStamp = dateToTimestamp(`${year}-${pad(month)}-${pad(i)}`)
monthDetail.push({
tips: 'cur',
text: i,
timeStamp: timeStamp,
disable: timeStamp < curentTimeStemp
});
}
return monthDetail;
}
function getMonthPreDetail(year, month) {
var monthDetail = [];
var daysSolt = preDaysSolt(year, month);
var preDate = getPreDate(year, month);
var preMonthDays = getMonthDays(preDate.year, preDate.month);
for (var i = preMonthDays - daysSolt + 1, len = preMonthDays; i <= len; i++) {
monthDetail.push({
text: i,
tips: 'pre',
timeStamp: dateToTimestamp(
`${preDate.year}-${pad(preDate.month)}-${pad(i)}`
),
});
}
return monthDetail;
}
function getMonthNextDetail(year, month) {
var monthDetail = [];
var daysSolt = preDaysSolt(year, month);
var days = getMonthDays(year, month);
var nextDate = getNextDate(year, month);
// console.log())
var count = 42 - (daysSolt + days)
count = count >= 7 ? count - 7 : count;
// console.log(count)
for (var i = 1, len = count; i <= len; i++) {
monthDetail.push({
text: i,
tips: 'next',
timeStamp: dateToTimestamp(
`${nextDate.year}-${pad(nextDate.month)}-${pad(i)}`
),
});
}
// console.log( `${nextDate.year}-${pad(nextDate.month)}---->${daysSolt}`)
return monthDetail;
}
export function timestampToDate(format, timestamp) {
if (!timestamp) {
return timestamp;
}
// var date = timestamp ? new Date(parseInt(timestamp) * 1000) : new Date(+new Date());
var date = new Date(parseInt(timestamp));
var year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate(),
hour = date.getHours(),
minute = date.getMinutes(),
second = date.getSeconds();
var str = format.replace(/y+|m+|d+|h+|s+/gi, function (w) {
if (w == 'yy' || w == 'YY' || w == 'y' || w == 'Y') {
return year.toString().substring(2);
} else if (w == 'yyyy' || w == 'YYYY') {
return year;
} else if (w == 'MM') {
return month >= 10 ? month : '0' + month;
} else if (w == 'M') {
return month;
} else if (w == 'DD' || w == 'dd') {
return day >= 10 ? day : '0' + day;
} else if (w == 'D' || w == 'd') {
return day;
} else if (w == 'HH' || w == 'hh') {
return hour >= 10 ? hour : '0' + hour;
} else if (w == 'H' || w == 'h') {
return hour;
} else if (w == 'mm') {
return minute >= 10 ? minute : '0' + minute;
} else if (w == 'm') {
return minute;
} else if (w == 'ss' || w == 's') {
return second >= 10 ? second : '0' + second;
}
});
return str;
}
export function Calender(config) {
var { date, mixDate, maxDate } = config;
// date = date.split("-");
var dateObj = new Date(date);
this.year = dateObj.getFullYear();
this.month = dateObj.getMonth() + 1;
this.mixDate = null;
this.maxDate = null;
// this.selecting = false;
if (mixDate) {
let timeStamp = timestampToDate('yyyy-MM-DD', dateToTimestamp(mixDate));
this.mixDate = dateToTimestamp(timeStamp);
}
if (maxDate) {
let timeStamp = timestampToDate('yyyy-MM-DD', dateToTimestamp(maxDate));
this.maxDate = dateToTimestamp(timeStamp);
}
this.rows = [];
}
Calender.prototype = {
switchPreMonth() {
var dateObj = getPreDate(this.year, this.month);
this.year = dateObj.year;
this.month = dateObj.month;
return this.getList();
},
switchNextMonth() {
var dateObj = getNextDate(this.year, this.month);
this.year = dateObj.year;
this.month = dateObj.month;
return this.getList();
},
getList() {
let currentDayDetail = getMonthCurDetail(this.year, this.month);
let mix = Math.min(this.mixDate, this.maxDate);
let max = Math.max(this.mixDate, this.maxDate);
this.mixDate = mix;
this.maxDate = max;
this.rows = this.markRange(this.mixDate, this.maxDate, currentDayDetail);
this.rows.unshift(...getMonthPreDetail(this.year, this.month));
this.rows.push(...getMonthNextDetail(this.year, this.month));
return this.rows;
},
getValue() {
return [this.mixDate, this.maxDate];
},
markRange(mixDate, maxDate, rows) {
for (let item of rows) {
var time = item.timeStamp;
item.inRange = mixDate && time >= mixDate && time <= maxDate;
item.start = mixDate && time === mixDate;
item.end = maxDate && time === maxDate;
}
return rows;
},
};
2.导入riqi.vue
<template>
<!-- <m-nav-bar :bar-style="{background: ''}" :fill-nav-bar="true"></m-nav-bar> -->
<!-- <div style="height: 50px;width: 100%;background-color:#E6EDF7"></div>-->
<transition name="slider">
<div
class="hl-calendar-wrap"
v-show="visibility"
>
<p class="hl-calendar-week align-center ig-xq" >
<span style="color: #026FF2">日</span>
<span>一</span>
<span>二</span>
<span>三</span>
<span>四</span>
<span>五</span>
<span style="color: #026FF2">六</span>
</p>
<div
@click="handleClick"
class="calendar-content clearfix align-center"
ref="calendarWrap"
>
<div
:key="item.title"
v-for="item in list"
>
<div class="ig-title">
{{ item.title }}
</div>
<div class="calendar-content_list-wrap clearfix">
<div
:class="{
'ig-range': info.inRange,
'ig-visibility': info.tips === 'pre' || info.tips === 'next',
'ig-disable': info.disable,
'ig-start': info.start,
'ig-end': info.end,
'ig-cursor': info.tips === 'cur'
}"
:date-timeStamp="info.timeStamp"
:key="info.timeStamp"
class="ig-cal-list"
v-for="info in item.list"
:id="item.title+'-'+info.text"
>
<div>
<span
class="page-table-note"
v-if="info.start"
>开始</span>
<span
class="page-table-note"
v-if="info.end"
>结束</span>
<span v-if="ss==(item.title+'-'+info.text)" style="color:red;">今日<!--{{ info.text }}--></span>
<span v-else>{{ info.text }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
/**
酒店日期选择组件
props参数
visibility boolean 选择弹框是否显示 必填 默认false
format string 返回的日期格式 非必填 默认:YYYY-MM-DD
initDate object 开始选中的日期范围 非必填 默认选中:当天日期~后天日期 传参格式{ startDate: 'xxxx-xx-xx', endDate: 'xxxx-xx-xx' }
事件
select-date-range function 选择两个日期的回调函数 返回选中的日期
外部可以调用方法
this.$refs['glHoelCalendar'].getValue() 返回选中的日期
this.$refs['glHoelCalendar'].getCalenderList(date, mixDate, maxDate) 重新渲染列表 date: YYYY-MM 开始月份, mixDate: YYYY-MM-DD 入住日期, maxDte: YYYY-MM-DD 离店日期
*/
import { Calender, timestampToDate } from './calendar'
// let bodyEl = document.body
// let top = 0
// function stopBodyScroll(isFixed) {
// if (isFixed) {
// top = window.scrollY
// bodyEl.style.position = 'fixed'
// bodyEl.style.top = -top + 'px'
// } else {
// bodyEl.style.position = ''
// bodyEl.style.top = ''
// window.scrollTo(0, top) // 回到原先的top
// }
// }
export default {
props: {
visibility: {
type: Boolean,
default: false
},
format: {
type: String,
default: 'YYYY-MM-DD'
},
initDate: {
type: Object,
default() {
return {
startDate: '',
endDate: ''
}
}
},
showMonth: {
type: Number,
default: 3
}
},
data() {
return {
ss:"",
starttimea:"",
endtimea:"",
// visibility: false,
target:0,
list: [],
mixDate: null,
maxDate: null
}
},
// watch: {
// visibility(newValue) {
// stopBodyScroll(newValue)
// }
// },
// deactivated() {
// stopBodyScroll(false)
// },
// created() {
// },
mounted() {
this.createList();
let thisDate = new Date();
let year = thisDate.getFullYear();
let month = thisDate.getMonth() + 1 < 10 ? '0' + (thisDate.getMonth() + 1) : thisDate.getMonth() + 1;
let day = thisDate.getDate();
this.ss = year+"-"+month+"-"+day
// let thisDate = new Date();
/* let year = thisDate.getFullYear();
let month = thisDate.getMonth() + 1 < 10 ? '0' + (thisDate.getMonth() + 1) : thisDate.getMonth() + 1;
let day = thisDate.getDate();
let ss = year+"-"+month+"-"+day*/
//document.getElementById(ss).scrollIntoView({behavior:"smooth",block:"center"})
console.log(this.visibility)
this.$nextTick(() => {
// document.getElementById("2024-11-25").scrollIntoView({behavior:"smooth",block:"center"});
})
/* console.log(this.target)
document.body.scrollTop = 200;*/
/* setTimeout(function (){
document.getElementById("2024-11-25").scrollIntoView();
},1000)
*/
},
methods: {
//inputdate :父组件 时间显示控件内容为空时跳转到当前时间 不为空不跳转
refrashtodate(inputdate){
//this.visibility = true
console.log("dhhdhdhd")
// document.getElementById("2024-11-25").scrollIntoView(true);
// location.href="#2024-11-25"
if(inputdate=="") {
setTimeout(function (){
let thisDate = new Date();
let year = thisDate.getFullYear();
let month = thisDate.getMonth() + 1 < 10 ? '0' + (thisDate.getMonth() + 1) : thisDate.getMonth() + 1;
let day = thisDate.getDate();
let ssaa = year+"-"+month+"-"+day
document.getElementById(ssaa).scrollIntoView({behavior: "smooth", block: "center"});
},1000)
}
/*this.$nextTick(() => {
document.getElementById("2024-11-25").scrollIntoView({behavior:"smooth",block:"center"});
})*/
},
createList() {
const currentTime = new Date("2024-01-01").getTime()//设置日历起至时间
const date = timestampToDate('yyyy-MM', currentTime)
// const mixDate = this.initDate.startDate ? this.initDate.startDate : timestampToDate('yyyy-MM-DD', currentTime)
// const maxDate = this.initDate.endDate ? this.initDate.endDate : timestampToDate('yyyy-MM-DD', currentTime + 86400000)
this.getCalenderList(date, "", "");
},
getCalenderList(date, mixDate, maxDate) {
const list = []
this.calender = new Calender({
date,
mixDate: mixDate,
maxDate: maxDate
})
this.mixDate = this.calender.mixDate
this.maxDate = this.calender.maxDate
// debugger
list.push({
title: date,
list: this.calender.getList()
})
for (let i = 0; i < this.showMonth - 1; i++) {
const listDetail = this.calender.switchNextMonth()
const month = this.calender.month >= 10 ? this.calender.month : '0' + this.calender.month
list.push({
title: this.calender.year + '-' + month,
list: listDetail
})
}
this.list = list
},
getValue() {
let mix = Math.min(this.mixDate, this.maxDate)
let max = Math.max(this.mixDate, this.maxDate)
return {
startDate: timestampToDate(this.format, mix),
endDate: timestampToDate(this.format, max),
seletDays: (max - mix) / 86400000 + 1
}
},
handleClick(event) {
let target = event.target
target = this.searchElement(target, 'ig-cal-list')
// debugger
if (!target) return
//if (target.className.indexOf('visibility') > -1 || target.className.indexOf('disable') > -1) return
var timeStamp = target.getAttribute('date-timestamp')
if (timeStamp) {
this._calHandleClick(timeStamp)
}
},
_calHandleClick(selectData) {
if (this.selecting) {
this.selecting = false
this.maxDate = selectData
} else {
this.selecting = true
this.mixDate = selectData
this.maxDate = null
}
let mix = Math.min(this.mixDate, this.maxDate)
let max = Math.max(this.mixDate, this.maxDate)
if (mix === max) {
this.$emit('select-date-range', this.getValue())
return
} else {
this.markRange(mix, max, this.list)
}
if (!this.selecting) {
// console.log('您选择的是:', this.mixDate, this.maxDate);
this.$emit('select-date-range', this.getValue())
}
},
markRange(mixDate, maxDate, rows) {
for (let item of rows) {
item.list.forEach((info) => {
var time = info.timeStamp
info.inRange = mixDate && time >= mixDate && time <= maxDate
if (!mixDate && maxDate) {
info.start = time === maxDate
info.end = false
this.starttimea= info.start
this.endtimea=info.end
} else {
info.start = mixDate && time === mixDate
info.end = maxDate && time === maxDate
this.starttimea= info.start
this.endtimea=info.end
}
})
}
// console.log(rows);
},
/**
* 搜索元素,解决事件委托颗粒度问题
* @param {[type]} el [description]
* @param {[type]} attr [description]
* @return {[type]} [description]
*/
searchElement: function (el, attr) {
var touchTarget = el,
count = 0,
endTarget = 'class'
while (touchTarget) {
count++
if (count > 5 || touchTarget.nodeName.toLowerCase() == 'html') {
touchTarget = null
return touchTarget
} else if (touchTarget.getAttribute(endTarget) != null && touchTarget.getAttribute(endTarget).indexOf(attr) > -1) {
return touchTarget
}
touchTarget = touchTarget.parentNode
}
}
}
}
</script>
<style>
.slider-enter-active,
.slider-leave-active {
transition: all 0.3s ease;
}
.slider-enter,
.slider-leave-to {
transform: translateX(100%);
}
.clearfix {
zoom: 1;
}
.clearfix:after {
content: '';
display: block;
clear: both;
}
.ig-visibility {
visibility: hidden;
}
.align-center {
text-align: center;
}
.ig-title {
background: hsla(210, 8%, 95%, 0.9);
position: sticky;
top: 30px;
z-index: 1;
height: 30px;
line-height: 30px;
}
.ig-xq {
background: #ffffff;
/*background: hsla(210, 8%, 95%, 0.9);*/
position: sticky;
top: 0px;
z-index: 2;
height: 30px;
line-height: 30px;
}
.hl-calendar-wrap {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: auto;
background: #fff;
z-index: 1000;
}
.hl-calendar-wrap > .hl-calendar-week {
width: 100%;
height: 30px;
display: flex;
line-height: 30px;
background: #fafafa;
font-size: 14px;
margin: 0;
padding: 0;
}
.hl-calendar-wrap > .hl-calendar-week > span {
flex: 1;
}
.ig-cal-list {
float: left;
width: 14.2%;
margin: 5px 0;
position: relative;
height: 60px;
color: #666;
display: flex;
align-items: center;
justify-content: center;
}
.ig-cal-list:nth-of-type(7n + 1),
.ig-cal-list:nth-of-type(7n + 7) {
color: #026FF2 !important;
/* color: red !important;*/
}
.ig-cal-list.ig-disable {
color: #666 !important;
}
.ig-cal-list.ig-disable:nth-of-type(7n + 1),
.ig-cal-list.ig-disable:nth-of-type(7n + 7) {
color: #026FF2 !important;
/*color: red !important;*/
}
.ig-range {
background: #D4EAFF;
}
.ig-start,
.ig-end {
background: #026FF2;
}
.hl-calendar-wrap .ig-start,
.hl-calendar-wrap .ig-end {
color: #fff !important;
}
.hl-calendar-wrap .ig-disable.ig-start,
.hl-calendar-wrap .ig-disable.ig-end {
color: #fff !important;
}
.cal-list > div {
width: 100%;
}
.ig-cal-list .page-table-note {
display: block;
font-size: 12px;
}
</style>
3.调用
<template>
<div style="width:100%;">
<div style="display: flex;flex-direction: row;align-items: center;position: relative">
<el-input ref="inp" clearable readonly @focus="openPicker('1')" style="margin-right: 10px;flex: 1;margin-left: 10px" v-model="inputdate" placeholder="选择日期"></el-input>
<img style="position: absolute;right: 15px;height: 20px;width: 20px;object-fit: contain " src="../../../assets/dbimg/chahao.png" @click="cleardate()"/>
<!-- <div class="searchdatestyle" @click="openPicker('1')" style="margin-right: 10px;flex: 1">{{selectstarttime}}</div>
<div style=" font-size: 16px;color: #606266;">至</div>
<div class="searchdatestyle" @click="openPicker('2')" style="margin-right: 10px;flex: 1">{{selectendtime}}</div>-->
</div>
<riqi
ref="hotelCalendar"
:visibility="show"
@select-date-range="selectDateRangeHandle"
:show-month="120"
format="YYYY-MM-DD"
></riqi>
</div>
</template>
<script>
import riqi from "@/components/riqi";
export default {
beforeRouteLeave(to,from,next){//当行防卫 组件离开之前调用
//console.log(next)
console.log(this.show)
if(this.show){
this.show = false
this.$refs.inp.blur()//使 el-input失去焦点
next(false)
}else{
next()
}
},
data() {
return {
inputdate:"",
show:false,
datetype:"",
searchtext:"",
options:[{
code:"",
dictdata_value:"全部"
}],
taskvalue:"",
selectstarttime:"选择日期",//选择时间
selectendtime:"选择日期",
}
},
components:{
riqi
},
methods: {
cleardate(){
this.$refs['hotelCalendar'].getCalenderList("2024-01-01", "", "")
this.inputdate=""
this.selectstarttime="选择日期"
this.selectendtime="选择日期"
},
selectDateRangeHandle(e) {
this.show = false;
this.dateRange = `开始${e.startDate}结束${e.endDate}, 共${e.seletDays - 1}天`
console.log( this.dateRange)
this.selectstarttime = e.startDate
this.selectendtime = e.endDate
this.inputdate=e.startDate+" 至 "+e.endDate
},
openPicker(datetype) {
this.datetype = datetype
console.log(this.show)
this.$refs['hotelCalendar'].refrashtodate(this.inputdate)
this. show = true
},
}
}
</script>
<style scoped>
.searchdatestyle{
line-height: 25px;
font-size: 15px;
color: #606266;
padding-left: 8px;
padding-right: 8px;
padding-bottom: 3px;
padding-top: 3px;
border-radius: 6px;
background-color: #EEEEEE;
margin-left: 10px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center
}
/deep/ .el-input__inner{
font-size: 15px;
/* background-color: #EEEEEE;*/
height: 30px;
}
/deep/ .el-input__inner::placeholder {
color: #909090; /* 将颜色改为灰色 */
}
/deep/ .picker-item.picker-selected{
color:#3875c6 ;
font-size: 20px;
}
/*控制 mt-datetime-picker 组件只显示年月*/
/*/deep/ .picker-items>:nth-child(3){
display: none;
}*/
.titlestyle{
width: 100%;
text-align: center;
font-size: 18px;
color: #3875c6;
margin-top: 20px;
margin-bottom: 20px;
}
</style>
网友评论