277 lines
8.0 KiB
Vue
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>
|