Skip to content

Commit e47ff7d

Browse files
committed
Merge branch 'origin/dev' into dev
2 parents 2b61e87 + 9f34779 commit e47ff7d

File tree

7 files changed

+98
-14
lines changed

7 files changed

+98
-14
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ You can also override some of the default locale by `lang`.
124124
| clearable | if false, don't show the clear icon | `boolean` | true |
125125
| confirm | if true, need click the button to change value | `boolean` | false |
126126
| confirm-text | the text of confirm button | `string` | 'OK' |
127+
| multiple | if true, multi-select date | `boolean` | false |
127128
| disabled | disable the component | `boolean` | false |
128129
| disabled-date | specify the date that cannot be selected | `(date) => boolean` | - |
129130
| disabled-time | specify the time that cannot be selected | `(date) => boolean` | - |
@@ -132,6 +133,7 @@ You can also override some of the default locale by `lang`.
132133
| input-class | input classname | `string` | 'mx-input' |
133134
| input-attr | input attrs(eg: { name: 'date', id: 'foo'}) | `object` ||
134135
| open | open state of picker | `boolean` | - |
136+
| default-panel | default panel of the picker | year\|month | - |
135137
| popup-style | popup style | `object` ||
136138
| popup-class | popup classes | ||
137139
| shortcuts | set shortcuts to select | `Array<{text, onClick}>` | - |

README.zh-CN.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ import 'vue2-datepicker/locale/zh-cn';
122122
| clearable | 是否显示清除按钮 | `boolean` | true |
123123
| confirm | 是否需要确认 | `boolean` | false |
124124
| confirm-text | 确认按钮的文字 | `string` | 'OK' |
125+
| multiple | 如果是 true, 可以选择多个日期 | `boolean` | false |
125126
| disabled | 禁用组件 | `boolean` | false |
126127
| disabled-date | 禁止选择的日期 | `(date) => boolean` | - |
127128
| disabled-time | 禁止选择的时间 | `(date) => boolean` | - |
@@ -130,6 +131,7 @@ import 'vue2-datepicker/locale/zh-cn';
130131
| input-class | 输入框的类 | `string` | 'mx-input' |
131132
| input-attr | 输入框的其他属性(eg: { name: 'date', id: 'foo'}) | `object` ||
132133
| open | 控制弹出层的显示 | `boolean` | - |
134+
| default-panel | 控制打开的面板 | year\|month | - |
133135
| popup-style | 弹出层的样式 | `object` ||
134136
| popup-class | 弹出层的类 | ||
135137
| shortcuts | 设置快捷选择 | `Array<{text, onClick}>` | - |

__test__/date-picker.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,4 +387,35 @@ describe('DatePicker', () => {
387387
input.trigger('change');
388388
expect(wrapper.emitted().input).toEqual([[[text, text]], [[text, text]], [[text, text]]]);
389389
});
390+
391+
it('prop: multiple', () => {
392+
const value = [new Date(2020, 5, 6), new Date(2020, 6, 7)];
393+
wrapper = mount(DatePicker, {
394+
propsData: {
395+
multiple: true,
396+
open: true,
397+
value,
398+
},
399+
});
400+
wrapper.find('.mx-date-row .active').trigger('click');
401+
expect(wrapper.emitted().input[0][0]).toEqual(value.slice(0, 1));
402+
wrapper.find('[title="2020-07-15"]').trigger('click');
403+
expect(wrapper.emitted().input[1][0]).toEqual(value.concat(new Date(2020, 6, 15)));
404+
});
405+
406+
it('prop: invalid multiple', () => {
407+
wrapper = shallowMount(DatePicker, {
408+
propsData: {
409+
multiple: true,
410+
range: true,
411+
},
412+
});
413+
const { vm } = wrapper;
414+
expect(vm.validMultipleType).toBe(false);
415+
wrapper.setProps({
416+
range: false,
417+
type: 'datetime',
418+
});
419+
expect(vm.validMultipleType).toBe(false);
420+
});
390421
});

