Browse Source

feat: [DatePicker] 新增label 快捷选择支持

zhangyuhan 11 months ago
parent
commit
248e48b28a
6 changed files with 187 additions and 20 deletions
  1. 20 6
      README.md
  2. 1 1
      examples/versions.json
  3. 154 11
      packages/date-picker/src/panel/date-range.vue
  4. 5 0
      packages/date-picker/src/picker.vue
  5. 1 1
      src/index.js
  6. 6 1
      yarn.lock

+ 20 - 6
README.md

@@ -36,12 +36,26 @@
   </a>
 </p>
 
-> @2.15.9-rc 剑鱼内网版本 element-ui
-Q:有什么不同?
-A: 因为当前2.x版本已经不是主要维护版本,pr的响应和合并不可预知,因此采用内网版本。
-  1. node-sass 替换为 sass
-  2. shadow dom scrollTop等属性获取兼容
-  2. popover、date-picker 系列组件的 shadow dom 事件兼容
+> @2.15.17-rc 剑鱼内网版本 element-ui
+
+> Q:有什么不同?
+
+> A: 因为当前2.x版本已经不是主要维护版本,pr的响应和合并不可预知,因此采用内网版本。
+
+
+> 内网版本变更记录:
+
+> v.2.15.18-rc
+1. 2.15.9 -> 2.15.14 pr bug 合并
+2. 支持 date-picker daterange 范围选择中`年、月`标签快捷选择年月,新增 props `range-label-click` 控制,默认启用。
+
+
+> v.2.15.16-rc
+1. node-sass 替换为 sass
+2. shadow dom scrollTop等属性获取兼容
+3. popover、date-picker 系列组件的 shadow dom 事件兼容
+4. 分页样式定制
+
 > A Vue.js 2.0 UI Toolkit for Web.
 
 Element will stay with Vue 2.x

+ 1 - 1
examples/versions.json

@@ -1 +1 @@
-{"1.4.13":"1.4","2.0.11":"2.0","2.1.0":"2.1","2.2.2":"2.2","2.3.9":"2.3","2.4.11":"2.4","2.5.4":"2.5","2.6.3":"2.6","2.7.2":"2.7","2.8.2":"2.8","2.9.2":"2.9","2.10.1":"2.10","2.11.1":"2.11","2.12.0":"2.12","2.13.2":"2.13","2.14.1":"2.14","2.15.15-rc":"2.15"}
+{"1.4.13":"1.4","2.0.11":"2.0","2.1.0":"2.1","2.2.2":"2.2","2.3.9":"2.3","2.4.11":"2.4","2.5.4":"2.5","2.6.3":"2.6","2.7.2":"2.7","2.8.2":"2.8","2.9.2":"2.9","2.10.1":"2.10","2.11.1":"2.11","2.12.0":"2.12","2.13.2":"2.13","2.14.1":"2.14","2.15.18-rc":"2.15"}

+ 154 - 11
packages/date-picker/src/panel/date-range.vue

@@ -91,6 +91,7 @@
                 @click="leftPrevYear"
                 class="el-picker-panel__icon-btn el-icon-d-arrow-left"></button>
               <button
+                v-show="canShowLeftDatePanel"
                 type="button"
                 @click="leftPrevMonth"
                 class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
@@ -104,13 +105,26 @@
               <button
                 type="button"
                 @click="leftNextMonth"
-                v-if="unlinkPanels"
+                v-if="unlinkPanels && canShowLeftDatePanel"
                 :disabled="!enableMonthArrow"
                 :class="{ 'is-disabled': !enableMonthArrow }"
                 class="el-picker-panel__icon-btn el-icon-arrow-right"></button>
-              <div>{{ leftLabel }}</div>
+              <div v-if="!rangeLabelClick">{{ leftLabel }}</div>
+              <div v-else>
+                <span
+                  @click="showYearPicker('left')"
+                  role="button"
+                  class="el-date-picker__header-label">{{ leftYearLabel }}</span>
+                <span
+                    @click="showMonthPicker('left')"
+                    v-show="canShowLeftDatePanel"
+                    role="button"
+                    class="el-date-picker__header-label"
+                    :class="{ active: currentView === 'left-month' }">{{t(`el.datepicker.month${ leftMonth + 1 }`)}}</span>
+              </div>
             </div>
             <date-table
