246 lines
9.2 KiB
Vue
246 lines
9.2 KiB
Vue
<template>
|
||
<view style="position: relative;">
|
||
<view class="uni-padding-wrap">
|
||
<view class="" style="font-size: 36rpx; line-height: 50rpx; color: #121212; text-align: center;width: 100%;margin-top: 52rpx;">选择时间</view>
|
||
<image src="@/static/icon/close2.png" style="width: 60rpx;height: 60rpx; position: absolute; top: 30rpx; right: 30rpx;" @click="closePopup"/>
|
||
</view>
|
||
<picker-view v-if="visible" :indicator-style="indicatorStyle" :value="value" @change="bindChange" class="picker-view">
|
||
<picker-view-column>
|
||
<view class="item" v-for="(item,index) in dateList" :key="index">{{item.label}}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="item" v-for="(item,index) in hourList" :key="index">{{item}}</view>
|
||
</picker-view-column>
|
||
<picker-view-column>
|
||
<view class="item" v-for="(item,index) in minuteList" :key="index">{{item}}</view>
|
||
</picker-view-column>
|
||
</picker-view>
|
||
<view class="line"></view>
|
||
<view class="btn">
|
||
<view class="btn1" @click="reset">重置</view>
|
||
<view class="btn2" @click="confirm">确定</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
|
||
<script>
|
||
export default {
|
||
data: function () {
|
||
const date = new Date();
|
||
const weekMap = ['日', '一', '二', '三', '四', '五', '六'];
|
||
// 生成今天起未来7天,若当天已过22:00则不加入当天
|
||
const dateList = [];
|
||
for (let i = 0; i < 3; i++) {
|
||
const d = new Date(date.getFullYear(), date.getMonth(), date.getDate() + i);
|
||
// 判断当天是否已过22:00
|
||
if (i === 0) {
|
||
const now = new Date();
|
||
if (now.getFullYear() === d.getFullYear() && now.getMonth() === d.getMonth() && now.getDate() === d.getDate()) {
|
||
if (now.getHours() > 21 || (now.getHours() === 21 && now.getMinutes() >= 60)) {
|
||
continue; // 跳过当天
|
||
}
|
||
}
|
||
}
|
||
const mm = (d.getMonth() + 1).toString().padStart(2, '0');
|
||
const dd = d.getDate().toString().padStart(2, '0');
|
||
const week = weekMap[d.getDay()];
|
||
dateList.push({
|
||
label: `${mm}月${dd}日周${week}`,
|
||
date: d
|
||
});
|
||
}
|
||
// 默认选中今天、当前小时、当前分钟
|
||
return {
|
||
title: 'picker-view',
|
||
dateList,
|
||
hourList: [],
|
||
minuteList: [],
|
||
value: [0, 0, 0],
|
||
visible: true,
|
||
indicatorStyle: `height: 50px;`
|
||
}
|
||
},
|
||
|
||
mounted() {
|
||
this.updateHourAndMinuteList(0, 0);
|
||
},
|
||
methods: {
|
||
bindChange: function (e) {
|
||
const val = e.detail.value;
|
||
// 选中项索引分别为dateList、hourList、minuteList
|
||
this.value = val;
|
||
// 联动更新小时和分钟
|
||
this.updateHourAndMinuteList(val[0], val[1]);
|
||
},
|
||
|
||
// 联动生成小时和分钟列表
|
||
updateHourAndMinuteList(dateIdx, hourIdx) {
|
||
const now = new Date();
|
||
const selectedDate = this.dateList[dateIdx]?.date;
|
||
let hourList = [];
|
||
let minuteList = [];
|
||
// 判断是否为今天
|
||
const isToday = selectedDate &&
|
||
selectedDate.getFullYear() === now.getFullYear() &&
|
||
selectedDate.getMonth() === now.getMonth() &&
|
||
selectedDate.getDate() === now.getDate();
|
||
if (isToday) {
|
||
// 如果当前时间已超过 22:00,则不显示任何可选时间
|
||
if (now.getHours() > 21 || (now.getHours() === 21 && now.getMinutes() >= 60)) {
|
||
hourList = [];
|
||
minuteList = [];
|
||
} else {
|
||
for (let i = 6; i <= 21; i++) {
|
||
if (i > now.getHours()) {
|
||
hourList.push(i < 10 ? `0${i}` : `${i}`);
|
||
} else if (i === now.getHours()) {
|
||
// 当前小时,分钟要过滤
|
||
let hasValidMinute = false;
|
||
for (let m = 0; m < 60; m += 10) {
|
||
if (m >= now.getMinutes()) {
|
||
hasValidMinute = true;
|
||
break;
|
||
}
|
||
}
|
||
if (hasValidMinute) {
|
||
hourList.push(i < 10 ? `0${i}` : `${i}`);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
for (let i = 6; i <= 21; i++) {
|
||
hourList.push(i < 10 ? `0${i}` : `${i}`);
|
||
}
|
||
}
|
||
// 选中的小时
|
||
let selectedHour = hourList[hourIdx] ? parseInt(hourList[hourIdx]) : parseInt(hourList[0]);
|
||
if (isToday && hourList.length > 0 && selectedHour === now.getHours()) {
|
||
for (let m = 0; m < 60; m += 10) {
|
||
if (m >= now.getMinutes()) {
|
||
minuteList.push(m < 10 ? `0${m}` : `${m}`);
|
||
}
|
||
}
|
||
} else if (hourList.length > 0) {
|
||
for (let m = 0; m < 60; m += 10) {
|
||
minuteList.push(m < 10 ? `0${m}` : `${m}`);
|
||
}
|
||
} else {
|
||
minuteList = [];
|
||
}
|
||
// 修正value
|
||
let value = [...this.value];
|
||
// hourIdx/minuteIdx 越界修正
|
||
if (value[1] >= hourList.length) value[1] = 0;
|
||
if (value[2] >= minuteList.length) value[2] = 0;
|
||
this.hourList = hourList;
|
||
this.minuteList = minuteList;
|
||
this.value = [dateIdx, value[1], value[2]];
|
||
},
|
||
|
||
// 重置
|
||
reset: function () {
|
||
// 重置为今天、可选的第一个小时和分钟
|
||
this.updateHourAndMinuteList(0, 0);
|
||
},
|
||
|
||
// 确认
|
||
confirm() {
|
||
// 获取选中索引
|
||
const [dateIdx, hourIdx, minuteIdx] = this.value;
|
||
const dateObj = this.dateList[dateIdx];
|
||
console.log("🚀 ~ dateObj:", this.value)
|
||
const hour = this.hourList[hourIdx];
|
||
const minute = this.minuteList[minuteIdx];
|
||
// 组装时间戳
|
||
let ts = 0;
|
||
let endts = 0;
|
||
if (dateObj && hour !== undefined && minute !== undefined) {
|
||
// 构造 yyyy-mm-dd hh:mm:00 字符串
|
||
const d = dateObj.date;
|
||
const yyyy = d.getFullYear();
|
||
|
||
const mm = (d.getMonth() + 1).toString().padStart(2, '0');
|
||
const dd = d.getDate().toString().padStart(2, '0');
|
||
const hh = hour.toString().padStart(2, '0');
|
||
const mi = minute.toString().padStart(2, '0');
|
||
const dateStr = `${yyyy}-${mm}-${dd} ${hh}:${mi}:00`;
|
||
const endStr = `${yyyy}-${mm}-${dd} 22:00:00`;
|
||
console.log("🚀 ~ endStr:", endStr)
|
||
ts = Math.floor(new Date(dateStr.replace(/-/g, '/')).getTime() / 1000);
|
||
endts = Math.floor(new Date(endStr.replace(/-/g, '/')).getTime() / 1000);
|
||
}
|
||
// 传递给父组件
|
||
this.$emit('confirm', {
|
||
date: dateObj.date,
|
||
dateLabel: dateObj.label,
|
||
hour,
|
||
minute,
|
||
value: `${dateObj.label} ${hour}:${minute}`,
|
||
timestamp: ts,
|
||
endtimestamp: endts
|
||
});
|
||
this.$emit('close');
|
||
},
|
||
|
||
closePopup() {
|
||
this.$emit('close');
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
|
||
<style>
|
||
.uni-padding-wrap {
|
||
display: flex;
|
||
}
|
||
|
||
.picker-view {
|
||
width: 750rpx;
|
||
height: 600rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.item {
|
||
line-height: 100rpx;
|
||
text-align: center;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.line {
|
||
margin-top: 62rpx;
|
||
height: 2rpx;
|
||
background: #E5E5E5;
|
||
}
|
||
|
||
.btn {
|
||
margin-top: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 32rpx;
|
||
}
|
||
|
||
.btn1, .btn2 {
|
||
width: 335rpx;
|
||
height: 90rpx;
|
||
text-align: center;
|
||
line-height: 90rpx;
|
||
font-size: 32rpx;
|
||
border-radius: 8rpx;
|
||
margin-bottom: 60rpx;
|
||
}
|
||
|
||
.btn1 {
|
||
background: #F6F7F8;
|
||
color: #303133;
|
||
}
|
||
|
||
.btn2 {
|
||
background: #365A9A;
|
||
color: #fff;
|
||
}
|
||
</style>
|