<template>
<div>
<Poptip transfer placement="bottom" :style="{ width: '100%' }">
<Input
readonly
clearable
@on-clear="clearValue"
:style="{ width: '100%' }"
:value="finalValue"
:disabled="disabled"
icon="ios-calendar-outlin"
placeholder="请选择日期"
style="width: 200px"
/>
<template #title>
<div class="header">
<div @click="leftClick">左</div>
<div class="day-info">{{ dayInfo }}</div>
<div @click="rightClick">右</div>
</div>
</template>
<template #content>
<div class="content">
<div class="date-picker">
<div class="week-list">
<span v-for="(day, index) in weekList" :key="index">{{ day }}</span>
</div>
<div class="day-list">
<div v-for="(day, index) in dayList">
<div class="day-line">
<span
v-for="(day, indexx) in day"
@click="selectDay(index, indexx)"
:class="[
day.isNowMoth ? 'isNowMoth' : '',
day.isSelected ? 'isSelected' : '',
day.isNowDay ? 'isNowDay' : '',
day.weekday === 0 ? 'weekend' : 'weekday',
day.disabled ? 'disabled' : '',
]"
>{{ day.value }}</span
>
</div>
</div>
</div>
</div>
<div class="time-picker">
<div
:class="['time-item', item.isSelect ? 'select-item' : '', item.disabled ? 'disabled-item' : '']"
v-for="(item, index) in timeList"
:key="index"
@click="selectTime(index)"
>
{{ item.text }}
</div>
</div>
</div>
</template>
</Poptip>
</div>
</template>
<script>
import moment from 'moment';
export default {
model: {
prop: 'value',
event: 'change',
},
props: {
disabled: {
type: Boolean,
default: false,
},
value: {
type: [String, Number, Array],
default: '',
},
},
data() {
return {
finalSelect_day: '',
dayInfo: moment(new Date()).format('YYYY-MM'),
weekList: ['日', '一', '二', '三', '四', '五', '六'],
dayList: [
[1, 2, 3, 4, 5, 6, 7],
[8, 9, 10, 11, 12, 13, 14],
[15, 16, 17, 18, 19, 20, 21],
[22, 23, 24, 25, 26, 27, 28],
[29, 30, 31, 1, 2, 3, 4],
[5, 6, 7, 8, 9, 10, 11],
],
timeList: [
{
text: '8:00之前',
value: '0:00-8:00',
startTime: 0,
endTime: 8,
isSelect: false,
},
{
text: '8:00-12:00',
value: '8:00-12:00',
startTime: 8,
endTime: 12,
isSelect: false,
},
{
text: '12:00-16:00',
value: '12:00-16:00',
startTime: 12,
endTime: 16,
isSelect: false,
},
{
text: '16:00-20:00',
value: '16:00-20:00',
startTime: 16,
endTime: 20,
isSelect: false,
},
{
text: '20:00之后',
value: '20:00-24:00',
startTime: 20,
endTime: 24,
isSelect: false,
},
],
};
},
computed: {
finalValue() {
const { finalSelect_day } = this;
const selectTime = this.timeList.find((item) => item.isSelect);
if (finalSelect_day && selectTime) {
const startT = moment(finalSelect_day)
.hour(selectTime.startTime)
.minute(0)
.second(0)
.format(selectTime.disabled ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss');
const endT = moment(finalSelect_day)
.hour(selectTime.endTime)
.minute(0)
.second(0)
.format(selectTime.disabled ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss');
if (selectTime.disabled) {
this.timeList.forEach((item) => {
item.isSelect = false;
});
this.$emit('change', [startT, endT]);
return `${finalSelect_day}`;
} else {
this.$emit('change', [startT, endT]);
return `${finalSelect_day} ${selectTime.value}`;
}
} else {
if (this.value && this.value.length > 0) {
return this.finalSelect_day;
} else {
return '';
}
}
},
},
mounted() {
// 计算当前月份下的日期列表
if (this.value && this.value.length > 0 && this.value[0]) {
this.finalSelect_day = moment(new Date(this.value[0])).format('YYYY-MM-D');
const startH = moment(new Date(this.value[0])).hour();
const endH = moment(new Date(this.value[1])).hour();
this.timeList.forEach((item) => {
if (startH == item.startTime && endH == item.endTime) {
item.isSelect = true;
} else {
item.isSelect = false;
}
});
this.setDayList(this.finalSelect_day);
} else {
this.setDayList(new Date());
}
},
methods: {
setDayList(nday) {
// 获取当前月份的所有天数
const daysInMonth = moment(nday).daysInMonth();
const dayList = [];
for (let i = 1; i <= daysInMonth; i++) {
// year-month-day
dayList.push(moment(nday).format('YYYY-MM-') + i);
}
// 计算每一天是周几
dayList.forEach((day, index) => {
const weekday = moment(day).weekday();
dayList[index] = {
day: moment(day).format('YYYY-MM-D'),
value: moment(day).format('D'),
isNowMoth: true,
isNowDay: moment(day).isSame(new Date(), 'day'),
isSelected: moment(this.finalSelect_day).isSame(day, 'day'),
weekday: weekday,
};
});
const newList = [];
dayList.forEach((day, index) => {
if (index === 0 && day.weekday != 0) {
const endIndex = dayList.findIndex((item) => item.weekday === 6);
newList.push(dayList.slice(index, endIndex + 1));
}
// 以周日开始 切割成二维数组
if (day.weekday === 0) {
newList.push(dayList.slice(index, index + 7));
}
});
if (newList[0].length !== 7) {
let endIndex = 7 - newList[0].length;
let startTime = newList[0][0].day;
for (let i = 0; i < endIndex; i++) {
newList[0].unshift({
day: moment(startTime)
.subtract(i + 1, 'days')
.format('YYYY-MM-D'),
value: moment(startTime)
.subtract(i + 1, 'days')
.format('D'),
weekdays: moment(startTime)
.subtract(i + 1, 'days')
.weekday(),
});
}
}
if (newList[newList.length - 1].length !== 7) {
let endIndex = 7 - newList[newList.length - 1].length;
let startTime = newList[newList.length - 1][newList[newList.length - 1].length - 1].day;
for (let i = 0; i < endIndex; i++) {
newList[newList.length - 1].push({
day: moment(startTime)
.add(i + 1, 'days')
.format('YYYY-MM-D'),
value: moment(startTime)
.add(i + 1, 'days')
.format('D'),
weekdays: moment(startTime)
.add(i + 1, 'days')
.weekday(),
});
}
}
if (newList.length !== 6) {
const emptyList = [];
let startTime = newList[newList.length - 1][newList[newList.length - 1].length - 1].day;
for (let i = 0; i < 7; i++) {
emptyList.push({
day: moment(startTime)
.add(i + 1, 'days')
.format('YYYY-MM-D'),
value: moment(startTime)
.add(i + 1, 'days')
.format('D'),
weekdays: moment(startTime)
.add(i + 1, 'days')
.weekday(),
});
}
newList.push(emptyList);
}
// 今天之前的日期不可选择
newList.forEach((item, index) => {
item.forEach((day) => {
if (moment(day.day).isBefore(moment(), 'day')) {
day.disabled = true;
}
});
});
this.dayList = newList;
},
leftClick() {
const nday = moment(this.dayInfo).subtract(1, 'M');
this.setDayList(nday);
this.dayInfo = nday.format('YYYY-MM');
},
rightClick() {
const nday = moment(this.dayInfo).add(1, 'M');
this.setDayList(nday);
this.dayInfo = nday.format('YYYY-MM');
},
selectDay(index1, index2) {
const select = moment(this.dayList[index1][index2].day);
if (this.dayList[index1][index2].disabled) {
return;
}
this.finalSelect_day = moment(select).format('YYYY-MM-D');
// 重置isSelect
this.dayList.forEach((item) => {
item.forEach((day) => {
day.isSelected = false;
day.isNowDay = false;
});
});
if (!this.dayList[index1][index2].isNowMoth) {
this.setDayList(select);
this.dayInfo = select.format('YYYY-MM');
} else {
this.dayList[index1][index2].isSelected = true;
}
// 过滤时间段
this.timeList.forEach((item) => {
if (!moment(select).isSame(new Date(), 'day') || moment(new Date()).hour() < item.endTime) {
item.disabled = false;
} else {
item.disabled = true;
}
});
this.dayList = [...this.dayList];
},
selectTime(index) {
if (this.timeList[index].disabled) {
return;
}
this.timeList.forEach((item) => {
item.isSelect = false;
});
this.timeList[index].isSelect = true;
this.timeList = [...this.timeList];
},
clearValue() {
this.finalSelect_day = '';
this.timeList.forEach((item) => {
item.isSelect = false;
});
this.setDayList(new Date());
this.dayInfo = moment(new Date()).format('YYYY-MM');
this.$emit('change', []);
},
},
};
</script>
<style lang="less" scoped>
/deep/.ivu-poptip-title {
padding: 0 !important;
}
/deep/.ivu-poptip-body {
padding: 0 !important;
}
/deep/ .ivu-poptip-arrow {
display: none !important;
}
/deep/ .ivu-poptip-arrow::after {
display: none !important;
}
/deep/ .ivu-poptip-rel {
width: 100%;
}
.header {
width: 280px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 10px;
.day-info {
font-size: 15px;
}
}
.content {
display: flex;
justify-content: space-between;
align-items: top;
width: 280px;
padding: 5px 0px;
padding-left: 10px;
.date-picker {
width: 210px;
.week-list {
span {
display: inline-block;
text-align: center;
width: 100%;
padding: 3px;
font-size: 15px;
}
display: flex;
justify-content: space-between;
align-items: center;
}
.day-list {
.day-line {
display: flex;
justify-content: space-between;
align-items: center;
span {
cursor: pointer;
display: inline-block;
width: 100%;
text-align: center;
padding: 3px;
font-size: 15px;
color: #ccc;
}
.isNowMoth {
color: #595959;
}
.isSelected {
background: #2d8cf0;
color: #fff;
border-radius: 3px;
}
.isNowDay {
border: 1px solid #2d8cf0;
border-radius: 3px;
}
.disabled {
color: #ccc;
}
}
}
}
.time-picker {
width: 90px;
margin-left: 10px;
text-align: center;
border-left: 1px solid #ececec;
.time-item {
height: 40px;
line-height: 40px;
border-bottom: 1px solid #ececec;
cursor: pointer;
}
.select-item {
background: #409eff;
color: #fff;
}
.disabled-item {
color: #ccc;
}
}
}
.footer {
display: flex;
justify-content: flex-end;
align-items: center;
width: 100%;
padding: 8px 10px;
}
</style>
最后修改:2024 年 09 月 26 日
© 允许规范转载