Commit e55ba7a2490fa2d2586da3f534c6a6d708d8162d

Authored by Sergio Crisostomo
1 parent ac231c9a

Add week numbers

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