+              v-show="canShowLeftDatePanel"
               selection-mode="range"
               :date="leftDate"
               :default-value="defaultValue"
@@ -123,6 +137,22 @@
               :first-day-of-week="firstDayOfWeek"
               @pick="handleRangePick">
             </date-table>
+            <year-table
+                v-show="currentView === 'left-year'"
+                @pick="handleYearPick($event, 'left')"
+                :selection-mode="selectionMode"
+                :default-value="defaultValue ? new Date(defaultValue) : null"
+                :date="leftDate"
+                :disabled-date="disabledDate">
+            </year-table>
+            <month-table
+                v-show="currentView === 'left-month'"
+                @pick="handleMonthPick($event, 'left')"
+                :selection-mode="selectionMode"
+                :default-value="defaultValue ? new Date(defaultValue) : null"
+                :date="leftDate"
+                :disabled-date="disabledDate">
+            </month-table>
           </div>
           <div class="el-picker-panel__content el-date-range-picker__content is-right">
             <div class="el-date-range-picker__header">
@@ -136,7 +166,7 @@
               <button
                 type="button"
                 @click="rightPrevMonth"
-                v-if="unlinkPanels"
+                v-if="unlinkPanels && canShowRightDatePanel"
                 :disabled="!enableMonthArrow"
                 :class="{ 'is-disabled': !enableMonthArrow }"
                 class="el-picker-panel__icon-btn el-icon-arrow-left"></button>
@@ -145,12 +175,26 @@
                 @click="rightNextYear"
                 class="el-picker-panel__icon-btn el-icon-d-arrow-right"></button>
               <button
+                v-show="canShowRightDatePanel"
                 type="button"
                 @click="rightNextMonth"
                 class="el-picker-panel__icon-btn el-icon-arrow-right"></button>
-              <div>{{ rightLabel }}</div>
+              <div v-if="!rangeLabelClick">{{ rightLabel }}</div>
+              <div v-else>
+                <span
+                    @click="showYearPicker('right')"
+                    role="button"
+                    class="el-date-picker__header-label">{{ rightYearLabel }}</span>
+                <span
+                    @click="showMonthPicker('right')"
+                    v-show="canShowRightDatePanel"
+                    role="button"
+                    class="el-date-picker__header-label"
+                    :class="{ active: currentView === 'right-month' }">{{t(`el.datepicker.month${ rightMonth + 1 }`)}}</span>
+              </div>
             </div>
             <date-table
+              v-show="canShowRightDatePanel"
               selection-mode="range"
               :date="rightDate"
               :default-value="defaultValue"
@@ -163,6 +207,22 @@
               :first-day-of-week="firstDayOfWeek"
               @pick="handleRangePick">
             </date-table>
+            <year-table
+                v-show="currentView === 'right-year'"
+                @pick="handleYearPick($event, 'right')"
+                :selection-mode="selectionMode"
+                :default-value="defaultValue ? new Date(defaultValue) : null"
+                :date="rightDate"
+                :disabled-date="disabledDate">
+            </year-table>
+            <month-table
+                v-show="currentView === 'right-month'"
+                @pick="handleMonthPick($event, 'right')"
+                :selection-mode="selectionMode"
+                :default-value="defaultValue ? new Date(defaultValue) : null"
+                :date="rightDate"
+                :disabled-date="disabledDate">
+            </month-table>
           </div>
         </div>
       </div>
@@ -200,12 +260,15 @@
     prevMonth,
     nextMonth,
     nextDate,
+    changeYearMonthAndClampDate,
     extractDateFormat,
     extractTimeFormat
   } from 'element-ui/src/utils/date-util';
   import Clickoutside from 'element-ui/src/utils/clickoutside';
   import Locale from 'element-ui/src/mixins/locale';
   import TimePicker from './time';
