diff --git a/examples/docs/en-US/date-picker.md b/examples/docs/en-US/date-picker.md index 6ed677351f..8a5fcbb28d 100644 --- a/examples/docs/en-US/date-picker.md +++ b/examples/docs/en-US/date-picker.md @@ -64,7 +64,9 @@ value8: '', value9: '', value10: '', - value11: '' + value11: '', + value12: '', + value13: '' }; } }; @@ -329,6 +331,50 @@ If type is `daterange`, `default-value` sets the left side calendar. ``` ::: +### Default start & end time value + +When picking date range on the date panel with type `datetimerange`, `00:00:00` will be used as the default time value for start & end date. We can control it with option `default-time`. + +`default-time` accepts an array of string. The first item controls time value of the start date and the second item controls time value of the end date. + +:::demo +```html + + + +``` +::: + ### Formatted Value By default, DatePicker emits `Date` object. You can use `value-format` to designate the format of emitted value, it accepts the same format string of `format` attribute. @@ -394,6 +440,7 @@ This feature is at alpha stage. Feedback welcome. | picker-options | additional options, check the table below | object | — | {} | | range-separator | range separator | string | — | '-' | | default-value | optional, default date of the calendar | Date | anything accepted by `new Date()` | — | +| default-time | optional, the time value to use when select datetime range in date table (type `datetimerange`) | string[] | Array with length 2, each item is a string like `12:00:00`. The first item for the start datetime and then second item for the end datetime | — | | value-format | optional, format of binding value. If not specified, the binding value will be a Date object | string | year `yyyy`, month `MM`, day `dd`, hour `HH`, minute `mm`, second `ss`, AM/PM `A` | — | | name | same as `name` in native input | string | — | — | | unlink-panels | unlink two date-panels in range-picker | boolean | — | false | diff --git a/examples/docs/zh-CN/date-picker.md b/examples/docs/zh-CN/date-picker.md index c7dbda5ad5..e1df024553 100644 --- a/examples/docs/zh-CN/date-picker.md +++ b/examples/docs/zh-CN/date-picker.md @@ -64,7 +64,9 @@ value8: '', value9: '', value10: '', - value11: '' + value11: '', + value12: '', + value13: '' }; } }; @@ -324,6 +326,50 @@ ``` ::: +### 默认的起始与结束时刻 + +使用类型`datetimerange`选择时间范围时,在日期选择面板中选定起始与结束的日期,默认会使用该日期的`00:00:00`作为起始与结束的时刻;通过选项`default-time`可以控制选中起始与结束日期时所使用的具体时刻。 + +`default-time`接受一个数组,数组每项值为字符串,形如`12:00:00`,其中第一项控制起始日期的具体时刻,第二项控制结束日期的具体时刻。 + +:::demo +```html + + + +``` +::: + ### 返回值格式 默认情况下,组件接受并返回`Date`对象。 @@ -390,6 +436,7 @@ | picker-options | 当前时间日期选择器特有的选项参考下表 | object | — | {} | | range-separator | 选择范围时的分隔符 | string | — | '-' | | default-value | 可选,选择器打开时默认显示的时间 | Date | 可被`new Date()`解析 | — | +| default-time | 可选,选择器 type 为 `datetimerange`,范围选择选中日期时所使用的当日内具体时刻 | string[] | 数组,长度为 2,每项值为字符串,形如`12:00:00`,第一项指定开始日期的时刻,第二项指定结束日期的时刻,不指定会使用时刻 `00:00:00` | — | | value-format | 可选,绑定值的格式。不指定则绑定值为 Date 对象 | string | 年 `yyyy`,月 `MM`,日 `dd`,小时 `HH`,分 `mm`,秒 `ss`,AM/PM `A` | — | | name | 原生属性 | string | — | — | | unlink-panels | 在范围选择器里取消两个日期面板之间的联动 | boolean | — | false | diff --git a/packages/date-picker/src/panel/date-range.vue b/packages/date-picker/src/panel/date-range.vue index cff1fe4079..1e8bfeb917 100644 --- a/packages/date-picker/src/panel/date-range.vue +++ b/packages/date-picker/src/panel/date-range.vue @@ -213,6 +213,19 @@ } }; + const modifyWithGivenTime = (date, time) => { + if (date == null || time == null) { + return date; + } + time = parseDate(time, 'HH:mm:ss'); + return modifyTime( + date, + time.getHours(), + time.getMinutes(), + time.getSeconds() + ); + }; + export default { mixins: [Locale], @@ -301,6 +314,7 @@ popperClass: '', value: [], defaultValue: null, + defaultTime: null, minDate: '', maxDate: '', leftDate: new Date(), @@ -412,8 +426,9 @@ }, handleChangeRange(val) { - this.minDate = val.minDate; - this.maxDate = val.maxDate; + const defaultTime = this.defaultTime || []; + this.minDate = modifyWithGivenTime(val.minDate, defaultTime[0]); + this.maxDate = modifyWithGivenTime(val.maxDate, defaultTime[1]); this.rangeState = val.rangeState; }, @@ -480,17 +495,21 @@ }, handleRangePick(val, close = true) { - if (this.maxDate === val.maxDate && this.minDate === val.minDate) { + const defaultTime = this.defaultTime || []; + const minDate = modifyWithGivenTime(val.minDate, defaultTime[0]); + const maxDate = modifyWithGivenTime(val.maxDate, defaultTime[1]); + + if (this.maxDate === maxDate && this.minDate === minDate) { return; } this.onPick && this.onPick(val); - this.maxDate = val.maxDate; - this.minDate = val.minDate; + this.maxDate = maxDate; + this.minDate = minDate; // workaround for https://github.com/ElemeFE/element/issues/7539, should remove this block when we don't have to care about Chromium 55 - 57 setTimeout(() => { - this.maxDate = val.maxDate; - this.minDate = val.minDate; + this.maxDate = maxDate; + this.minDate = minDate; }, 10); if (!close || this.showTime) return; this.handleConfirm(); diff --git a/packages/date-picker/src/picker.vue b/packages/date-picker/src/picker.vue index 95cb2bb352..63c7da8e61 100644 --- a/packages/date-picker/src/picker.vue +++ b/packages/date-picker/src/picker.vue @@ -333,6 +333,7 @@ export default { }, value: {}, defaultValue: {}, + defaultTime: {}, rangeSeparator: { default: '-' }, @@ -701,6 +702,7 @@ export default { mountPicker() { this.picker = new Vue(this.panel).$mount(); this.picker.defaultValue = this.defaultValue; + this.picker.defaultTime = this.defaultTime; this.picker.popperClass = this.popperClass; this.popperElm = this.picker.$el; this.picker.width = this.reference.getBoundingClientRect().width; diff --git a/test/unit/specs/date-picker.spec.js b/test/unit/specs/date-picker.spec.js index 30f1ec31c8..08e2383ad0 100644 --- a/test/unit/specs/date-picker.spec.js +++ b/test/unit/specs/date-picker.spec.js @@ -1246,6 +1246,97 @@ describe('DatePicker', () => { }, DELAY); }); + it('select daterange with defaultTime min', done => { + + const vmWithDefaultTime = createVue({ + template: ` + + `, + data() { + return { + value: [new Date(2000, 10, 10, 10, 10), new Date(2000, 10, 11, 10, 10)], + defaultTime: ['11:59:59'] + }; + } + }, true).$refs.compo; + + setTimeout(_ => { + vmWithDefaultTime.$el.click(); + + setTimeout(_ => { + const pickers = vmWithDefaultTime.picker.$el.querySelectorAll('.el-date-range-picker__content'); + const leftCell = pickers[0].querySelector('td.available'); + const rightCell = pickers[1].querySelector('td.available'); + + triggerEvent(leftCell, 'mousemove', true); + triggerEvent(leftCell, 'click', true); + setTimeout(_ => { + triggerEvent(rightCell, 'mousemove', true); + triggerEvent(rightCell, 'click', true); + + setTimeout(_ => { + const { + minDate, + maxDate + } = vmWithDefaultTime.picker; + expect(minDate.getHours()).to.be.equal(11); + expect(minDate.getMinutes()).to.be.equal(59); + expect(minDate.getSeconds()).to.be.equal(59); + expect(maxDate.getHours()).to.be.equal(0); + expect(maxDate.getMinutes()).to.be.equal(0); + expect(maxDate.getSeconds()).to.be.equal(0); + done(); + }, DELAY); + }, DELAY); + }, DELAY); + }, DELAY * 2); // `DELAY * 2` to ensure this case passes in travis CI + }); + + it('select daterange with defaultTime min & max', done => { + const vmWithDefaultTime = createVue({ + template: ` + + `, + data() { + return { + value: [new Date(2000, 10, 10, 10, 10), new Date(2000, 10, 11, 10, 10)], + defaultTime: ['11:59:59', '18:00:00'] + }; + } + }, true).$refs.compo; + + setTimeout(_ => { + vmWithDefaultTime.$el.click(); + + setTimeout(_ => { + const pickers = vmWithDefaultTime.picker.$el.querySelectorAll('.el-date-range-picker__content'); + const leftCell = pickers[0].querySelector('td.available'); + const rightCell = pickers[1].querySelector('td.available'); + + triggerEvent(leftCell, 'mousemove', true); + triggerEvent(leftCell, 'click', true); + setTimeout(_ => { + triggerEvent(rightCell, 'mousemove', true); + triggerEvent(rightCell, 'click', true); + + setTimeout(_ => { + const { + minDate, + maxDate + } = vmWithDefaultTime.picker; + expect(minDate.getHours()).to.be.equal(11); + expect(minDate.getMinutes()).to.be.equal(59); + expect(minDate.getSeconds()).to.be.equal(59); + expect(maxDate.getHours()).to.be.equal(18); + expect(maxDate.getMinutes()).to.be.equal(0); + expect(maxDate.getSeconds()).to.be.equal(0); + done(); + }, DELAY); + }, DELAY); + }, DELAY); + }, DELAY * 2); // `DELAY * 2` to ensure this case passes in travis CI + }); + it('prev/next month button', done => { const leftBtn = vm.picker.$el.querySelector('.is-left .el-icon-arrow-left'); const rightBtn = vm.picker.$el.querySelector('.is-right .el-icon-arrow-right');