example/demo/DisabledDateTime.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ export default {
3838
data() {
3939
return {
4040
value1: new Date(),
41-
value2: new Date(),
4241
value3: '',
4342
value4: '',
44-
value5: '',
4543
};
4644
},
4745
methods: {

src/calendar/calendar-panel.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ export default {
240240
initCalendar() {
241241
let calendarDate = this.calendar;
242242
if (!isValidDate(calendarDate)) {
243-
calendarDate = getValidDate(this.innerValue[0], this.defaultValue);
243+
const { length } = this.innerValue;
244+
calendarDate = getValidDate(length > 0 ? this.innerValue[length - 1] : this.defaultValue);
244245
}
245246
this.innerCalendar = calendarDate;
246247
},
@@ -249,7 +250,7 @@ export default {
249250
},
250251
emitDate(date, type) {
251252
if (!this.isDisabled(date)) {
252-
this.$emit('select', date, type);
253+
this.$emit('select', date, type, this.innerValue);
253254
// someone need get the first selected date to set range value. (#429)
254255
this.dispatch('DatePicker', 'pick', date, type);
255256
}
@@ -287,7 +288,7 @@ export default {
287288
const nextCalendar = setYear(this.innerCalendar, year);
288289
this.updateCalendar(nextCalendar, 'year');
289290
this.handelPanelChange('month');
290-
if (this.partialUpdate && this.innerValue[0]) {
291+
if (this.partialUpdate && this.innerValue.length === 1) {
291292
const date = setYear(this.innerValue[0], year);
292293
this.emitDate(date, 'year');
293294
}
@@ -301,7 +302,7 @@ export default {
301302
const nextCalendar = setMonth(this.innerCalendar, month);
302303
this.updateCalendar(nextCalendar, 'month');
303304
this.handelPanelChange('date');
304-
if (this.partialUpdate && this.innerValue[0]) {
305+
if (this.partialUpdate && this.innerValue.length === 1) {
305306
const date = setMonth(setYear(this.innerValue[0], this.calendarYear), month);
306307
this.emitDate(date, 'month');
307308
}

src/date-picker.vue

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090

9191
<script>
9292
import { parse, format, getWeek } from 'date-format-parse';
93-
import { isValidDate, isValidRangeDate } from './util/date';
93+
import { isValidDate, isValidRangeDate, isValidDates } from './util/date';
9494
import { pick, isObject, mergeDeep } from './util/base';
9595
import { getLocale, getLocaleFieldValue } from './locale';
9696
import Popup from './popup';
@@ -157,9 +157,15 @@ export default {
157157
type: Boolean,
158158
default: false,
159159
},
160+
multiple: {
161+
type: Boolean,
162+
default: false,
163+
},
160164
rangeSeparator: {
161165
type: String,
162-
default: ' ~ ',
166+
default() {
167+
return this.multiple ? ',' : ' ~ ';
168+
},
163169
},
164170
lang: {
165171
type: [String, Object],
@@ -222,6 +228,9 @@ export default {
222228
type: String,
223229
default: 'OK',
224230
},
231+
renderInputText: {
232+
type: Function,
233+
},
225234
shortcuts: {
226235
type: Array,
227236
validator(value) {
@@ -262,6 +271,10 @@ export default {
262271
},
263272
innerValue() {
264273
let { value } = this;
274+
if (this.validMultipleType) {
275+
value = Array.isArray(value) ? value : [];
276+
return value.map(this.value2date);
277+
}
265278
if (this.range) {
266279
value = Array.isArray(value) ? value.slice(0, 2) : [null, null];
267280
return value.map(this.value2date);
@@ -272,6 +285,9 @@ export default {
272285
if (this.userInput !== null) {
273286
return this.userInput;
274287
}
288+
if (typeof this.renderInputText === 'function') {
289+
return this.renderInputText(this.innerValue);
290+
}
275291
if (!this.isValidValue(this.innerValue)) {
276292
return '';
277293
}
@@ -290,6 +306,10 @@ export default {
290306
}
291307
return getLocale(this.lang);
292308
},
309+
validMultipleType() {
310+
const types = ['date', 'month', 'year'];
311+
return this.multiple && !this.range && types.indexOf(this.type) !== -1;
312+
},
293313
},
294314
watch: {
295315
innerValue: {
@@ -368,14 +388,30 @@ export default {
368388
}
369389
},
370390
isValidValue(value) {
371-
const validate = this.range ? isValidRangeDate : isValidDate;
372-
return validate(value);
391+
if (this.validMultipleType) {
392+
return isValidDates(value);
393+
}
394+
if (this.range) {
395+
return isValidRangeDate(value);
396+
}
397+
return isValidDate(value);
373398
},
374-
handleSelectDate(val, type) {
399+
handleMultipleDates(date, dates) {
400+
if (this.validMultipleType && dates) {
401+
const nextDates = dates.filter(v => v.getTime() !== date.getTime());
402+
if (nextDates.length === dates.length) {
403+
nextDates.push(date);
404+
}
405+
return nextDates;
406+
}
407+
return date;
408+
},
409+
handleSelectDate(val, type, dates) {
410+
val = this.handleMultipleDates(val, dates);
375411
if (this.confirm) {
376412
this.currentValue = val;
377413
} else {
378-
this.emitValue(val, type);
414+
this.emitValue(val, this.validMultipleType ? `multiple-${type}` : type);
379415
}
380416
},
381417
handleClear() {
@@ -421,9 +457,13 @@ export default {
421457
return;
422458
}
423459
let date;
424-
if (this.range) {
460+
if (this.validMultipleType) {
461+
date = text.split(this.rangeSeparator).map(v => this.parseDate(v.trim(), this.format));
462+
} else if (this.range) {
425463
let arr = text.split(this.rangeSeparator);
426464
if (arr.length !== 2) {
465+
// Maybe the separator during the day is the same as the separator for the date
466+
// eg: 2019-10-09-2020-01-02
427467
arr = text.split(this.rangeSeparator.trim());
428468
}
429469
date = arr.map(v => this.parseDate(v.trim(), this.format));

src/util/date.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,19 @@ export function isValidRangeDate(date) {
1515
return Array.isArray(date) && date.length === 2 && date.every(isValidDate) && date[0] <= date[1];
1616
}
1717

18+
export function isValidDates(dates) {
19+
return Array.isArray(dates) && dates.every(isValidDate);
20+
}
21+
1822
export function getValidDate(value, ...backup) {
1923
const date = new Date(value);
20-
return isValidDate(date) ? date : getValidDate(...backup);
24+
if (isValidDate(date)) {
25+
return date;
26+
}
27+
if (backup.length) {
28+
return getValidDate(...backup);
29+
}
30+
return new Date();
2131
}
2232

2333
export function assignTime(target, source) {

0 commit comments

Comments
 (0)