+  import YearTable from '../basic/year-table';
+  import MonthTable from '../basic/month-table';
   import DateTable from '../basic/date-table';
   import ElInput from 'element-ui/packages/input';
   import ElButton from 'element-ui/packages/button';
@@ -250,6 +313,26 @@
         return this.leftDate.getDate();
       },
 
+      leftYearLabel() {
+        return this.computedYearLabel(this.leftYear, !this.canShowLeftDatePanel && this.canShowYearPanel);
+      },
+
+      canShowLeftDatePanel() {
+        return this.currentView.indexOf('left') === -1;
+      },
+
+      canShowRightDatePanel() {
+        return this.currentView.indexOf('right') === -1;
+      },
+
+      canShowYearPanel() {
+        return this.currentView.indexOf('year') !== -1;
+      },
+
+      yearStep() {
+        return this.canShowYearPanel ? 10 : 1;
+      },
+
       rightYear() {
         return this.rightDate.getFullYear();
       },
@@ -262,6 +345,10 @@
         return this.rightDate.getDate();
       },
 
+      rightYearLabel() {
+        return this.computedYearLabel(this.rightYear, !this.canShowRightDatePanel && this.canShowYearPanel);
+      },
+
       minVisibleDate() {
         if (this.dateUserInput.min !== null) return this.dateUserInput.min;
         if (this.minDate) return formatDate(this.minDate, this.dateFormat);
@@ -340,6 +427,7 @@
         format: '',
         arrowControl: false,
         unlinkPanels: false,
+        rangeLabelClick: true,
         dateUserInput: {
           min: null,
           max: null
@@ -347,7 +435,9 @@
         timeUserInput: {
           min: null,
           max: null
-        }
+        },
+        currentView: 'date',
+        selectionMode: 'day'
       };
     },
 
