Commit e55ba7a2490fa2d2586da3f534c6a6d708d8162d

Authored by Sergio Crisostomo
1 parent ac231c9a

Add week numbers

examples/routers/date.vue
... ... @@ -165,6 +165,8 @@
165 165 <br>
166 166 <Date-picker type="date" multiple style="width: 200px"></Date-picker> | Single date, multiple
167 167 <br>
  168 + <Date-picker type="date" multiple style="width: 200px" show-week-numbers></Date-picker> | Single date, multiple, show week numbers
  169 + <br>
168 170 <Date-picker type="date" format="yyyy-MM-dd HH:mm" placeholder="选择日期和时间(不含秒)" style="width: 200px"></Date-picker> | Single date, format MM-dd HH:mm
169 171 <br>
170 172 <Date-picker type="datetime" :start-date="minDate" v-model="singleDate" placeholder="选择日期和时间" style="width: 200px"></Date-picker> | Single datetime, date object, start date
... ...
src/components/date-picker/base/date-table.vue
... ... @@ -7,18 +7,19 @@
7 7 </div>
8 8 <span
9 9 :class="getCellCls(cell)"
10   - v-for="cell in readCells"
  10 + v-for="(cell, i) in readCells"
  11 + :key="String(cell.date) + i"
11 12 @click="handleClick(cell)"
12 13 @mouseenter="handleMouseMove(cell)"
13 14 >
14   - <em>{{ cell.text }}</em>
  15 + <em>{{ cell.desc }}</em>
15 16 </span>
16 17 </div>
17 18 </template>
18 19 <script>
19   - import { getFirstDayOfMonth, getDayCountOfMonth, clearHours, isInRange } from '../util';
20   - import { deepCopy } from '../../../utils/assist';
  20 + import { clearHours, isInRange } from '../util';
21 21 import Locale from '../../../mixins/locale';
  22 + import jsCalendar from 'js-calendar';
22 23  
23 24 import mixin from './mixin';
24 25 import prefixCls from './prefixCls';
... ... @@ -29,16 +30,25 @@
29 30  
30 31 props: {
31 32 /* more props in mixin */
  33 + showWeekNumbers: {
  34 + type: Boolean,
  35 + default: false
  36 + },
32 37 },
33 38 data () {
  39 + const weekStartDay = Number(this.t('i.datepicker.weekStartDay'));
34 40 return {
35 41 prefixCls: prefixCls,
  42 + calendar: new jsCalendar.Generator({onlyDays: !this.showWeekNumbers, weekStart: weekStartDay})
36 43 };
37 44 },
38 45 computed: {
39 46 classes () {
40 47 return [
41   - `${prefixCls}`
  48 + `${prefixCls}`,
  49 + {
  50 + [`${prefixCls}-show-week-numbers`]: this.showWeekNumbers
  51 + }
42 52 ];
43 53 },
44 54 headerDays () {
... ... @@ -47,76 +57,32 @@
47 57 return this.t('i.datepicker.weeks.' + item);
48 58 });
49 59 const weekDays = translatedDays.splice(weekStartDay, 7 - weekStartDay).concat(translatedDays.splice(0, weekStartDay));
50   - return weekDays;
  60 + return this.showWeekNumbers ? [''].concat(weekDays) : weekDays;
