Эх сурвалжийг харах

DatePicker: fix date clamping during navigation (#9577)

Jiewei Qian 7 жил өмнө
parent
commit
5b0b1e7e92

+ 23 - 19
packages/date-picker/src/panel/date-range.vue

@@ -190,6 +190,8 @@
     isDate,
     modifyDate,
     modifyTime,
+    prevYear,
+    nextYear,
     prevMonth,
     nextMonth
   } from '../util';
@@ -557,17 +559,14 @@
         }
       },
 
+      // leftPrev*, rightNext* need to take care of `unlinkPanels`
       leftPrevYear() {
-        this.leftDate = modifyDate(this.leftDate, this.leftYear - 1, this.leftMonth, this.leftMonthDate);
+        this.leftDate = prevYear(this.leftDate);
         if (!this.unlinkPanels) {
           this.rightDate = nextMonth(this.leftDate);
         }
       },
 
-      leftNextYear() {
-        this.leftDate = modifyDate(this.leftDate, this.leftYear + 1, this.leftMonth, this.leftMonthDate);
-      },
-
       leftPrevMonth() {
         this.leftDate = prevMonth(this.leftDate);
         if (!this.unlinkPanels) {
@@ -575,27 +574,15 @@
         }
       },
 
-      leftNextMonth() {
-        this.leftDate = nextMonth(this.leftDate);
-      },
-
-      rightPrevYear() {
-        this.rightDate = modifyDate(this.rightDate, this.rightYear - 1, this.rightMonth, this.rightMonthDate);
-      },
-
       rightNextYear() {
         if (!this.unlinkPanels) {
-          this.leftDate = modifyDate(this.leftDate, this.leftYear + 1, this.leftMonth, this.leftMonthDate);
+          this.leftDate = nextYear(this.leftDate);
           this.rightDate = nextMonth(this.leftDate);
         } else {
-          this.rightDate = modifyDate(this.rightDate, this.rightYear + 1, this.rightMonth, this.rightMonthDate);
+          this.rightDate = nextYear(this.rightDate);
         }
       },
 
-      rightPrevMonth() {
-        this.rightDate = prevMonth(this.rightDate);
-      },
-
       rightNextMonth() {
         if (!this.unlinkPanels) {
           this.leftDate = nextMonth(this.leftDate);
@@ -605,6 +592,23 @@
         }
       },
 
+      // leftNext*, rightPrev* are called when `unlinkPanels` is true
+      leftNextYear() {
+        this.leftDate = nextYear(this.leftDate);
+      },
+
+      leftNextMonth() {
+        this.leftDate = nextMonth(this.leftDate);
+      },
+
+      rightPrevYear() {
+        this.rightDate = prevYear(this.rightDate);
+      },
+
+      rightPrevMonth() {
+        this.rightDate = prevMonth(this.rightDate);
+      },
+
       handleConfirm(visible = false) {
         this.$emit('pick', [this.minDate, this.maxDate], visible);
       },

+ 4 - 3
packages/date-picker/src/panel/date.vue

@@ -150,7 +150,8 @@
     prevYear,
     nextYear,
     prevMonth,
-    nextMonth
+    nextMonth,
+    changeYearMonthAndClampDate
   } from '../util';
   import Locale from 'element-ui/src/mixins/locale';
   import ElInput from 'element-ui/packages/input';
@@ -304,7 +305,7 @@
           this.date = modifyDate(this.date, this.year, month, 1);
           this.emit(this.date);
         } else {
-          this.date = modifyDate(this.date, this.year, month, this.monthDate);
+          this.date = changeYearMonthAndClampDate(this.date, this.year, month);
           // TODO: should emit intermediate value ??
           // this.emit(this.date);
           this.currentView = 'date';
@@ -325,7 +326,7 @@
           this.date = modifyDate(this.date, year, 0, 1);
           this.emit(this.date);
         } else {
-          this.date = modifyDate(this.date, year, this.month, this.monthDate);
+          this.date = changeYearMonthAndClampDate(this.date, year, this.month);
           // TODO: should emit intermediate value ??
           // this.emit(this.date, true);
           this.currentView = 'month';

+ 20 - 26
packages/date-picker/src/util/index.js

@@ -181,43 +181,37 @@ export const timeWithinRange = function(date, selectableRange, format) {
   return limitedDate.getTime() === date.getTime();
 };
 
-export const prevMonth = function(date) {
-  let year = date.getFullYear();
-  let month = date.getMonth();
-  if (month === 0) {
-    year -= 1;
-    month = 11;
-  } else {
-    month -= 1;
-  }
+export const changeYearMonthAndClampDate = function(date, year, month) {
+  // clamp date to the number of days in `year`, `month`
+  // eg: (2010-1-31, 2010, 2) => 2010-2-28
   const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
   return modifyDate(date, year, month, monthDate);
 };
 
+export const prevMonth = function(date) {
+  const year = date.getFullYear();
+  const month = date.getMonth();
+  return month === 0
+    ? changeYearMonthAndClampDate(date, year - 1, 11)
+    : changeYearMonthAndClampDate(date, year, month - 1);
+};
+
 export const nextMonth = function(date) {
-  let year = date.getFullYear();
-  let month = date.getMonth();
-  if (month === 11) {
-    year += 1;
-    month = 0;
-  } else {
-    month += 1;
-  }
-  const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
-  return modifyDate(date, year, month, monthDate);
+  const year = date.getFullYear();
+  const month = date.getMonth();
+  return month === 11
+    ? changeYearMonthAndClampDate(date, year + 1, 0)
+    : changeYearMonthAndClampDate(date, year, month + 1);
 };
 
-// check for leap year Feburary
 export const prevYear = function(date, amount = 1) {
-  const year = date.getFullYear() - amount;
+  const year = date.getFullYear();
   const month = date.getMonth();
-  const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
-  return modifyDate(date, year, month, monthDate);
+  return changeYearMonthAndClampDate(date, year - amount, month);
 };
 
 export const nextYear = function(date, amount = 1) {
-  const year = date.getFullYear() + amount;
+  const year = date.getFullYear();
   const month = date.getMonth();
-  const monthDate = Math.min(date.getDate(), getDayCountOfMonth(year, month));
-  return modifyDate(date, year, month, monthDate);
+  return changeYearMonthAndClampDate(date, year + amount, month);
 };

+ 18 - 0
test/unit/specs/date-picker.spec.js

@@ -850,6 +850,24 @@ describe('DatePicker', () => {
         });
       });
     });
+
+    it('month label with fewer dates', done => {
+      navigationTest(new Date(2000, 6, 31), _ => {
+        const $el = vm.$refs.compo.picker.$el;
+        const monthLabel = $el.querySelectorAll('.el-date-picker__header-label')[1];
+        click(monthLabel, _ => {
+          setTimeout(_ => {
+            const juneLabel = $el.querySelectorAll('.el-month-table td a')[5];
+            juneLabel.click();
+            setTimeout(_ => {
+              expect(getYearLabel()).to.include('2000');
+              expect(getMonthLabel()).to.include('6');
+              done();
+            }, DELAY);
+          }, DELAY);
+        });
+      });
+    });
   });
 
   it('type:month', done => {