@@ -440,6 +530,18 @@
     },
 
     methods: {
+      computedYearLabel(year, showYear = false) {
+        const yearTranslation = this.t('el.datepicker.year');
+        if (showYear) {
+          const startYear = Math.floor(year / 10) * 10;
+          if (yearTranslation) {
+            return startYear + ' ' + yearTranslation + ' - ' + (startYear + 9) + ' ' + yearTranslation;
+          }
+          return startYear + ' - ' + (startYear + 9);
+        }
+        return year + ' ' + yearTranslation;
+      },
+
       handleClear() {
         this.minDate = null;
         this.maxDate = null;
@@ -555,6 +657,38 @@
         this.handleConfirm();
       },
 
+      handleYearPick(year, direction) {
+        const pointVal = direction === 'left' ? 'leftDate' : 'rightDate';
+        const pointMonthVal = direction === 'left' ? this.leftMonth : this.rightMonth;
+        if (this.selectionMode === 'year') {
+          this[pointVal] = modifyDate(this[pointVal], year, 0, 1);
+          this.emit(this[pointVal]);
+        } else if (this.selectionMode === 'years') {
+          this.emit(year, true);
+        } else {
+          this[pointVal] = changeYearMonthAndClampDate(this[pointVal], year, pointMonthVal);
+          // TODO: should emit intermediate value ??
+          // this.emit(this.date, true);
+          this.currentView = 'month';
+        }
+      },
+
+      handleMonthPick(month, direction) {
+        const pointVal = direction === 'left' ? 'leftDate' : 'rightDate';
+        const pointYearVal = direction === 'left' ? this.leftYear : this.rightYear;
+        if (this.selectionMode === 'month') {
+          this[pointVal] = modifyDate(this[pointVal], pointYearVal, month, 1);
+          this.emit(this[pointVal]);
+        } else if (this.selectionMode === 'months') {
+          this.emit(month, true);
+        } else {
+          this[pointVal] = changeYearMonthAndClampDate(this[pointVal], pointYearVal, month);
+          // TODO: should emit intermediate value ??
+          // this.emit(this.date);
+          this.currentView = 'date';
+        }
+      },
+
       handleShortcutClick(shortcut) {
         if (shortcut.onClick) {
           shortcut.onClick(this);
@@ -600,7 +734,7 @@
 
       // leftPrev*, rightNext* need to take care of `unlinkPanels`
       leftPrevYear() {
-        this.leftDate = prevYear(this.leftDate);
+        this.leftDate = prevYear(this.leftDate, this.yearStep);
         if (!this.unlinkPanels) {
           this.rightDate = nextMonth(this.leftDate);
         }
@@ -615,10 +749,10 @@
 
       rightNextYear() {
         if (!this.unlinkPanels) {
-          this.leftDate = nextYear(this.leftDate);
+          this.leftDate = nextYear(this.leftDate, this.yearStep);
           this.rightDate = nextMonth(this.leftDate);
         } else {
-          this.rightDate = nextYear(this.rightDate);
+          this.rightDate = nextYear(this.rightDate, this.yearStep);
         }
       },
 
@@ -633,7 +767,7 @@
 
       // leftNext*, rightPrev* are called when `unlinkPanels` is true
       leftNextYear() {
-        this.leftDate = nextYear(this.leftDate);
+        this.leftDate = nextYear(this.leftDate, this.yearStep);
       },
 
       leftNextMonth() {
@@ -641,7 +775,7 @@
       },
 
       rightPrevYear() {
-        this.rightDate = prevYear(this.rightDate);
+        this.rightDate = prevYear(this.rightDate, this.yearStep);
       },
 
       rightPrevMonth() {
@@ -672,9 +806,18 @@
         if (this.minDate && this.maxDate == null) this.rangeState.selecting = false;
         this.minDate = this.value && isDate(this.value[0]) ? new Date(this.value[0]) : null;
         this.maxDate = this.value && isDate(this.value[0]) ? new Date(this.value[1]) : null;
+        this.currentView = 'date';
+      },
+
+      showMonthPicker(direction) {
+        this.currentView = direction + '-month';
+      },
+
+      showYearPicker(direction) {
+        this.currentView = direction + '-year';
       }
     },
 
-    components: { TimePicker, DateTable, ElInput, ElButton }
+    components: { TimePicker, YearTable, MonthTable, DateTable, ElInput, ElButton }
   };
 </script>

+ 5 - 0
packages/date-picker/src/picker.vue

@@ -408,6 +408,10 @@ export default {
     },
     pickerOptions: {},
     unlinkPanels: Boolean,
+    rangeLabelClick: {
+      type: Boolean,
+      default: true
+    },
     validateEvent: {
       type: Boolean,
       default: true
@@ -857,6 +861,7 @@ export default {
       this.picker.showTime = this.type === 'datetime' || this.type === 'datetimerange';
       this.picker.selectionMode = this.selectionMode;
       this.picker.unlinkPanels = this.unlinkPanels;
+      this.picker.rangeLabelClick = this.rangeLabelClick;
       this.picker.arrowControl = this.arrowControl || this.timeArrowControl || false;
       this.$watch('format', (format) => {
         this.picker.format = format;

+ 1 - 1
src/index.js

@@ -210,7 +210,7 @@ if (typeof window !== 'undefined' && window.Vue) {
 }
 
 export default {
-  version: '2.15.15-rc',
+  version: '2.15.18-rc',
   locale: locale.use,
   i18n: locale.i18n,
   install,

+ 6 - 1
yarn.lock

@@ -4111,7 +4111,7 @@ fs.realpath@^1.0.0:
   resolved "http://192.168.3.42:4873/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
   integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
 
-fsevents@^1.0.0, fsevents@^1.2.7, fsevents@^1.2.9, fsevents@~2.3.2:
+fsevents@^1.0.0, fsevents@^1.2.7:
   version "1.2.13"
   resolved "http://192.168.3.42:4873/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38"
   integrity sha1-8yXLBFVZJCi88Rs4M3DvcOO/zDg=
@@ -4119,6 +4119,11 @@ fsevents@^1.0.0, fsevents@^1.2.7, fsevents@^1.2.9, fsevents@~2.3.2:
     bindings "^1.5.0"
     nan "^2.12.1"
 
+fsevents@~2.3.2:
+  version "2.3.3"
+  resolved "http://192.168.3.71:4873/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+  integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
 function-bind@^1.1.1:
   version "1.1.1"
   resolved "http://192.168.3.42:4873/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"