51 61 },
52 62 readCells () {
53 63 const tableYear = this.tableDate.getFullYear();
54 64 const tableMonth = this.tableDate.getMonth();
55   - const date = new Date(tableYear, tableMonth, 1);
56   - const weekStartDay = Number(this.t('i.datepicker.weekStartDay'));
57   - const day = (getFirstDayOfMonth(date) || 7) - weekStartDay; // day of first day
58 65 const today = clearHours(new Date()); // timestamp of today
59 66 const selectedDays = this.dates.filter(Boolean).map(clearHours); // timestamp of selected days
60 67 const [minDay, maxDay] = this.dates.map(clearHours);
61 68 const rangeStart = this.rangeState.from && clearHours(this.rangeState.from);
62 69 const rangeEnd = this.rangeState.to && clearHours(this.rangeState.to);
63 70  
64   - const dateCountOfMonth = getDayCountOfMonth(date.getFullYear(), date.getMonth());
65   - const dateCountOfLastMonth = getDayCountOfMonth(date.getFullYear(), (date.getMonth() === 0 ? 11 : date.getMonth() - 1));
66   -
67   - const disabledDate = this.disabledDate;
68   -
69   - let cells = [];
70   - const cell_tmpl = {
71   - text: '',
72   - type: '',
73   - date: null,
74   - selected: false,
75   - disabled: false,
76   - range: false,
77   - start: false,
78   - end: false
79   - };
80   - if (day !== 7) {
81   - for (let i = 0; i < day; i++) {
82   - const cell = deepCopy(cell_tmpl);
83   - cell.type = 'prev-month';
84   - cell.text = dateCountOfLastMonth - (day - 1) + i;
85   - cell.date = new Date(tableYear, tableMonth - 1, cell.text);
86   - const time = clearHours(cell.date);
87   - cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
88   - cells.push(cell);
89   - }
90   - }
91   -
92   - for (let i = 1; i <= dateCountOfMonth; i++) {
93   - const cell = deepCopy(cell_tmpl);
94   - cell.text = i;
95   - cell.date = new Date(tableYear, tableMonth, cell.text);
96   - const time = clearHours(cell.date);
97   - cell.type = time === today ? 'today' : 'normal';
98   - cell.selected = selectedDays.includes(time);
99   - cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
100   - if (this.selectionMode === 'range'){
101   - cell.range = isInRange(time, rangeStart, rangeEnd);
102   - cell.start = time === minDay;
103   - cell.end = time === maxDay;
104   - }
105   - cells.push(cell);
106   - }
107   -
108   - const nextMonthCount = 42 - cells.length;
109   - for (let i = 1; i <= nextMonthCount; i++) {
110   - const cell = deepCopy(cell_tmpl);
111   - cell.type = 'next-month';
112   - cell.text = i;
113   - cell.date = new Date(tableYear, tableMonth + 1, cell.text);
114   - const time = clearHours(cell.date);
115   - cell.disabled = typeof disabledDate === 'function' && disabledDate(new Date(time));
116   - cells.push(cell);
117   - }
  71 + const isRange = this.selectionMode === 'range';
  72 + const disabledTestFn = typeof this.disabledDate === 'function' && this.disabledDate;
118 73  
119   - return cells;
  74 + return this.calendar(tableYear, tableMonth, (cell) => {
  75 + const time = cell.date && clearHours(cell.date);
  76 + return {
  77 + ...cell,
  78 + type: time === today ? 'today' : cell.type,
  79 + selected: selectedDays.includes(time),
  80 + disabled: (cell.date && disabledTestFn) && disabledTestFn(new Date(time)),
  81 + range: isRange && isInRange(time, rangeStart, rangeEnd),
  82 + start: isRange && time === minDay,
  83 + end: isRange && time === maxDay
  84 + };
  85 + }).cells.slice(8);
120 86 }
121 87 },
122 88 methods: {
... ... @@ -127,8 +93,9 @@
127 93 [`${prefixCls}-cell-selected`]: cell.selected || cell.start || cell.end,
128 94 [`${prefixCls}-cell-disabled`]: cell.disabled,
129 95 [`${prefixCls}-cell-today`]: cell.type === 'today',
130   - [`${prefixCls}-cell-prev-month`]: cell.type === 'prev-month',
131   - [`${prefixCls}-cell-next-month`]: cell.type === 'next-month',
  96 + [`${prefixCls}-cell-prev-month`]: cell.type === 'prevMonth',
  97 + [`${prefixCls}-cell-next-month`]: cell.type === 'nextMonth',
  98 + [`${prefixCls}-cell-week-label`]: cell.type === 'weekLabel',
132 99 [`${prefixCls}-cell-range`]: cell.range && !cell.start && !cell.end
133 100 }
134 101 ];
... ...
src/components/date-picker/panel/Date/date-panel-mixin.js
... ... @@ -36,6 +36,10 @@ export default {
36 36 type: Array,
37 37 default: () => [initTimeDate(), initTimeDate()]
38 38 },
  39 + showWeekNumbers: {
  40 + type: Boolean,
  41 + default: false
  42 + },
