<template>
<view class="content">
<view class="header">
<div class="tou">
<view class="in-and-out">
{{ startDay }} - {{ endDay }}
<text @click="reset" class="qingkong">清空</text>
</view>
</div>
<view class="week">
<view>日</view>
<view>一</view>
<view>二</view>
<view>三</view>
<view>四</view>
<view>五</view>
<view>六</view>
</view>
</view>
<scroll-view scroll-y="true" class="section">
<div class="section2">
<view v-for="(res, line) in resDate" class="riqiitem" :key="line">
<view class="year">{{ res.year }}年{{ res.month }}月</view>
<view class="day">
<view v-for="week in res.oneDayWeek" class="day-list" :style="{ width: (dayWidth - 10) / 7 + 'px' }"></view>
<view
@tap="selectDay(line, index, (line + 1).toString() + index)"
v-for="(riqiitem, index) in res.day"
:key="index"
class="day-list"
:class="[
line == start[0] && index == start[1] ? 'bg-orange select-style' : '',
(line >= start[0] && line <= end[0] && index > start[1] && index < end[1]) ||
(line >= start[0] && index > start[1] && line < end[0]) ||
(line <= end[0] && index < end[1] && line > start[0]) ||
(line < end[0] && line > start[0])
? 'bg-higlt-orange'
: '',
line == 0 && index + 1 < nowDay ? 'time-out' : '',
isNaN(riqiitem) ? 'is-festival' : '',
(isNaN(riqiitem) && line == start[0] && index == start[1]) || (isNaN(riqiitem) && line == end[0] && index == end[1]) ? 'not-festival' : '',
(priceStauts.length > 0 && priceStauts[line][index] < 0 && start.length > 0 && end.length > 0) ||
(priceStauts.length > 0 && priceStauts[line][index] < 0 && start.length == 0 && end.length == 0)
? 'not-sub'
: '',
priceStauts.length > 0 && end.length == 0 && start.length > 0 && priceStauts[line][index] < 0 && line + index * 2 != lastNot[0] + lastNot[1] * 2
? 'not-sub'
: ''
]"
:style="{
width: (dayWidth - 10) / 7 + 'px',
backgroundColor: line == end[0] && index == end[1] ? 'rgba(129, 197, 231, 1.00)' : '',
color: line == end[0] && index == end[1] ? '#FFFFFF' : ''
}"
>
<view class="select-style" v-if="line == start[0] && index == start[1]">入住</view>
<view class="select-style" v-if="line == end[0] && index == end[1]">离店</view>
<view style="padding-top:2px;padding-bottom:2px;">{{ riqiitem }}</view>
<view style="font-size:12px;padding-bottom: 3px;" v-if="priceStauts.length > 0">
<view v-if="priceStauts[line][index] > 0">¥{{ priceStauts[line][index] }}</view>
<view v-if="priceStauts[line][index] < 0">无房</view>
</view>
</view>
</view>
</view>
</div>
</scroll-view>
<view class="submit">
<button class="sub-btn " :disabled="!isSub" @click="submit">
<text v-if="isSub">确定</text>
<text v-if="!isSub">请选择入住日期</text>
</button>
</view>
</view>
</template>
<script>
import { mapState, mapGetters, mapMutations } from 'vuex';
//引入节假日的数据,也可以用后台返回去渲染
export default {
computed: {
...mapGetters(['checkinDate', 'checkoutDate']),
//房间是否能预订
isSub() {
if (this.priceStauts.length > 0) {
for (var i = this.start[0]; i <= this.end[0]; i++) {
if (i == this.start[0]) {
for (var j = this.start[1]; j < this.date[i].length; j++) {
if (this.priceStauts[i][j] == -1) return false;
}
} else if (this.end[0] == this.start[0]) {
for (var j = this.start[1]; j < this.end[1]; j++) {
if (this.priceStauts[i][j] == -1) return false;
}
} else if (i == this.end[0]) {
for (var j = 0; j < this.end[1]; j++) {
if (this.priceStauts[i][j] == -1) return false;
}
} else {
for (var j = 0; j < this.priceStauts[i].length; j++) {
if (this.priceStauts[i][j] == -1) return false;
}
}
}
}
return this.start.length == 2 && this.end.length == 2 ? true : false;
},
//计算日历里的节假日
resDate() {
if (this.date.length == 0) return;
for (var i = 0; i < this.date.length; i++) {
for (var j = 0; j < this.festival.length; j++) {
if (this.festival[j].year == this.date[i].year && this.festival[j].month == this.date[i].month) {
for (var k = 0; k < this.festival[j].festival.length; k++) {
if (this.date[i].day.indexOf(this.festival[j].festival[k].day) != -1) {
this.date[i].day[this.date[i].day.indexOf(this.festival[j].festival[k].day)] = this.festival[j].festival[k].name;
}
}
}
}
}
return this.date;
}
},
data() {
return {
out: 0,
festival: [], //节假日
type: '-', //日期分隔符
date: [], //日期数组对象
dayWidth: 0, //日期的宽度
nowDay: 0, //当前时间的日
start: [], //入住时间
count: 6, //显示月的数量
startDay: '', //入住日期
startWeek: '', //入住时间的周几
end: [], //离开时间
endDay: '', //离开日期
endWeek: '', //离开时间的周几
day: 0, //多少晚
priceStauts: [], //价格状态
lastNot: [0, 10] //前置的无房操作
};
},
onLoad(option) {},
mounted() {
uni.getSystemInfo({
success: res => {
this.dayWidth = res.windowWidth;
}
});
this.setDate();
console.log(this.checkinDate)
this.nowDay = new Date(this.checkinDate).getDate();
console.log(this.nowDay)
console.log('this.nowDay')
/*默认入住离店日期,今日入住明日离店,此处应在setDefaultDate函数内传入vuex里保存的日期进行默认操作
*不推荐使用本地缓存,下边只是使用缓存的示例
*/
this.start = this.setDefaultDate(this.checkinDate);
this.end = this.setDefaultDate(this.checkoutDate);
console.log(this.start, this.end);
},
watch: {
//离店日期
end(newVal) {
if (this.end.length != 0) {
//计算选择离店日期
this.endDay = this.setMonth(newVal[0]) + this.isFestival(newVal[0], newVal[1]) + '日';
this.endWeek = this.getWeek(this.date[newVal[0]].year + '/' + this.date[newVal[0]].month + '/' + this.isFestival(newVal[0], newVal[1]));
//计算天数
var startDay = this.date[this.start[0]].year + '/' + this.date[this.start[0]].month + '/' + this.isFestival(this.start[0], this.start[1]);
var endDay = this.date[newVal[0]].year + '/' + this.date[newVal[0]].month + '/' + this.isFestival(this.end[0], this.end[1]);
this.day = this.getDay(startDay, endDay);
} else {
this.day = 0;
}
},
//入住日期
start(newVal) {
if (this.start.length > 0) {
this.startDay = this.setMonth(newVal[0]) + this.isFestival(newVal[0], newVal[1]) + '日';
this.startWeek = this.getWeek(this.date[newVal[0]].year + '/' + this.date[newVal[0]].month + '/' + this.isFestival(newVal[0], newVal[1]));
}
if (this.priceStauts.length > 0) {
console.log(this.lastNot);
for (var i = newVal[0]; i < this.priceStauts.length; i++) {
if (i == newVal[0]) {
for (var j = newVal[1]; j < this.priceStauts[i].length; j++) {
if (this.priceStauts[i][j] == -1) {
this.lastNot = [i, j];
console.log(this.lastNot);
return;
}
}
} else {
for (var j = 0; j < this.priceStauts[i].length; j++) {
if (this.priceStauts[i][j] == -1) {
this.lastNot = [i, j];
console.log(this.lastNot);
return;
}
}
}
}
//清空
this.lastNot = [];
}
}
},
methods: {
//月份补零
setMonth(dateIndex) {
let month = this.date[dateIndex].month;
if (month < 10) {
month = '0' + month;
}
return month + '月';
},
//如果是节假日名称则返回选择的日期天数
isFestival(line, index, push = false) {
var date = this.date[line].day[index];
if (isNaN(date)) {
var newIndex = this.date[line].day.indexOf(date) + 1;
if (push) return newIndex;
return newIndex < 10 ? '0' + newIndex : newIndex;
} else {
if (push) return date;
return date < 10 ? '0' + date : date;
}
},
//获取今天明天的日期
getDefaultDate(AddDayCount) {
var dd = new Date();
dd.setDate(dd.getDate() + AddDayCount); //获取AddDayCount天后的日期
var year = dd.getFullYear();
var mon = dd.getMonth() + 1; //获取当前月份的日期
var day = dd.getDate();
return year + '-' + mon + '-' + day;
},
//设置入住时间 如果没有传值则根据默认值设置
setDefaultDate(data) {
var arr = [0, parseInt(this.nowDay - 1)];
var start = data.indexOf('-') != -1 ? data.split('-') : data.split('/');
var year = new Date().getFullYear();
var month = new Date().getMonth() + 1;
for (var i = 0; i < this.date.length; i++) {
if (this.date[i].year == start[0] && this.date[i].month == start[1]) {
if (year == start[0] && month == start[1] && start[2] < this.nowDay) {
arr = [i, parseInt(this.nowDay - 1)];
} else {
arr = [i, parseInt(start[2] - 1)];
}
break;
}
}
return arr;
},
//清空
reset() {
this.start = [];
this.end = [];
this.day = 0;
},
//补零操作
setPull(day) {
if (day < 10) {
day = '0' + day;
}
return day;
},
//计算天数
getDay(date1, date2) {
//获得天数
//date1:开始日期,date2结束日期
var a1 = Date.parse(new Date(date1));
var a2 = Date.parse(new Date(date2));
var day = parseInt((a2 - a1) / (1000 * 60 * 60 * 24)); //核心:时间戳相减,然后除以天数
return day;
},
//计算周几
getWeek(date) {
var weekDay = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var myDate = new Date(Date.parse(date));
return weekDay[myDate.getDay()];
},
//选择入住离开
selectDay(line, index) {
if (line == 0 && index + 1 < this.nowDay) return;
//如果有入住情况和价格则需要进行一些列的判断
if (this.priceStauts.length > 0) {
if ((this.start.length == 0 && this.priceStauts[line][index] < 0) || (this.end.length > 0 && this.priceStauts[line][index] < 0)) {
return uni.showToast({
title: '该日期已被预订',
icon: 'none'
});
}
if ((this.start.length > 0 && line < this.start[0]) || (line == this.start[0] && this.start[1] > index)) {
if (this.priceStauts[line][index] < 0)
return uni.showToast({
title: '该日期已被预订',
icon: 'none'
});
this.start = [line, index];
this.end = [];
return;
}
if (this.start.length > 0 && this.end.length == 0) {
if (this.start[0] - line == 0) {
for (var j = this.start[1]; j < index; j++) {
if (this.priceStauts[line][j] < 0)
return uni.showToast({
title: '很抱歉,所选入离店时间包含无房日期',
icon: 'none',
mask: true
});
}
} else {
//如果不在同一个月份有三种情况需要处理
for (var i = this.start[0]; i <= line; i++) {
//开始日期到开始日期当月的最大日期是否包含无房情况
if (i == this.start[0]) {
for (var j = this.start[1]; j < this.priceStauts[i].length; j++) {
if (this.priceStauts[i][j] < 0)
return uni.showToast({
title: '很抱歉,所选入离店时间包含无房日期',
icon: 'none',
mask: true
});
}
} else if (i == line) {
//结束日期到当月结束日期之前是否包含无房情况
for (var j = 0; j < index; j++) {
if (this.priceStauts[i][j] < 0)
return uni.showToast({
title: '很抱歉,所选入离店时间包含无房日期',
icon: 'none',
mask: true
});
}
} else {
//中间间隔的月份需要检查每一天是否包含无房情况
for (var j = 0; j < this.priceStauts[i].length; j++) {
if (this.priceStauts[i][j] < 0)
return uni.showToast({
title: '很抱歉,所选入离店时间包含无房日期',
icon: 'none',
mask: true
});
}
}
}
}
}
}
//如果没有入住时间
if (this.start.length == 0) {
//填充入住时间
this.start = [line, index];
} else if (this.start.length > 0 && this.start[0] == line && this.start[1] == index && this.end.length == 0) {
return;
} else {
//如果没有离开时间
if (this.end.length == 0) {
//如果有价格和入住离开情况则需要进行判断所选的离店时间时候包含无房日期
if (line < this.start[0] || (line == this.start[0] && index < this.start[1])) {
this.end = this.start;
this.start = [line, index];
} else {
//如果离开时间比入住时间晚则填充
this.end = [line, index];
}
} else {
//如果有离开时间则清空离开时间重新填充入住时间
this.start = [line, index];
this.end = [];
}
}
},
//设置日历
setDate() {
//年份
var year = new Date(this.checkinDate).getFullYear();
//月份
var month = new Date(this.checkinDate).getMonth();
for (let i = 0; i < this.count; i++) {
var day = [];
var week = 0;
for (var j = 0; j < new Date(year, month + 1, 0).getDate(); j++) {
day.push(j + 1);
}
this.date.push({
year: year,
month: month + 1,
day: day,
oneDayWeek: new Date(Date.parse(year + '/' + (month + 1) + '/' + '01')).getDay()
});
if (month == 11) {
year += 1;
month = 0;
} else {
month++;
}
}
return this.date;
},
//关闭
close() {
uni.navigateBack({
delta: 1
});
},
//确定入住离店事件提交
submit() {
var obj = {
/* startYMD: this.date[this.start[0]].year + this.type + this.date[this.start[0]].month + this.type + this.isFestival(
this.start[0], this.start[1]),
startMD: this.date[this.start[0]].month + this.type + this.isFestival(this.start[0], this.start[1]),
startDay: this.startDay,
startWeek: this.startWeek,
endYMD: this.date[this.end[0]].year + this.type + this.date[this.end[0]].month + this.type + this.isFestival(this
.end[0], this.end[1]),
emdMD: this.date[this.end[0]].month + this.type + this.type + this.isFestival(this.end[0], this.end[1]),
endDay: this.endDay,
endWeek: this.endWeek,
day: this.day */
start: this.date[this.start[0]].year + this.type + this.date[this.start[0]].month + this.type + this.isFestival(this.start[0], this.start[1], true),
end: this.date[this.end[0]].year + this.type + this.date[this.end[0]].month + this.type + this.isFestival(this.end[0], this.end[1], true),
startDay: this.date[this.start[0]].month + '月' + this.isFestival(this.start[0], this.start[1], true) + '日',
endDay: this.date[this.end[0]].month + '月' + this.isFestival(this.end[0], this.end[1], true) + '日',
day: this.day
};
/*此处应把需要的数据进行保存,如入住离开日期...添加到vuex然后再进行跳转到上一页
*不推荐使用本地缓存,下面是缓存的示例
*/
uni.setStorage({
key: 'Time',
data: JSON.stringify(obj)
});
console.log(JSON.stringify(obj))
this.$store.commit('upcheckinDate', obj.start);
this.$store.commit('upcheckoutDate', obj.end);
this.$emit('getdata', true);
}
}
};
</script>
<style>
/**确认按钮**/
.submit {
width: 100%;
background: white;
bottom: 0upx;
height: auto;
}
.sub-btn {
height: auto;
border-radius: 10upx;
background: #fff;
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 500;
color: #80c5e7;
height: 100rpx;
}
.content {
z-index: 999;
width: 700rpx;
background: #fff;
border-radius: 10rpx;
overflow: hidden;
}
/**不能预订**/
/* 入住离开时间的color */
.bg-orange {
background-color: rgba(128, 197, 231, 1);
font-size: 18upx;
}
.bg-higlt-orange {
background-color: rgba(128, 197, 231, 1);
color: #fff;
}
/* 节假日的日期样式 */
.is-festival {
font-size: 18upx;
color: orange;
}
/** 非节假日的日期样式**/
.not-festival {
font-size: 18upx;
color: white;
}
/***入住离开时间的日历样式*/
.not-sub {
color: #222222;
background: #dddddd;
}
.select-out-riqiitem {
background: #ffffff;
}
.select-style {
color: white;
font-size: 20upx;
padding-top: 4upx;
}
.time-out {
text-decoration: line-through;
color: #c0c0c0;
}
/**
* 点击日期的样式
*/
.bg {
background: orange;
}
/**
* 日期部分
*/
.section {
width: 100%;
height: 500rpx;
overflow: scroll;
padding-top: 0upx;
background-color: #ffffff;
}
.section2 > .riqiitem > .year {
text-align: center;
height: 100upx;
line-height: 100upx;
font-size: 30upx;
font-weight: bold;
/* padding-left:30upx;
padding-right: 30upx; */
}
.section2 > .riqiitem > .day {
display: flex;
flex-wrap: wrap;
text-align: center;
margin-left: 5px;
margin-right: 5px;
}
.section2 > .riqiitem > .day > .day-list {
margin-top: 10upx;
margin-bottom: 10upx;
min-height: 80upx;
max-height: 150upx;
display: flex;
font-size: 28upx;
flex-direction: column;
align-riqiitems: center;
justify-content: center;
}
/**
* 头部固定
*/
.header {
width: 100%;
background: white;
}
.bar {
width: 100%;
height: var(--status-bar-height);
background: #222222;
}
/**
* 关闭清空
*/
.set {
height: 100upx;
padding-left: 30upx;
padding-right: 30upx;
align-riqiitems: center;
display: flex;
justify-content: space-between;
}
/**
* 入住离开时间
*/
.in-and-out {
height: 90upx;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
position: relative;
font-size: 30rpx;
font-family: PingFang;
font-weight: 400;
color: #484848;
}
/**
* 入住离开的view
*/
.in-and-out > .riqiitem {
display: flex;
flex-direction: column;
height: 100upx;
}
/**
* 未选择入离时间时的文字样式
*/
.in-and-out > .text {
margin-top: 100upx;
font-weight: bold;
font-size: 36upx;
color: #c0c0c0;
}
/**
* 一共选择了多少晚的样式
*/
.in-and-out > .riqiitem > .count-border {
width: 200upx;
font-size: 28upx;
height: 40upx;
margin-top: 48upx;
text-align: center;
}
.gray {
color: #c0c0c0;
border-bottom: 1px solid #c0c0c0;
}
.orange {
color: orange;
border-bottom: 1px solid orange;
}
/**
* 共多少晚
*/
.in-and-out > .riqiitem > .count-border > .count {
font-size: 10px;
}
/**
* 周一到周日
*/
.week {
border-bottom: 1px solid #dcdcdc;
height: 70upx;
display: flex;
margin-bottom: 20upx;
justify-content: space-between;
align-riqiitems: center;
padding-left: 25px;
padding-right: 25px;
font-size: 22upx;
background: white;
}
.isa {
color: red;
}
.isa2 {
color: red;
}
.qingkong {
position: absolute;
right: 20rpx;
font-size: 30rpx;
font-family: PingFang;
font-weight: 400;
color: #80c5e7;
}
</style>
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import moment from 'moment';
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
hotelday: 0,
checkinDate: moment().subtract('days', -1).format('YYYY-MM-DD'),
checkoutDate: moment()
.subtract('days', -2)
.format('YYYY-MM-DD'),
},
mutations: {
hotelday(state, hotelday) {
state.hotelday = hotelday
},
meishiday(state, meishiday) {
state.meishiday = meishiday
},
},
getters: {
meishiday(state) {
return state.meishiday
},
hotelday(state) {
return state.hotelday
},
checkoutDate(state, provider) {
return state.checkoutDate
},
checkinDate(state, provider) {
return state.checkinDate
},
},
})
export default store
使用
<template>
<view>
<div class="datetime" @click="goriqi">
<div class="left">
<div class="itema">
<div class="itema1">{{ checkinDate | filterdata }}</div>
<div class="itema2">入住</div>
</div>
<div class="itemb"></div>
<div class="itema">
<div class="itema1">{{ checkoutDate | filterdata }}</div>
<div class="itema2">离店</div>
</div>
</div>
<div class="itemd">
<text>共{{ days }}晚</text>
<image src="../../static/icon_right.png" mode=""></image>
</div>
</div>
<uni-popup ref="popup" type="center"><riqi @getdata="close"></riqi></uni-popup>
</view>
</template>
<script>
import moment from 'moment';
import uniPopup from '@/components/uni-popup/uni-popup.vue';
import riqi from './riqi.vue';
import { mapState, mapGetters, mapMutations } from 'vuex';
export default {
components: { uniPopup, riqi },
computed: mapGetters(['checkinDate', 'checkoutDate']),
data() {
return {
showCaledar: false,
dateStr: '',
cityName: '',
list: [],
days: 0,
pageIndex: 1,
pageSize: 10,
serviceId: 0,
keyword: '',
HomeownersList: [],
HotelList: [],
open_city_id: '',
tjHotelList: [],
banner: [],
open_city_gratis_list: [],
startDate: '',
endDate: '',
betweenStart: '',
betweenEnd: '',
bo_find: {
image: ''
}
};
},
mounted() {
this.getday();
},
onShow() {
this.getday();
},
watch: {
checkinDate() {
this.getday();
},
checkoutDate() {
this.getday();
}
},
filters: {
filtersImg: function(img) {
return configs.baseUrl + img;
},
filterdata: function(e) {
let data2 = e.replace(/-/g, '/');
console.log(e);
return moment(data2).format('MM月DD日');
},
filterdata2: function(e, b) {
return moment(e).diff(moment(b), 'days');
}
},
methods: {
getday() {
this.days = moment(this.checkoutDate).diff(moment(this.checkinDate), 'days');
},
goriqi() {
this.$refs.popup.open();
},
close() {
this.$refs.popup.close();
}
}
};
</script>
<style lang="scss">
.datetime {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
height: 130rpx;
.left {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
}
.itema {
display: flex;
justify-content: center;
align-items: flex-start;
flex-wrap: nowrap;
flex-direction: column;
.itema1 {
font-size: 36rpx;
font-family: PingFang SC;
font-weight: 400;
color: #000000;
}
.itema2 {
font-size: 22rpx;
font-family: PingFang SC;
font-weight: 500;
color: #92959b;
}
}
.itemb {
width: 32rpx;
height: 2rpx;
background: #cecece;
margin-left: 40rpx;
margin-right: 30rpx;
}
.itemd {
font-size: 22rpx;
font-family: PingFang SC;
font-weight: 500;
color: #92959b;
image {
width: 12rpx;
height: 22rpx;
margin-right: 26rpx;
margin-left: 16rpx;
}
}
}
</style>