<template>
|
|
<view class="select-datetime-container">
|
|
<picker
|
|
mode="multiSelector"
|
|
:range="pickerRange"
|
|
:value="pickerValue"
|
|
@change="onPickerChange"
|
|
@columnchange="onColumnChange"
|
|
>
|
|
<slot>
|
|
<view class="datetime-display">
|
|
<text>{{ displayText }}</text>
|
|
<uv-icon name="arrow-down" size="16" color="#999"></uv-icon>
|
|
</view>
|
|
</slot>
|
|
</picker>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'SelectDatetime',
|
|
props: {
|
|
// 选择器类型: 'datetime', 'date', 'time'
|
|
type: {
|
|
type: String,
|
|
default: 'datetime'
|
|
},
|
|
// 默认值
|
|
value: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
// 占位文本
|
|
placeholder: {
|
|
type: String,
|
|
default: '请选择时间'
|
|
},
|
|
// 最小年份
|
|
minYear: {
|
|
type: Number,
|
|
default: 2020
|
|
},
|
|
// 最大年份
|
|
maxYear: {
|
|
type: Number,
|
|
default: 2030
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
pickerValue: [0, 0, 0, 0, 0],
|
|
pickerRange: [],
|
|
currentDate: new Date(),
|
|
selectedDateTime: ''
|
|
}
|
|
},
|
|
computed: {
|
|
displayText() {
|
|
if (this.selectedDateTime) {
|
|
return this.selectedDateTime;
|
|
}
|
|
return this.placeholder;
|
|
},
|
|
|
|
// 年份数组
|
|
years() {
|
|
const years = [];
|
|
for (let i = this.minYear; i <= this.maxYear; i++) {
|
|
years.push(i + '年');
|
|
}
|
|
return years;
|
|
},
|
|
|
|
// 月份数组
|
|
months() {
|
|
const months = [];
|
|
for (let i = 1; i <= 12; i++) {
|
|
months.push(i + '月');
|
|
}
|
|
return months;
|
|
},
|
|
|
|
// 日期数组
|
|
days() {
|
|
const year = this.minYear + this.pickerValue[0];
|
|
const month = this.pickerValue[1] + 1;
|
|
const daysInMonth = new Date(year, month, 0).getDate();
|
|
|
|
const days = [];
|
|
for (let i = 1; i <= daysInMonth; i++) {
|
|
days.push(i + '日');
|
|
}
|
|
return days;
|
|
},
|
|
|
|
// 小时数组
|
|
hours() {
|
|
const hours = [];
|
|
for (let i = 0; i < 24; i++) {
|
|
hours.push(i.toString().padStart(2, '0') + '时');
|
|
}
|
|
return hours;
|
|
},
|
|
|
|
// 分钟数组
|
|
minutes() {
|
|
const minutes = [];
|
|
for (let i = 0; i < 60; i += 5) { // 每5分钟一个选项
|
|
minutes.push(i.toString().padStart(2, '0') + '分');
|
|
}
|
|
return minutes;
|
|
}
|
|
},
|
|
mounted() {
|
|
this.initPicker();
|
|
if (this.value) {
|
|
this.parseValue(this.value);
|
|
}
|
|
},
|
|
watch: {
|
|
value(newVal) {
|
|
if (newVal) {
|
|
this.parseValue(newVal);
|
|
}
|
|
},
|
|
type() {
|
|
this.initPicker();
|
|
}
|
|
},
|
|
methods: {
|
|
// 初始化选择器
|
|
initPicker() {
|
|
switch (this.type) {
|
|
case 'datetime':
|
|
this.pickerRange = [this.years, this.months, this.days, this.hours, this.minutes];
|
|
this.pickerValue = [0, 0, 0, 0, 0];
|
|
break;
|
|
case 'date':
|
|
this.pickerRange = [this.years, this.months, this.days];
|
|
this.pickerValue = [0, 0, 0];
|
|
break;
|
|
case 'time':
|
|
this.pickerRange = [this.hours, this.minutes];
|
|
this.pickerValue = [0, 0];
|
|
break;
|
|
}
|
|
this.setDefaultValue();
|
|
},
|
|
|
|
// 设置默认值为当前时间
|
|
setDefaultValue() {
|
|
const now = new Date();
|
|
const year = now.getFullYear();
|
|
const month = now.getMonth();
|
|
const day = now.getDate() - 1;
|
|
const hour = now.getHours();
|
|
const minute = Math.floor(now.getMinutes() / 5);
|
|
|
|
switch (this.type) {
|
|
case 'datetime':
|
|
this.pickerValue = [
|
|
year - this.minYear,
|
|
month,
|
|
day,
|
|
hour,
|
|
minute
|
|
];
|
|
break;
|
|
case 'date':
|
|
this.pickerValue = [
|
|
year - this.minYear,
|
|
month,
|
|
day
|
|
];
|
|
break;
|
|
case 'time':
|
|
this.pickerValue = [hour, minute];
|
|
break;
|
|
}
|
|
this.updateDisplayText();
|
|
},
|
|
|
|
// 解析传入的值
|
|
parseValue(value) {
|
|
try {
|
|
const date = new Date(value);
|
|
if (isNaN(date.getTime())) {
|
|
return;
|
|
}
|
|
|
|
const year = date.getFullYear();
|
|
const month = date.getMonth();
|
|
const day = date.getDate() - 1;
|
|
const hour = date.getHours();
|
|
const minute = Math.floor(date.getMinutes() / 5);
|
|
|
|
switch (this.type) {
|
|
case 'datetime':
|
|
this.pickerValue = [
|
|
year - this.minYear,
|
|
month,
|
|
day,
|
|
hour,
|
|
minute
|
|
];
|
|
break;
|
|
case 'date':
|
|
this.pickerValue = [
|
|
year - this.minYear,
|
|
month,
|
|
day
|
|
];
|
|
break;
|
|
case 'time':
|
|
this.pickerValue = [hour, minute];
|
|
break;
|
|
}
|
|
this.updateDisplayText();
|
|
} catch (e) {
|
|
console.error('解析时间值失败:', e);
|
|
}
|
|
},
|
|
|
|
// 选择器值改变
|
|
onPickerChange(e) {
|
|
this.pickerValue = e.detail.value;
|
|
this.updateDisplayText();
|
|
this.emitChange();
|
|
},
|
|
|
|
// 列改变时更新日期选项
|
|
onColumnChange(e) {
|
|
const column = e.detail.column;
|
|
const value = e.detail.value;
|
|
|
|
// 如果改变的是年份或月份,需要更新日期选项
|
|
if ((column === 0 || column === 1) && this.type !== 'time') {
|
|
this.pickerValue[column] = value;
|
|
this.$nextTick(() => {
|
|
this.pickerRange[2] = this.days;
|
|
// 如果当前选择的日期超出了新月份的天数,调整到最后一天
|
|
if (this.pickerValue[2] >= this.days.length) {
|
|
this.pickerValue[2] = this.days.length - 1;
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
// 更新显示文本
|
|
updateDisplayText() {
|
|
switch (this.type) {
|
|
case 'datetime':
|
|
this.selectedDateTime = `${this.years[this.pickerValue[0]]} ${this.months[this.pickerValue[1]]} ${this.days[this.pickerValue[2]]} ${this.hours[this.pickerValue[3]]} ${this.minutes[this.pickerValue[4]]}`;
|
|
break;
|
|
case 'date':
|
|
this.selectedDateTime = `${this.years[this.pickerValue[0]]} ${this.months[this.pickerValue[1]]} ${this.days[this.pickerValue[2]]}`;
|
|
break;
|
|
case 'time':
|
|
this.selectedDateTime = `${this.hours[this.pickerValue[0]]} ${this.minutes[this.pickerValue[1]]}`;
|
|
break;
|
|
}
|
|
},
|
|
|
|
// 发送改变事件
|
|
emitChange() {
|
|
let dateValue = '';
|
|
|
|
switch (this.type) {
|
|
case 'datetime':
|
|
const year = this.minYear + this.pickerValue[0];
|
|
const month = (this.pickerValue[1] + 1).toString().padStart(2, '0');
|
|
const day = (this.pickerValue[2] + 1).toString().padStart(2, '0');
|
|
const hour = this.pickerValue[3].toString().padStart(2, '0');
|
|
const minute = (this.pickerValue[4] * 5).toString().padStart(2, '0');
|
|
dateValue = `${year}-${month}-${day} ${hour}:${minute}:00`;
|
|
break;
|
|
case 'date':
|
|
const dateYear = this.minYear + this.pickerValue[0];
|
|
const dateMonth = (this.pickerValue[1] + 1).toString().padStart(2, '0');
|
|
const dateDay = (this.pickerValue[2] + 1).toString().padStart(2, '0');
|
|
dateValue = `${dateYear}-${dateMonth}-${dateDay}`;
|
|
break;
|
|
case 'time':
|
|
const timeHour = this.pickerValue[0].toString().padStart(2, '0');
|
|
const timeMinute = (this.pickerValue[1] * 5).toString().padStart(2, '0');
|
|
dateValue = `${timeHour}:${timeMinute}:00`;
|
|
break;
|
|
}
|
|
|
|
this.$emit('change', {
|
|
value: dateValue,
|
|
displayText: this.selectedDateTime,
|
|
pickerValue: this.pickerValue
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.select-datetime-container {
|
|
width: 100%;
|
|
}
|
|
|
|
.datetime-display {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 20rpx;
|
|
background-color: #fff;
|
|
border: 1rpx solid #e0e0e0;
|
|
border-radius: 8rpx;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
|
|
text {
|
|
flex: 1;
|
|
}
|
|
}
|
|
</style>
|