39 43 startDate: {
40 44 type: Date
41 45 }
... ...
src/components/date-picker/panel/Date/date-range.vue
... ... @@ -38,6 +38,7 @@
38 38 selection-mode="range"
39 39 :disabled-date="disabledDate"
40 40 :range-state="rangeState"
  41 + :show-week-numbers="showWeekNumbers"
41 42 :value="dates"
42 43 @on-change-range="handleChangeRange"
43 44 @on-pick="handleRangePick"
... ... @@ -75,6 +76,7 @@
75 76 selection-mode="range"
76 77 :range-state="rangeState"
77 78 :disabled-date="disabledDate"
  79 + :show-week-numbers="showWeekNumbers"
78 80 :value="dates"
79 81 @on-change-range="handleChangeRange"
80 82 @on-pick="handleRangePick"
... ...
src/components/date-picker/panel/Date/date.vue
... ... @@ -33,6 +33,7 @@
33 33 ref="pickerTable"
34 34 v-if="currentView !== 'time'"
35 35 :table-date="panelDate"
  36 + :show-week-numbers="showWeekNumbers"
36 37 :value="dates"
37 38 :selection-mode="selectionMode"
38 39 :disabled-date="disabledDate"
... ...
src/components/date-picker/picker.vue
... ... @@ -17,7 +17,9 @@
17 17 @on-click="handleIconClick"
18 18 @mouseenter.native="handleInputMouseenter"
19 19 @mouseleave.native="handleInputMouseleave"
20   - :icon="iconType"></i-input>
  20 +
  21 + :icon="iconType"
  22 + ></i-input>
21 23 </slot>
22 24 </div>
23 25 <transition :name="transition">
... ... @@ -41,6 +43,7 @@
41 43 :value="internalValue"
42 44 :start-date="startDate"
43 45 :split-panels="splitPanels"
  46 + :show-week-numbers="showWeekNumbers"
44 47  
45 48 v-bind="ownPickerProps"
46 49  
... ... @@ -210,6 +213,10 @@
210 213 type: Boolean,
211 214 default: false
212 215 },
  216 + showWeekNumbers: {
  217 + type: Boolean,
  218 + default: false
  219 + },
213 220 startDate: {
214 221 type: Date
215 222 },
... ... @@ -423,8 +430,7 @@
423 430 onPickSuccess(){
424 431 this.visible = false;
425 432 this.$emit('on-ok');
426   - }
427   -
  433 + },
428 434 },
429 435 watch: {
430 436 visible (state) {
... ...
src/styles/components/date-picker.less
... ... @@ -2,6 +2,7 @@
2 2 @picker-prefix-cls: ~"@{css-prefix}picker";
3 3  
4 4 @date-picker-cells-width: 196px;
  5 +@date-picker-cells-width-with-weeknumbers: 226px;
5 6  
6 7 .@{date-picker-prefix-cls} {
7 8 //position: relative;
... ... @@ -64,15 +65,17 @@
64 65 }
65 66 }
66 67 }
67   - span&-disabled,span&-disabled:hover{
  68 + span&-week-label,span&-week-label:hover,span&-disabled,span&-disabled:hover{
68 69 cursor: @cursor-disabled;
69   - background: @btn-disable-bg;
70 70 color: @btn-disable-color;
71 71 em{
72 72 color: inherit;
73 73 background: inherit;
74 74 }
75 75 }
  76 + span&-disabled,span&-disabled:hover{
  77 + background: @btn-disable-bg;
  78 + }
76 79 &-today{
77 80 em {
78 81 position: relative;
... ... @@ -132,6 +135,10 @@
132 135 }
133 136 }
134 137  
  138 + &-cells-show-week-numbers {
  139 + width: @date-picker-cells-width-with-weeknumbers;
  140 + }
  141 +
135 142 &-cells-year,&-cells-month{
136 143 margin-top: 14px;
137 144 span{
... ... @@ -190,7 +197,12 @@
190 197 float: left;
191 198 }
192 199 }
  200 + .@{picker-prefix-cls}-cells-show-week-numbers {
  201 + min-width: (@date-picker-cells-width-with-weeknumbers + 20) * 2;
  202 + }
  203 +
193 204 }
  205 +
194 206 &-transfer{
195 207 z-index: @zindex-transfer;
196 208 max-height: none;
... ...