wx-starlock/components/LockDateHourPicker/LockDateHourPicker.vue
2025-02-12 10:51:44 +08:00

277 lines
8.0 KiB
Vue

<template>
<view>
<view @click="openPicker" class="flex items-center bg-white font-bold text-base h-100 w-full">
<view class="w-168 ml-4 leading-[100rpx]">{{ title }}</view>
<view class="mr-4 text-right w-[518rpx] h-100 leading-[100rpx]">
{{ timeFormat(value, 'yyyy-mm-dd h:M') }}
</view>
</view>
<up-popup :show="show" @close="closePicker" mode="bottom" bgColor="transparent" round="32rpx">
<view class="w-750 bg-white">
<view class="flex justify-between items-center px-4 py-3 text-lg">
<text class="text-gray-500" @click="closePicker">取消</text>
<text class="font-bold">{{ title }}</text>
<text class="text-blue-500" @click="confirmSelection">确定</text>
</view>
<picker-view
:value="pickerIndex"
class="h-250px"
indicator-style="height:50px"
@change="onPickerChange"
:immediate-change="true"
>
<picker-view-column>
<view v-for="year in years" :key="year" class="text-center text-lg leading-10"
>{{ year }}</view
>
</picker-view-column>
<picker-view-column>
<view v-for="month in months" :key="month" class="text-center text-lg leading-10"
>{{ month }}</view
>
</picker-view-column>
<picker-view-column>
<view v-for="day in days" :key="day" class="text-center text-lg leading-10"
>{{ day }}</view
>
</picker-view-column>
<picker-view-column>
<view v-for="hour in hours" :key="hour" class="text-center text-lg leading-10"
>{{ hour }}</view
>
</picker-view-column>
</picker-view>
</view>
</up-popup>
</view>
</template>
<script setup>
import { ref, watch, computed } from 'vue'
import { timeFormat } from 'uview-plus'
const props = defineProps({
title: { type: String, default: '请选择时间' },
value: { type: String, default: '' },
minDate: { type: Number, required: true },
maxDate: { type: Number, required: true }
})
const emit = defineEmits(['changeTime'])
const openPicker = () => {
show.value = true
initPickerData(props.value)
}
const closePicker = () => {
show.value = false
}
const parseDate = timestamp => {
const date = new Date(timestamp)
return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hour: date.getHours()
}
}
const minDateParsed = computed(() => parseDate(props.minDate))
const maxDateParsed = computed(() => parseDate(props.maxDate))
const show = ref(false)
const years = ref([])
const months = ref([])
const days = ref([])
const hours = ref([])
const pickerIndex = ref([0, 0, 0, 0])
const tempPickerValue = ref({
year: 0,
month: 0,
day: 0,
hour: 0
})
const generateYears = () => {
const minYear = minDateParsed.value.year
const maxYear = maxDateParsed.value.year
return Array.from({ length: maxYear - minYear + 1 }, (_, i) => minYear + i)
}
const updateMonths = year => {
let monthsList = []
const minMonth = year === minDateParsed.value.year ? minDateParsed.value.month : 1
const maxMonth = year === maxDateParsed.value.year ? maxDateParsed.value.month : 12
for (let month = minMonth; month <= maxMonth; month++) {
monthsList.push(month)
}
months.value = monthsList
return monthsList
}
const updateDays = (year, month) => {
const daysInMonth = new Date(year, month, 0).getDate()
let minDay = 1
let maxDay = daysInMonth
if (year === minDateParsed.value.year && month === minDateParsed.value.month) {
minDay = minDateParsed.value.day
}
if (year === maxDateParsed.value.year && month === maxDateParsed.value.month) {
maxDay = maxDateParsed.value.day
}
maxDay = Math.min(maxDay, daysInMonth)
if (minDay > maxDay) {
days.value = [1]
return [1]
}
const daysList = Array.from({ length: maxDay - minDay + 1 }, (_, i) => minDay + i)
days.value = daysList
return daysList
}
const updateHours = (year, month, day) => {
let startHour = 0
let endHour = 24
if (
year === minDateParsed.value.year &&
month === minDateParsed.value.month &&
day === minDateParsed.value.day
) {
startHour = minDateParsed.value.hour
}
if (
year === maxDateParsed.value.year &&
month === maxDateParsed.value.month &&
day === maxDateParsed.value.day
) {
endHour = maxDateParsed.value.hour
}
const hoursList = Array.from({ length: endHour - startHour + 1 }, (_, i) => startHour + i)
hours.value = hoursList
return hoursList
}
const onPickerChange = event => {
const [yearIndex, monthIndex, dayIndex, hourIndex] = event.detail.value
const selectedYear = years.value[yearIndex]
const updatedMonths = updateMonths(selectedYear)
let selectedMonth = updatedMonths[Math.max(0, Math.min(monthIndex, updatedMonths.length - 1))]
if (selectedYear === minDateParsed.value.year) {
selectedMonth = Math.max(selectedMonth, minDateParsed.value.month)
}
const updatedDays = updateDays(selectedYear, selectedMonth)
let selectedDay = updatedDays[Math.max(0, Math.min(dayIndex, updatedDays.length - 1))]
if (selectedYear === minDateParsed.value.year && selectedMonth === minDateParsed.value.month) {
selectedDay = Math.max(selectedDay, minDateParsed.value.day)
}
const updatedHours = updateHours(selectedYear, selectedMonth, selectedDay)
let selectedHour = updatedHours[Math.max(0, Math.min(hourIndex, updatedHours.length - 1))]
if (
selectedYear === minDateParsed.value.year &&
selectedMonth === minDateParsed.value.month &&
selectedDay === minDateParsed.value.day
) {
selectedHour = Math.max(selectedHour, minDateParsed.value.hour)
}
console.log(1111, selectedYear, selectedMonth, selectedDay, selectedHour)
console.log(
1111,
yearIndex,
updatedMonths.indexOf(selectedMonth),
updatedDays.indexOf(selectedDay),
updatedHours.indexOf(selectedHour)
)
tempPickerValue.value = {
year: selectedYear,
month: selectedMonth,
day: selectedDay,
hour: selectedHour
}
pickerIndex.value = [
yearIndex,
updatedMonths.indexOf(selectedMonth),
updatedDays.indexOf(selectedDay),
updatedHours.indexOf(selectedHour)
]
}
const initPickerData = timestamp => {
if (!timestamp) {
timestamp = props.minDate
}
const date = new Date(timestamp)
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
let hour = date.getHours()
if (hour === 24) {
hour = 0
const nextDay = new Date(date)
nextDay.setDate(date.getDate() + 1)
year = nextDay.getFullYear()
month = nextDay.getMonth() + 1
day = nextDay.getDate()
}
if (year === minDateParsed.value.year) {
month = Math.max(month, minDateParsed.value.month)
if (month === minDateParsed.value.month) {
day = Math.max(day, minDateParsed.value.day)
if (day === minDateParsed.value.day) {
hour = Math.max(hour, minDateParsed.value.hour)
}
}
}
years.value = generateYears()
const updatedMonths = updateMonths(year)
const updatedDays = updateDays(year, month)
const updatedHours = updateHours(year, month, day)
tempPickerValue.value = {
year,
month,
day,
hour
}
pickerIndex.value = [
years.value.indexOf(year),
updatedMonths.indexOf(month),
updatedDays.indexOf(day),
updatedHours.indexOf(hour)
]
}
watch(() => props.value, initPickerData, { immediate: true })
const confirmSelection = () => {
const { year, month, day, hour } = tempPickerValue.value
const selectedDate = new Date(year, month - 1, day, hour, 0, 0, 0)
emit('changeTime', selectedDate.getTime())
show.value = false
}
</script>