mirror of
https://github.com/youzan/vant.git
synced 2025-10-20 10:44:59 +00:00
[improvement] DatetimePicker: split into two components (#3995)
This commit is contained in:
210
src/datetime-picker/DatePicker.js
Normal file
210
src/datetime-picker/DatePicker.js
Normal file
@@ -0,0 +1,210 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import { isDate } from '../utils/validate/date';
|
||||
import { padZero } from '../utils/format/string';
|
||||
import { pickerProps } from '../picker/shared';
|
||||
import { getTrueValue, getMonthEndDay } from './utils';
|
||||
import { sharedProps, TimePickerMixin } from './shared';
|
||||
import Picker from '../picker';
|
||||
|
||||
const currentYear = new Date().getFullYear();
|
||||
const [createComponent, bem] = createNamespace('date-picker');
|
||||
|
||||
export default createComponent({
|
||||
mixins: [TimePickerMixin],
|
||||
|
||||
props: {
|
||||
...sharedProps,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'datetime'
|
||||
},
|
||||
minDate: {
|
||||
type: Date,
|
||||
default: () => new Date(currentYear - 10, 0, 1),
|
||||
validator: isDate
|
||||
},
|
||||
maxDate: {
|
||||
type: Date,
|
||||
default: () => new Date(currentYear + 10, 11, 31),
|
||||
validator: isDate
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(val) {
|
||||
val = this.formatValue(val);
|
||||
|
||||
if (val.valueOf() !== this.innerValue.valueOf()) {
|
||||
this.innerValue = val;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
ranges() {
|
||||
const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary(
|
||||
'max',
|
||||
this.innerValue
|
||||
);
|
||||
|
||||
const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary(
|
||||
'min',
|
||||
this.innerValue
|
||||
);
|
||||
|
||||
const result = [
|
||||
{
|
||||
type: 'year',
|
||||
range: [minYear, maxYear]
|
||||
},
|
||||
{
|
||||
type: 'month',
|
||||
range: [minMonth, maxMonth]
|
||||
},
|
||||
{
|
||||
type: 'day',
|
||||
range: [minDate, maxDate]
|
||||
},
|
||||
{
|
||||
type: 'hour',
|
||||
range: [minHour, maxHour]
|
||||
},
|
||||
{
|
||||
type: 'minute',
|
||||
range: [minMinute, maxMinute]
|
||||
}
|
||||
];
|
||||
|
||||
if (this.type === 'date') result.splice(3, 2);
|
||||
if (this.type === 'year-month') result.splice(2, 3);
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
formatValue(value) {
|
||||
if (!isDate(value)) {
|
||||
value = this.minDate;
|
||||
}
|
||||
|
||||
value = Math.max(value, this.minDate.getTime());
|
||||
value = Math.min(value, this.maxDate.getTime());
|
||||
|
||||
return new Date(value);
|
||||
},
|
||||
|
||||
getBoundary(type, value) {
|
||||
const boundary = this[`${type}Date`];
|
||||
const year = boundary.getFullYear();
|
||||
let month = 1;
|
||||
let date = 1;
|
||||
let hour = 0;
|
||||
let minute = 0;
|
||||
|
||||
if (type === 'max') {
|
||||
month = 12;
|
||||
date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
|
||||
hour = 23;
|
||||
minute = 59;
|
||||
}
|
||||
|
||||
if (value.getFullYear() === year) {
|
||||
month = boundary.getMonth() + 1;
|
||||
if (value.getMonth() + 1 === month) {
|
||||
date = boundary.getDate();
|
||||
if (value.getDate() === date) {
|
||||
hour = boundary.getHours();
|
||||
if (value.getHours() === hour) {
|
||||
minute = boundary.getMinutes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
[`${type}Year`]: year,
|
||||
[`${type}Month`]: month,
|
||||
[`${type}Date`]: date,
|
||||
[`${type}Hour`]: hour,
|
||||
[`${type}Minute`]: minute
|
||||
};
|
||||
},
|
||||
|
||||
onChange(picker) {
|
||||
const values = picker.getValues();
|
||||
const year = getTrueValue(values[0]);
|
||||
const month = getTrueValue(values[1]);
|
||||
const maxDate = getMonthEndDay(year, month);
|
||||
|
||||
let date = getTrueValue(values[2]);
|
||||
if (this.type === 'year-month') {
|
||||
date = 1;
|
||||
}
|
||||
|
||||
date = date > maxDate ? maxDate : date;
|
||||
|
||||
let hour = 0;
|
||||
let minute = 0;
|
||||
|
||||
if (this.type === 'datetime') {
|
||||
hour = getTrueValue(values[3]);
|
||||
minute = getTrueValue(values[4]);
|
||||
}
|
||||
|
||||
const value = new Date(year, month - 1, date, hour, minute);
|
||||
|
||||
this.innerValue = this.formatValue(value);
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$nextTick(() => {
|
||||
this.$emit('change', picker);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
updateColumnValue(value) {
|
||||
const { formatter } = this;
|
||||
let values = [
|
||||
formatter('year', `${value.getFullYear()}`),
|
||||
formatter('month', padZero(value.getMonth() + 1)),
|
||||
formatter('day', padZero(value.getDate()))
|
||||
];
|
||||
|
||||
if (this.type === 'datetime') {
|
||||
values.push(
|
||||
formatter('hour', padZero(value.getHours())),
|
||||
formatter('minute', padZero(value.getMinutes()))
|
||||
);
|
||||
}
|
||||
|
||||
if (this.type === 'year-month') {
|
||||
values = values.slice(0, 2);
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$refs.picker.setValues(values);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const props = {};
|
||||
Object.keys(pickerProps).forEach(key => {
|
||||
props[key] = this[key];
|
||||
});
|
||||
|
||||
return (
|
||||
<Picker
|
||||
class={bem()}
|
||||
ref="picker"
|
||||
columns={this.columns}
|
||||
onChange={this.onChange}
|
||||
onConfirm={this.onConfirm}
|
||||
onCancel={() => {
|
||||
this.$emit('cancel');
|
||||
}}
|
||||
{...{ props }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
Reference in New Issue
Block a user