feat(DatetimePicker): add month-day type (#6395)

This commit is contained in:
neverland 2020-05-28 10:35:06 +08:00 committed by GitHub
parent d8b6401cf0
commit 661fd07233
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 365 additions and 46 deletions

View File

@ -1,4 +1,4 @@
import { createNamespace } from '../utils';
import { createNamespace, get } from '../utils';
import { isDate } from '../utils/validate/date';
import { padZero } from '../utils/format/string';
import { getTrueValue, getMonthEndDay } from './utils';
@ -60,7 +60,7 @@ export default createComponent({
minMinute,
} = this.getBoundary('min', this.innerValue);
const result = [
let result = [
{
type: 'year',
range: [minYear, maxYear],
@ -83,8 +83,18 @@ export default createComponent({
},
];
if (this.type === 'date') result.splice(3, 2);
if (this.type === 'year-month') result.splice(2, 3);
if (this.type === 'date') {
result = result.slice(0, 3);
}
if (this.type === 'year-month') {
result = result.slice(0, 2);
}
if (this.type === 'month-day') {
result = result.slice(1, 3);
}
return result;
},
},
@ -139,35 +149,39 @@ export default createComponent({
},
updateInnerValue() {
const { type } = this;
const indexes = this.getPicker().getIndexes();
const getValue = (index) => {
const { values } = this.originColumns[index];
return getTrueValue(values[indexes[index]]);
};
const year = getValue(0);
const month = getValue(1);
const maxDate = getMonthEndDay(year, month);
let year;
let month;
let day;
let date;
if (this.type === 'year-month') {
date = 1;
if (type === 'month-day') {
year = this.innerValue.getFullYear();
month = getValue(0);
day = getValue(1);
} else {
date = getValue(2);
year = getValue(0);
month = getValue(1);
day = type === 'year-month' ? 1 : getValue(2);
}
date = date > maxDate ? maxDate : date;
const maxDay = getMonthEndDay(year, month);
day = day > maxDay ? maxDay : day;
let hour = 0;
let minute = 0;
if (this.type === 'datetime') {
if (type === 'datetime') {
hour = getValue(3);
minute = getValue(4);
}
const value = new Date(year, month - 1, date, hour, minute);
const value = new Date(year, month - 1, day, hour, minute);
this.innerValue = this.formatValue(value);
},
@ -203,6 +217,10 @@ export default createComponent({
values = values.slice(0, 2);
}
if (this.type === 'month-day') {
values = values.slice(1, 3);
}
this.$nextTick(() => {
this.getPicker().setValues(values);
});

View File

@ -74,6 +74,41 @@ export default {
};
```
### Choose Month-Day
```html
<van-datetime-picker
v-model="currentDate"
type="month-day"
title="Choose Month-Day"
:min-date="minDate"
:max-date="maxDate"
:formatter="formatter"
/>
```
```js
export default {
data() {
return {
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 10, 1),
currentDate: new Date(),
};
},
methods: {
formatter(type, val) {
if (type === 'month') {
return `${val} Month`;
} else if (type === 'day') {
return `${val} Day`;
}
return val;
},
},
};
```
### Choose Time
```html
@ -143,7 +178,6 @@ export default {
if (type === 'minute') {
return options.filter((option) => option % 5 === 0);
}
return options;
},
},
@ -156,7 +190,7 @@ export default {
| Attribute | Description | Type | Default |
| --- | --- | --- | --- |
| type | Can be set to `date` `time`<br> `year-month` | _string_ | `datetime` |
| type | Can be set to `date` `time`<br> `year-month` `month-day` | _string_ | `datetime` |
| title | Toolbar title | _string_ | `''` |
| confirm-button-text | Text of confirm button | _string_ | `Confirm` |
| cancel-button-text | Text of cancel button | _string_ | `Cancel` |

View File

@ -17,6 +17,8 @@ Vue.use(DatetimePicker);
### 选择年月日
DatetimePicker 通过 type 属性来定义需要选择的时间类型type 为 `date` 表示选择年月日。通过 min-date 和 max-date 属性可以确定可选的时间范围。
```html
<van-datetime-picker
v-model="currentDate"
@ -41,7 +43,7 @@ export default {
### 选择年月
通过传入`formatter`函数,可以对选项文字进行格式化处理
将 type 设置为 `year-month` 即可选择年份和月份。通过传入`formatter`函数,可以对选项文字进行格式化处理
```html
<van-datetime-picker
@ -76,8 +78,47 @@ export default {
};
```
### 选择年月
将 type 设置为 `month-day` 即可选择月份和日期(从 2.8.4 版本开始支持)
```html
<van-datetime-picker
v-model="currentDate"
type="month-day"
title="选择月日"
:min-date="minDate"
:max-date="maxDate"
:formatter="formatter"
/>
```
```js
export default {
data() {
return {
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 10, 1),
currentDate: new Date(),
};
},
methods: {
formatter(type, val) {
if (type === 'month') {
return `${val}月`;
} else if (type === 'day') {
return `${val}日`;
}
return val;
},
},
};
```
### 选择时间
将 type 设置为 `time` 即可选择时间(小时和分钟)
```html
<van-datetime-picker
v-model="currentTime"
@ -100,6 +141,8 @@ export default {
### 选择完整时间
将 type 设置为 `datetime` 即可选择完整时间,包括年月日和小时、分钟。
```html
<van-datetime-picker
v-model="currentDate"
@ -142,7 +185,6 @@ export default {
if (type === 'minute') {
return options.filter((option) => option % 5 === 0);
}
return options;
},
},
@ -155,7 +197,7 @@ export default {
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 类型,可选值为 `date` <br> `time` `year-month` | _string_ | `datetime` |
| type | 时间类型,可选值为 `date` `time` <br> `year-month` `month-day` | _string_ | `datetime` |
| title | 顶部栏标题 | _string_ | `''` |
| confirm-button-text | 确认按钮文字 | _string_ | `确认` |
| cancel-button-text | 取消按钮文字 | _string_ | `取消` |

View File

@ -1,41 +1,52 @@
<template>
<demo-section>
<demo-block :title="t('title2')">
<demo-block :title="t('dateType')">
<van-datetime-picker
v-model="currentDate2"
v-model="value.date"
type="date"
:title="t('title2')"
:title="t('dateType')"
:min-date="minDate"
:max-date="maxDate"
/>
</demo-block>
<demo-block :title="t('title3')">
<demo-block :title="t('yearMonthType')">
<van-datetime-picker
v-model="currentDate3"
v-model="value.yearMonth"
type="year-month"
:title="t('title3')"
:title="t('yearMonthType')"
:min-date="minDate"
:max-date="maxDate"
:formatter="formatter"
/>
</demo-block>
<demo-block :title="t('title4')">
<demo-block :title="t('monthDayType')">
<van-datetime-picker
v-model="currentTime1"
v-model="value.monthDayType"
type="month-day"
:title="t('monthDayType')"
:min-date="minDate"
:max-date="maxDate"
:formatter="formatter"
/>
</demo-block>
<demo-block :title="t('timeType')">
<van-datetime-picker
v-model="value.time"
type="time"
:title="t('title4')"
:title="t('timeType')"
:min-hour="10"
:max-hour="20"
/>
</demo-block>
<demo-block :title="t('title1')">
<demo-block :title="t('datetimeType')">
<van-datetime-picker
v-model="currentDate1"
v-model="value.datetime"
type="datetime"
:title="t('title1')"
:title="t('datetimeType')"
:min-date="minDate"
:max-date="maxDate"
/>
@ -43,7 +54,7 @@
<demo-block :title="t('optionFilter')">
<van-datetime-picker
v-model="currentTime2"
v-model="value.optionFilter"
type="time"
:title="t('optionFilter')"
:filter="filter"
@ -56,21 +67,25 @@
export default {
i18n: {
'zh-CN': {
title1: '选择完整时间',
title2: '选择年月日',
title3: '选择年月',
title4: '选择时间',
day: '日',
year: '年',
month: '月',
timeType: '选择时间',
dateType: '选择年月日',
datetimeType: '选择完整时间',
monthDayType: '选择月日',
yearMonthType: '选择年月',
optionFilter: '选项过滤器',
},
'en-US': {
title1: 'Choose DateTime',
title2: 'Choose Date',
title3: 'Choose Year-Month',
title4: 'Choose Time',
day: 'Day',
year: ' Year',
month: ' Month',
timeType: 'Choose Time',
dateType: 'Choose Date',
datetimeType: 'Choose DateTime',
monthDayType: 'Choose Month-Day',
yearMonthType: 'Choose Year-Month',
optionFilter: 'Option Filter',
},
},
@ -79,11 +94,14 @@ export default {
return {
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 10, 1),
currentDate1: new Date(2020, 0, 1),
currentDate2: null,
currentDate3: new Date(2020, 0, 1),
currentTime1: '12:00',
currentTime2: '12:00',
value: {
date: null,
time: '12:00',
datetime: new Date(2020, 0, 1),
monthDay: new Date(2020, 0, 1),
yearMonth: new Date(2020, 0, 1),
optionFilter: '12:00',
},
};
},
@ -95,6 +113,9 @@ export default {
if (type === 'month') {
return value + this.t('month');
}
if (type === 'day') {
return value + this.t('day');
}
return value;
},

View File

@ -249,6 +249,156 @@ exports[`renders demo correctly 1`] = `
<!---->
</div>
</div>
<div>
<div class="van-picker van-datetime-picker">
<div class="van-picker__toolbar"><button type="button" class="van-picker__cancel">取消</button>
<div class="van-ellipsis van-picker__title">选择月日</div><button type="button" class="van-picker__confirm">确认</button>
</div>
<!---->
<div class="van-picker__columns" style="height: 220px;">
<div class="van-picker-column">
<ul class="van-picker-column__wrapper" style="transform: translate3d(0, 88px, 0); transition-duration: 0ms; transition-property: none;">
<li role="button" tabindex="0" class="van-picker-column__item van-picker-column__item--selected" style="height: 44px;">
<div class="van-ellipsis">01月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">02月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">03月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">04月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">05月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">06月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">07月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">08月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">09月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">10月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">11月</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">12月</div>
</li>
</ul>
</div>
<div class="van-picker-column">
<ul class="van-picker-column__wrapper" style="transform: translate3d(0, 88px, 0); transition-duration: 0ms; transition-property: none;">
<li role="button" tabindex="0" class="van-picker-column__item van-picker-column__item--selected" style="height: 44px;">
<div class="van-ellipsis">01日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">02日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">03日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">04日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">05日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">06日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">07日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">08日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">09日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">10日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">11日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">12日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">13日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">14日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">15日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">16日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">17日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">18日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">19日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">20日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">21日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">22日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">23日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">24日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">25日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">26日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">27日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">28日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">29日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">30日</div>
</li>
<li role="button" tabindex="0" class="van-picker-column__item" style="height: 44px;">
<div class="van-ellipsis">31日</div>
</li>
</ul>
</div>
<div class="van-picker__mask" style="background-size: 100% 88px;"></div>
<div class="van-hairline-unset--top-bottom van-picker__frame" style="height: 44px;"></div>
</div>
<!---->
</div>
</div>
<div>
<div class="van-picker van-datetime-picker">
<div class="van-picker__toolbar"><button type="button" class="van-picker__cancel">取消</button>

View File

@ -68,6 +68,60 @@ test('confirm event', () => {
expect(wrapper.emitted('confirm')[1][0].getFullYear()).toEqual(2025);
});
test('year-month type', () => {
const date = new Date(2020, 10, 1, 0, 0);
const wrapper = mount(DatePicker, {
propsData: {
type: 'year-month',
value: date,
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 10, 1),
},
});
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')[0][0].getFullYear()).toEqual(2020);
expect(wrapper.emitted('confirm')[0][0].getMonth()).toEqual(10);
triggerDrag(wrapper.find('.van-picker-column'), 0, -100);
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')[1][0].getFullYear()).toEqual(2025);
expect(wrapper.emitted('confirm')[1][0].getMonth()).toEqual(0);
triggerDrag(wrapper.findAll('.van-picker-column').at(1), 0, -100);
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')[2][0].getFullYear()).toEqual(2025);
expect(wrapper.emitted('confirm')[2][0].getMonth()).toEqual(10);
});
test('month-day type', () => {
const date = new Date(2020, 10, 1, 0, 0);
const wrapper = mount(DatePicker, {
propsData: {
type: 'month-day',
value: date,
minDate: new Date(2020, 0, 1),
maxDate: new Date(2025, 10, 1),
},
});
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')[0][0].getMonth()).toEqual(10);
expect(wrapper.emitted('confirm')[0][0].getDate()).toEqual(1);
triggerDrag(wrapper.find('.van-picker-column'), 0, -100);
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')[1][0].getMonth()).toEqual(11);
expect(wrapper.emitted('confirm')[1][0].getDate()).toEqual(1);
triggerDrag(wrapper.findAll('.van-picker-column').at(1), 0, -100);
wrapper.find('.van-picker__confirm').trigger('click');
expect(wrapper.emitted('confirm')[2][0].getMonth()).toEqual(11);
expect(wrapper.emitted('confirm')[2][0].getDate()).toEqual(31);
});
test('cancel event', () => {
const wrapper = mount(DatePicker);