├── screenshots
└── datepicker.png
├── demo.html
├── README.md
├── dist
├── vue.datepicker.min.css
└── vue.datepicker.min.js
└── src
├── vue.datepicker.css
└── vue.datepicker.js
/screenshots/datepicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weifeiyue/vue-datepicker/HEAD/screenshots/datepicker.png
--------------------------------------------------------------------------------
/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | StartTime:{{startTime}}
11 | EndTime:{{endTime}}
12 | Time:{{time}}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
35 |
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | vue-datepicker
2 | ========
3 | ### A Beautiful Datepicker Component For Vue
4 | * Lightweight (less than 5kb minified and gzipped)
5 | * Only dependencies Vue
6 | * Beautiful!
7 |
8 | for vue2:
9 | [https://github.com/weifeiyue/vue-datepicker-local](https://github.com/weifeiyue/vue-datepicker-local)
10 |
11 | 
12 |
13 | ## Usage
14 |
15 | ```html
16 |
17 | ```
18 |
19 | ```html
20 |
21 | ```
22 |
23 | ```html
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | ```
54 |
--------------------------------------------------------------------------------
/dist/vue.datepicker.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-datepicker v0.1.2
3 | * https://github.com/weifeiyue/vue-datepicker
4 | * (c) 2016 weifeiyue
5 | * Released under the MIT License.
6 | */
7 | .mz-datepicker{display:inline-block;vertical-align:middle;position:relative;font-family:Microsoft YaHei,serif}.mz-datepicker>input{font-family:Microsoft YaHei,serif;color:#666;border:1px solid #d9d9d9;height:30px;box-sizing:border-box;outline:0;padding:0 30px 0 7px;font-size:13px;width:100%;cursor:pointer}.mz-datepicker>input:disabled{cursor:not-allowed;background-color:#ebebe4}.mz-datepicker>input.focus,.mz-datepicker>input:focus{border-color:#3bb4f2;box-shadow:0 0 5px rgba(59,180,242,.3)}.mz-datepicker>i{display:inline-block;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAB9JREFUCNdjEBSAov//GSYKMjQwAhlAEoTaHyIzIFIAFm0NVxDW3twAAAAASUVORK5CYII=') no-repeat 50% 50%}.mz-datepicker>a,.mz-datepicker>i{position:absolute;width:30px;height:30px;top:0;right:0}.mz-datepicker>a{display:none;cursor:pointer;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARBAMAAADJQ1rJAAAAMFBMVEUAAACZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmy/KNBAAAAD3RSTlMAeQfv0sgfSr2XgBXh4Em9LfYxAAAAdElEQVQI12NgYGAqXFgEpIAM4f//PwuBWFv/A8HXDUCh+P8gEMTAwPjf9v//P/YfGRiU/7v5A9FnBYb6/z9SvmT8/1/AIP//f9g0oFoBhvX////kBGpZgBBDqEPoBZpn8///X6B5CDsQ9iLcAmI+XPgISAEABvtVL6xNmm0AAAAASUVORK5CYII=') no-repeat 50% 50%}.mz-datepicker>a:hover{opacity:.8}.mz-datepicker:hover>a{display:block}.mz-datepicker:hover>a+i{display:none}.mz-datepicker-popup{font-size:9pt;position:absolute;top:100%;margin-top:1px;border:1px solid #d9d9d9;box-shadow:0 1px 6px rgba(99,99,99,.2);padding:8px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:#fff;outline:0;z-index:1}.mz-datepicker-popup-left{right:0}.mz-datepicker-popup-transition{transition:all .2s ease;opacity:1;transform:scaleY(1);transform-origin:center top}.mz-datepicker-popup-enter,.mz-datepicker-popup-leave{opacity:0;transform:scaleY(0)}.mz-calendar{width:196px;display:inline-block;vertical-align:middle;position:relative}.mz-calendar-header{text-align:center;color:#999;position:relative;line-height:34px}.mz-calendar-header a{cursor:pointer}.mz-calendar-header a:hover{color:#1284e7}.mz-calendar-next-month,.mz-calendar-next-year,.mz-calendar-prev-month,.mz-calendar-prev-year{position:absolute;font-size:1pc}.mz-calendar-prev-year{left:4px}.mz-calendar-prev-month{left:24px}.mz-calendar-next-month{right:24px}.mz-calendar-next-year{right:4px}.mz-calendar-month-select,.mz-calendar-year-select{font-weight:700;color:#666;padding:0 2px}.mz-calendar td,.mz-calendar th{width:28px;height:28px;text-align:center;box-sizing:border-box}.mz-calendar th{font-weight:400}.mz-calendar td{cursor:pointer}.mz-calendar td:hover,.mz-calendar-inrange{background:#eaf8fe}.mz-calendar-lastmonth,.mz-calendar-nextmonth{color:#ccc}.mz-calendar-today{border:1px solid #1284e7;font-weight:700;color:#1284e7}.mz-calendar-selected{color:#fff;font-weight:700;background:#1284e7!important}.mz-calendar-disabled{cursor:not-allowed!important;color:#bcbcbc!important;background:#f3f3f3!important}.mz-calendar-top{color:#616161;padding-bottom:8px;margin-bottom:8px;border-bottom:1px solid #f3f3f3}.mz-calendar-top a{display:inline-block;vertical-align:middle;height:1pc;cursor:pointer}.mz-calendar-top a:hover{color:#77bdfb}.mz-calendar-top a.on{font-weight:700;color:#1284e7}.mz-calendar-top i{content:'|';display:inline-block;width:1px;margin:0 10px;height:1pc;background:#616161;vertical-align:middle}.mz-calendar-bottom{margin-top:8px;padding-top:8px;border-top:1px solid #f3f3f3;text-align:right}.mz-calendar-btn{display:inline-block;height:22px;text-align:center;vertical-align:middle;cursor:pointer;border-radius:2px;-webkit-transition:all .3s ease;transition:all .3s ease;padding:0 10px;line-height:22px;color:#1284e7;margin-left:5px}.mz-calendar-btn:hover{color:#60b3fb}.mz-calendar-btn:active{color:#006cca}.mz-calendar-btn.ok{background:#1284e7;color:#fff}.mz-calendar-btn.ok:hover{background:#60b3fb}.mz-calendar-btn.ok:active{background:#006cca}.mz-calendar-range{width:423px}.mz-calendar-separator{display:inline-block;vertical-align:middle;width:31px;position:relative}.mz-calendar-separator:before{content:"";position:absolute;width:1px;height:180px;background:#e0e0e0;left:50%;top:50%;margin-top:-90px}.mz-calendar-separator span{position:absolute;width:100%;text-align:center;height:30px;line-height:30px;background:#fff;top:50%;margin-top:-15px}.mz-calendar-year-panel{position:absolute;left:0;top:34px;width:100%;height:196px;background:#fff}.mz-calendar-year-panel-next,.mz-calendar-year-panel-prev,.mz-calendar-year-panel-year{display:inline-block;text-align:center;width:50%;height:2pc;line-height:2pc;vertical-align:middle;box-sizing:border-box}.mz-calendar-year-panel-next,.mz-calendar-year-panel-prev{width:100%;height:18px;position:relative;display:block}.mz-calendar-year-panel-next:before,.mz-calendar-year-panel-prev:before{content:'';display:inline-block;width:0;height:0;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;left:50%;top:50%;margin-left:-3px;margin-top:-3px}.mz-calendar-year-panel-prev:before{border-bottom:5px solid #999}.mz-calendar-year-panel-next:before{border-top:5px solid #999}.mz-calendar-month-panel-month:hover,.mz-calendar-year-panel-next:hover,.mz-calendar-year-panel-prev:hover,.mz-calendar-year-panel-year:hover{background:#eaf8fe;cursor:pointer}.mz-calendar-month-panel{position:absolute;left:0;top:34px;width:100%;height:196px;background:#fff}.mz-calendar-month-panel-month{display:inline-block;text-align:center;width:33.33%;height:25%;line-height:49px;vertical-align:middle;box-sizing:border-box}.mz-calendar-panel-transition{transition:all .2s ease;opacity:1;transform:scale(1);transform-origin:center center}.mz-calendar-panel-enter,.mz-calendar-panel-leave{opacity:0;transform:scale(0)}
--------------------------------------------------------------------------------
/src/vue.datepicker.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-datepicker v0.1.2
3 | * https://github.com/weifeiyue/vue-datepicker
4 | * (c) 2016 weifeiyue
5 | * Released under the MIT License.
6 | */
7 | .mz-datepicker {
8 | display: inline-block;
9 | vertical-align: middle;
10 | position: relative;
11 | font-family: 'Microsoft YaHei', serif;
12 | }
13 | .mz-datepicker > input {
14 | font-family: 'Microsoft YaHei', serif;
15 | color: #666;
16 | border: 1px solid #d9d9d9;
17 | height: 30px;
18 | box-sizing: border-box;
19 | outline: none;
20 | padding: 0 30px 0 7px;
21 | font-size: 13px;
22 | width: 100%;
23 | cursor: pointer;
24 | }
25 | .mz-datepicker > input:disabled {
26 | cursor: not-allowed;
27 | background-color: #ebebe4;
28 | }
29 | .mz-datepicker > input:focus, .mz-datepicker > input.focus {
30 | border-color: #3bb4f2;
31 | -webkit-box-shadow: 0 0 5px rgba(59, 180, 242, .3);
32 | box-shadow: 0 0 5px rgba(59, 180, 242, .3);
33 | }
34 | .mz-datepicker > i {
35 | display: inline-block;
36 | position: absolute;
37 | width: 30px;
38 | height: 30px;
39 | top: 0;
40 | right: 0;
41 | background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAACZmZl+9SADAAAAAXRSTlMAQObYZgAAAB9JREFUCNdjEBSAov//GSYKMjQwAhlAEoTaHyIzIFIAFm0NVxDW3twAAAAASUVORK5CYII=') no-repeat 50% 50%;
42 | }
43 | .mz-datepicker > a {
44 | display: none;
45 | position: absolute;
46 | width: 30px;
47 | height: 30px;
48 | top: 0;
49 | right: 0;
50 | cursor: pointer;
51 | background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARBAMAAADJQ1rJAAAAMFBMVEUAAACZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmy/KNBAAAAD3RSTlMAeQfv0sgfSr2XgBXh4Em9LfYxAAAAdElEQVQI12NgYGAqXFgEpIAM4f//PwuBWFv/A8HXDUCh+P8gEMTAwPjf9v//P/YfGRiU/7v5A9FnBYb6/z9SvmT8/1/AIP//f9g0oFoBhvX////kBGpZgBBDqEPoBZpn8///X6B5CDsQ9iLcAmI+XPgISAEABvtVL6xNmm0AAAAASUVORK5CYII=') no-repeat 50% 50%;
52 | }
53 | .mz-datepicker > a:hover {
54 | opacity: 0.8;
55 | }
56 | .mz-datepicker:hover > a {
57 | display: block;
58 | }
59 | .mz-datepicker:hover > a + i {
60 | display: none;
61 | }
62 | .mz-datepicker-popup {
63 | font-size: 12px;
64 | position: absolute;
65 | top: 100%;
66 | margin-top: 1px;
67 | border: 1px solid #d9d9d9;
68 | box-shadow: 0 1px 6px rgba(99, 99, 99, 0.2);
69 | padding: 8px;
70 | -webkit-user-select: none;
71 | -moz-user-select: none;
72 | -ms-user-select: none;
73 | user-select: none;
74 | background: #fff;
75 | outline: none;
76 | z-index: 1;
77 | }
78 | .mz-datepicker-popup-left{
79 | right: 0;
80 | }
81 | .mz-datepicker-popup-transition {
82 | transition: all 200ms ease;
83 | opacity: 1;
84 | transform: scaleY(1);
85 | transform-origin: center top;
86 | }
87 | .mz-datepicker-popup-enter, .mz-datepicker-popup-leave {
88 | opacity: 0;
89 | transform: scaleY(0)
90 | }
91 | .mz-calendar {
92 | width: 196px;
93 | display: inline-block;
94 | vertical-align: middle;
95 | position: relative;
96 | }
97 | .mz-calendar-header {
98 | text-align: center;
99 | color: #999;
100 | position: relative;
101 | line-height: 34px;
102 | }
103 | .mz-calendar-header a {
104 | cursor: pointer;
105 | }
106 | .mz-calendar-header a:hover {
107 | color: #1284e7;
108 | }
109 | .mz-calendar-prev-year, .mz-calendar-prev-month, .mz-calendar-next-month, .mz-calendar-next-year {
110 | position: absolute;
111 | font-size: 16px;
112 | }
113 | .mz-calendar-prev-year {
114 | left: 4px;
115 | }
116 | .mz-calendar-prev-month {
117 | left: 24px;
118 | }
119 | .mz-calendar-next-month {
120 | right: 24px;
121 | }
122 | .mz-calendar-next-year {
123 | right: 4px;
124 | }
125 | .mz-calendar-year-select, .mz-calendar-month-select {
126 | font-weight: 700;
127 | color: #666;
128 | padding: 0 2px;
129 | }
130 | .mz-calendar-footer {}
131 | .mz-calendar th, .mz-calendar td {
132 | width: 28px;
133 | height: 28px;
134 | text-align: center;
135 | box-sizing: border-box;
136 | }
137 | .mz-calendar th {
138 | font-weight: normal;
139 | }
140 | .mz-calendar td {
141 | cursor: pointer;
142 | }
143 | .mz-calendar td:hover, .mz-calendar-inrange {
144 | background: #eaf8fe;
145 | }
146 | .mz-calendar-lastmonth, .mz-calendar-nextmonth {
147 | color: #ccc;
148 | }
149 | .mz-calendar-today {
150 | border: solid 1px #1284e7;
151 | font-weight: bold;
152 | color: #1284e7;
153 | }
154 | .mz-calendar-selected {
155 | color: #fff;
156 | font-weight: bold;
157 | background: #1284e7 !important;
158 | }
159 | .mz-calendar-disabled {
160 | cursor: not-allowed !important;
161 | color: #bcbcbc !important;
162 | background: #f3f3f3 !important;
163 | }
164 | .mz-calendar-top {
165 | color: #616161;
166 | padding-bottom: 8px;
167 | margin-bottom: 8px;
168 | border-bottom: 1px solid #f3f3f3;
169 | }
170 | .mz-calendar-top a {
171 | display: inline-block;
172 | vertical-align: middle;
173 | height: 16px;
174 | cursor: pointer;
175 | }
176 | .mz-calendar-top a:hover {
177 | color: #77BDFB;
178 | }
179 | .mz-calendar-top a.on {
180 | font-weight: bold;
181 | color: #1284e7;
182 | }
183 | .mz-calendar-top i {
184 | content: '|';
185 | display: inline-block;
186 | width: 1px;
187 | margin: 0 10px;
188 | height: 16px;
189 | background: #616161;
190 | vertical-align: middle;
191 | }
192 | .mz-calendar-bottom {
193 | margin-top: 8px;
194 | padding-top: 8px;
195 | border-top: 1px solid #f3f3f3;
196 | text-align: right;
197 | }
198 | .mz-calendar-btn {
199 | display: inline-block;
200 | height: 22px;
201 | text-align: center;
202 | vertical-align: middle;
203 | cursor: pointer;
204 | border-radius: 2px;
205 | -webkit-transition: all .3s ease;
206 | transition: all .3s ease;
207 | padding: 0 10px;
208 | line-height: 22px;
209 | color: #1284e7;
210 | margin-left: 5px;
211 | }
212 | .mz-calendar-btn:hover {
213 | color: #60B3FB;
214 | }
215 | .mz-calendar-btn:active {
216 | color: #006CCA;
217 | }
218 | .mz-calendar-btn.ok {
219 | background: #1284e7;
220 | color: #fff;
221 | }
222 | .mz-calendar-btn.ok:hover {
223 | background: #60B3FB;
224 | }
225 | .mz-calendar-btn.ok:active {
226 | background: #006CCA;
227 | }
228 | .mz-calendar-range {
229 | width: 423px;
230 | }
231 | .mz-calendar-separator {
232 | display: inline-block;
233 | vertical-align: middle;
234 | width: 31px;
235 | position: relative;
236 | }
237 | .mz-calendar-separator::before {
238 | content: "";
239 | position: absolute;
240 | width: 1px;
241 | height: 180px;
242 | background: #e0e0e0;
243 | left: 50%;
244 | top: 50%;
245 | margin-top: -90px;
246 | }
247 | .mz-calendar-separator span {
248 | position: absolute;
249 | width: 100%;
250 | text-align: center;
251 | height: 30px;
252 | line-height: 30px;
253 | background: #fff;
254 | top: 50%;
255 | margin-top: -15px;
256 | }
257 | .mz-calendar-year-panel {
258 | position: absolute;
259 | left: 0;
260 | top: 34px;
261 | width: 100%;
262 | height: 196px;
263 | background: #fff;
264 | }
265 | .mz-calendar-year-panel-year, .mz-calendar-year-panel-prev,.mz-calendar-year-panel-next {
266 | display: inline-block;
267 | text-align: center;
268 | width: 50%;
269 | height: 32px;
270 | line-height: 32px;
271 | vertical-align: middle;
272 | box-sizing: border-box;
273 | }
274 | .mz-calendar-year-panel-prev, .mz-calendar-year-panel-next {
275 | width: 100%;
276 | height: 18px;
277 | position: relative;
278 | display: block;
279 | }
280 | .mz-calendar-year-panel-prev::before,.mz-calendar-year-panel-next::before{
281 | content: '';
282 | display: inline-block;
283 | width: 0;
284 | height: 0;
285 | border-left: 5px solid transparent;
286 | border-right: 5px solid transparent;
287 | position: absolute;
288 | left: 50%;
289 | top: 50%;
290 | margin-left: -3px;
291 | margin-top: -3px;
292 | }
293 | .mz-calendar-year-panel-prev::before{
294 | border-bottom: 5px solid #999;
295 | }
296 | .mz-calendar-year-panel-next::before{
297 | border-top: 5px solid #999;
298 | }
299 | .mz-calendar-year-panel-year:hover,.mz-calendar-month-panel-month:hover, .mz-calendar-year-panel-prev:hover,.mz-calendar-year-panel-next:hover {
300 | background: #eaf8fe;
301 | cursor: pointer;
302 | }
303 | .mz-calendar-month-panel {
304 | position: absolute;
305 | left: 0;
306 | top: 34px;
307 | width: 100%;
308 | height: 196px;
309 | background: #fff;
310 | }
311 | .mz-calendar-month-panel-month {
312 | display: inline-block;
313 | text-align: center;
314 | width: 33.33%;
315 | height: 25%;
316 | line-height: 49px;
317 | vertical-align: middle;
318 | box-sizing: border-box;
319 | }
320 | .mz-calendar-panel-transition {
321 | transition: all 200ms ease;
322 | opacity: 1;
323 | transform: scale(1);
324 | transform-origin: center center;
325 | }
326 | .mz-calendar-panel-enter, .mz-calendar-panel-leave {
327 | opacity: 0;
328 | transform: scale(0)
329 | }
--------------------------------------------------------------------------------
/dist/vue.datepicker.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-datepicker v0.1.2
3 | * https://github.com/weifeiyue/vue-datepicker
4 | * (c) 2016 weifeiyue
5 | * Released under the MIT License.
6 | */
7 | !function(a){"use strict";"function"==typeof define&&define.amd?define(["vue"],a):"object"==typeof exports?a(require("vue")):a(Vue)}(function(a){a.component("mz-datepicker",{template:'',props:{range:{type:Boolean,"default":!1},width:{"default":214},time:{twoWay:!0},startTime:{twoWay:!0},endTime:{twoWay:!0},maxRange:{coerce:function(a){return+a}},clearable:{type:Boolean,"default":!1},format:{type:String,"default":"yyyy-MM-dd"},disabled:{type:Boolean,"default":!1},confirm:{type:Boolean,"default":!1},en:{type:Boolean,"default":!1},onConfirm:Function},data:function(){return{show:!1,showYear1:!1,showYear2:!1,showMonth1:!1,showMonth2:!1,prevYearTitle:this.en?"last year":"上一年",prevMonthTitle:this.en?"last month":"上个月",selectYearTitle:this.en?"select year":"选择年份",selectMonthTitle:this.en?"select month":"选择月份",nextMonthTitle:this.en?"next month":"下个月",nextYearTitle:this.en?"next year":"下一年",toTitle:this.en?"TO":"至",okTitle:this.en?"OK":"确定",left:!1,ranges:[],days:this.en?["Mo","Tu","We","Th","Fr","Sa","Su"]:["一","二","三","四","五","六","日"],months:this.en?["January","February","March","April","May","June","July","August","September","October","November","December"]:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],years1:[],years2:[],months1:[],months2:[],date1:null,date2:null,time1:this.parse(this.startTime,!1)||this.parse(this.time,!1),time2:this.parse(this.endTime,!0),now1:this.parse(new Date,!1),now2:this.parse(new Date,!0),count:this.range?2:1}},computed:{value:function(){return this.range?this.startTime&&this.endTime?this.stringify(this.parse(this.startTime,!1))+" ~ "+this.stringify(this.parse(this.endTime,!1)):"":this.stringify(this.parse(this.time,!1))}},watch:{show:function(a){this.hidePanel(),a&&this.$els.popup.focus()},now1:function(){this.updateAll()},now2:function(){this.updateAll()}},methods:{parse:function(a,b){if(a){var c=new Date(a);return void 0===b?c:b?new Date(c.getFullYear(),c.getMonth(),c.getDate(),23,59,59,999):new Date(c.getFullYear(),c.getMonth(),c.getDate())}return null},initRanges:function(){var a=new Date,b=[];b.push({name:"今天",start:this.parse(a,!1),end:this.parse(a,!0)}),a.setDate(a.getDate()-1),b.push({name:"昨天",start:this.parse(a,!1),end:this.parse(a,!0)}),a=new Date,a.setDate(a.getDate()-6),b.push({name:"最近7天",start:this.parse(a,!1),end:this.parse(new Date,!0)}),a=new Date,a.setMonth(a.getMonth()+1,0),b.push({name:"本月",start:new Date(a.getFullYear(),a.getMonth(),1),end:this.parse(a,!0)}),a=new Date,a.setMonth(a.getMonth(),0),b.push({name:"上个月",start:new Date(a.getFullYear(),a.getMonth(),1),end:this.parse(a,!0)}),a=new Date,a.setDate(a.getDate()-29),b.push({name:"最近一个月",start:this.parse(a,!1),end:this.parse(new Date,!0)}),a=new Date,a.setDate(a.getDate()-365),b.push({name:"最近一年",start:this.parse(a,!1),end:this.parse(new Date,!0)}),this.ranges=b},updateAll:function(){this.update(new Date(this.now1),1),this.range&&this.update(new Date(this.now2),2)},click:function(){var b,c,a=this;a.time1=a.parse(a.startTime)||a.parse(a.time),a.now1=a.parse(a.startTime)||new Date,a.range&&(a.initRanges(),a.time2=a.parse(a.endTime),a.now2=a.parse(a.endTime)||new Date),b=this.$el.getBoundingClientRect(),c=document.documentElement.clientWidth-b.left,a.left=c<(a.range?441:214)&&c0;c--)h=f-c+1,d=new Date(a.getFullYear(),a.getMonth(),h),d=this.parse(d,2===b),i.push({status:this.getTimeStatus(d,b)||"mz-calendar-lastmonth",title:this.stringify(d),text:h,time:d});for(a.setMonth(a.getMonth()+2,0),g=a.getDate(),a.setDate(1),c=1;g>=c;c++)d=new Date(a.getFullYear(),a.getMonth(),c),d=this.parse(d,2===b),i.push({status:this.getTimeStatus(d,b),title:this.stringify(d),text:c,time:d});for(c=1;i.length<42;c++)d=new Date(a.getFullYear(),a.getMonth()+1,c),d=this.parse(d,2===b),i.push({status:this.getTimeStatus(d,b)||"mz-calendar-nextmonth",title:this.stringify(d),text:c,time:d});this["date"+b]=i},getTimeStatus:function(a,b,c){var j,k,d="",e=new Date,f=this["time"+b],g=this.stringify(a,c||"yyyy-MM-dd"),h=this.stringify(e,c||"yyyy-MM-dd"),i=this.stringify(f,c||"yyyy-MM-dd");return g===i?d="mz-calendar-selected":g===h&&(d="mz-calendar-today"),this.time1&&this.time2&&a>=this.time1&&a<=this.time2&&(d+=" mz-calendar-inrange"),1==b&&this.time2&&(j=new Date(this.time2),this.maxRange?(j.setDate(j.getDate()-this.maxRange),"yyyy"===c&&(j=new Date(j.getFullYear(),0,1)),"yyyy-MM"===c&&(j=new Date(j.getFullYear(),0,1)),(j>a||a>this.time2)&&(d+=" mz-calendar-disabled")):a>this.time2&&(d+=" mz-calendar-disabled"),a>this.time2&&(d+=" mz-calendar-disabled")),2==b&&this.time1&&(k=new Date(this.time1),this.maxRange?(k.setDate(k.getDate()+this.maxRange),"yyyy"===c&&(k=new Date(k.getFullYear(),11,1)),"yyyy-MM"===c&&(k=new Date(k.getFullYear(),k.getMonth()+1,1)),(a>k||a' +
19 | '' +
20 | '' +
51 | '',
52 | props: {
53 | //是否显示范围
54 | range: {
55 | type: Boolean,
56 | default: false
57 | },
58 | //显示宽度
59 | width: {
60 | default: 214
61 | },
62 | //输入的时间
63 | time: {
64 | twoWay: true
65 | },
66 | //输入的开始时间
67 | startTime: {
68 | twoWay: true
69 | },
70 | //输入的结束时间
71 | endTime: {
72 | twoWay: true
73 | },
74 | //选择最大范围限制,以天为单位(只有range为true的时候才起作用)
75 | maxRange: {
76 | coerce: function(val) {
77 | return +val;
78 | }
79 | },
80 | //是否可以清除
81 | clearable: {
82 | type: Boolean,
83 | default: false
84 | },
85 | //显示格式
86 | format: {
87 | type: String,
88 | default: 'yyyy-MM-dd'
89 | },
90 | //禁用
91 | disabled: {
92 | type: Boolean,
93 | default: false
94 | },
95 | //是否需要点击确认
96 | confirm: {
97 | type: Boolean,
98 | default: false
99 | },
100 | //英文显示
101 | en: {
102 | type: Boolean,
103 | default: false
104 | },
105 | //点击确认触发事件
106 | onConfirm: Function
107 | },
108 | data: function() {
109 | return {
110 | show: false,
111 | showYear1: false,
112 | showYear2: false,
113 | showMonth1: false,
114 | showMonth2: false,
115 | prevYearTitle: this.en ? 'last year' : '上一年',
116 | prevMonthTitle: this.en ? 'last month' : '上个月',
117 | selectYearTitle: this.en ? 'select year' : '选择年份',
118 | selectMonthTitle: this.en ? 'select month' : '选择月份',
119 | nextMonthTitle: this.en ? 'next month' : '下个月',
120 | nextYearTitle: this.en ? 'next year' : '下一年',
121 | toTitle: this.en ? 'TO' : '至',
122 | okTitle: this.en ? 'OK' : '确定',
123 | left: false,
124 | ranges: [], //选择范围
125 | days: this.en ? ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'] : ['一', '二', '三', '四', '五', '六', '日'],
126 | months: this.en ? ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] : ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
127 | years1: [],
128 | years2: [],
129 | months1: [],
130 | months2: [],
131 | date1: null,
132 | date2: null,
133 | time1: this.parse(this.startTime, false) || this.parse(this.time, false),
134 | time2: this.parse(this.endTime, true),
135 | now1: this.parse(new Date(), false),
136 | now2: this.parse(new Date(), true),
137 | count: this.range ? 2 : 1 //日历数量
138 | };
139 | },
140 | computed: {
141 | value: function() {
142 | if (this.range) {
143 | if (this.startTime && this.endTime) {
144 | return this.stringify(this.parse(this.startTime, false)) + ' ~ ' + this.stringify(this.parse(this.endTime, false));
145 | } else {
146 | return '';
147 | }
148 | } else {
149 | return this.stringify(this.parse(this.time, false));
150 | }
151 | }
152 | },
153 | watch: {
154 | show: function(val) {
155 | this.hidePanel();
156 | val && this.$els.popup.focus();
157 | },
158 | now1: function() {
159 | this.updateAll();
160 | },
161 | now2: function() {
162 | this.updateAll();
163 | }
164 | },
165 | methods: {
166 | //转换输入的时间
167 | parse: function(time, isLast) {
168 | if (time) {
169 | var tmpTime = new Date(time);
170 | if (isLast === undefined) {
171 | return tmpTime;
172 | } else if (isLast) {
173 | return new Date(tmpTime.getFullYear(), tmpTime.getMonth(), tmpTime.getDate(), 23, 59, 59, 999);
174 | } else {
175 | return new Date(tmpTime.getFullYear(), tmpTime.getMonth(), tmpTime.getDate());
176 | }
177 | }
178 | return null;
179 | },
180 | //初始化时间范围
181 | initRanges: function() {
182 | var time = new Date(),
183 | ranges = [];
184 | ranges.push({
185 | name: '今天',
186 | start: this.parse(time, false),
187 | end: this.parse(time, true)
188 | });
189 | time.setDate(time.getDate() - 1);
190 | ranges.push({
191 | name: '昨天',
192 | start: this.parse(time, false),
193 | end: this.parse(time, true)
194 | });
195 | time = new Date();
196 | time.setDate(time.getDate() - 6);
197 | ranges.push({
198 | name: '最近7天',
199 | start: this.parse(time, false),
200 | end: this.parse(new Date(), true)
201 | });
202 | time = new Date();
203 | time.setMonth(time.getMonth() + 1, 0);
204 | ranges.push({
205 | name: '本月',
206 | start: new Date(time.getFullYear(), time.getMonth(), 1),
207 | end: this.parse(time, true)
208 | });
209 | time = new Date();
210 | time.setMonth(time.getMonth(), 0);
211 | ranges.push({
212 | name: '上个月',
213 | start: new Date(time.getFullYear(), time.getMonth(), 1),
214 | end: this.parse(time, true)
215 | });
216 | time = new Date();
217 | time.setDate(time.getDate() - 29);
218 | ranges.push({
219 | name: '最近一个月',
220 | start: this.parse(time, false),
221 | end: this.parse(new Date(), true)
222 | });
223 | time = new Date();
224 | time.setDate(time.getDate() - 365);
225 | ranges.push({
226 | name: '最近一年',
227 | start: this.parse(time, false),
228 | end: this.parse(new Date(), true)
229 | });
230 | this.ranges = ranges;
231 | },
232 | //更新所有的日历
233 | updateAll: function() {
234 | this.update(new Date(this.now1), 1);
235 | this.range && this.update(new Date(this.now2), 2);
236 | },
237 | //点击时间输入框的时候触发
238 | click: function() {
239 | var self = this;
240 | self.time1 = self.parse(self.startTime) || self.parse(self.time);
241 | self.now1 = self.parse(self.startTime) || new Date();
242 | if (self.range) {
243 | self.initRanges();
244 | self.time2 = self.parse(self.endTime);
245 | self.now2 = self.parse(self.endTime) || new Date();
246 | }
247 | var rect = this.$el.getBoundingClientRect(),
248 | right = document.documentElement.clientWidth - rect.left;
249 | (right < (self.range ? 441 : 214) && right < rect.left) ? (self.left = true) : (self.left = false);
250 | self.show = !self.show;
251 | },
252 | //选择时间
253 | select: function(item, no) {
254 | var self = this;
255 | self.hidePanel();
256 | if (item.status.indexOf('mz-calendar-disabled') !== -1) {
257 | return;
258 | }
259 | self['now' + no] = new Date(item.time);
260 | self['time' + no] = new Date(item.time);
261 | if (!self.range) {
262 | self.time = self.getOutTime(item.time);
263 | self.show = false;
264 | } else if (!self.confirm) {
265 | self[no === 1 ? 'startTime' : 'endTime'] = self.getOutTime(item.time);
266 | }
267 | },
268 | //确认
269 | ok: function() {
270 | var self = this;
271 | self.show = false;
272 | if (self.range && self.confirm) {
273 | self.startTime = self.getOutTime(self.time1);
274 | self.endTime = self.getOutTime(self.time2);
275 | self.onConfirm && self.onConfirm(self.startTime, self.endTime);
276 | }
277 | },
278 | //选择范围
279 | selectRange: function(item) {
280 | var self = this;
281 | self.now1 = new Date(item.start);
282 | self.now2 = new Date(item.end);
283 | self.time1 = new Date(item.start);
284 | self.time2 = new Date(item.end);
285 | self.startTime = self.getOutTime(item.start);
286 | self.endTime = self.getOutTime(item.end);
287 | self.hidePanel();
288 | },
289 | //根据输出类型,获取输出的时间
290 | getOutTime: function(time) {
291 | var type = this.time ? typeof(this.time) : typeof(this.startTime);
292 | if (type === 'number') {
293 | return time.getTime();
294 | } else if (type === 'object') {
295 | return new Date(time);
296 | } else {
297 | return this.stringify(time);
298 | }
299 | },
300 | //更新时间
301 | update: function(time, no) {
302 | var i, tmpTime, curFirstDay, lastDay, curDay, day, arr = [];
303 | time.setDate(0); //切换到上个月最后一天
304 | curFirstDay = time.getDay(); //星期几
305 | lastDay = time.getDate(); //上个月的最后一天
306 | for (i = curFirstDay; i > 0; i--) {
307 | day = lastDay - i + 1;
308 | tmpTime = new Date(time.getFullYear(), time.getMonth(), day);
309 | tmpTime = this.parse(tmpTime, no === 2);
310 | arr.push({
311 | status: this.getTimeStatus(tmpTime, no) || 'mz-calendar-lastmonth',
312 | title: this.stringify(tmpTime),
313 | text: day,
314 | time: tmpTime
315 | });
316 | }
317 | time.setMonth(time.getMonth() + 2, 0); //切换到当前月的最后一天
318 | curDay = time.getDate(); //当前月的最后一天
319 | time.setDate(1);
320 | for (i = 1; i <= curDay; i++) {
321 | tmpTime = new Date(time.getFullYear(), time.getMonth(), i);
322 | tmpTime = this.parse(tmpTime, no === 2);
323 | arr.push({
324 | status: this.getTimeStatus(tmpTime, no),
325 | title: this.stringify(tmpTime),
326 | text: i,
327 | time: tmpTime
328 | });
329 | }
330 | //下个月的前几天
331 | for (i = 1; arr.length < 42; i++) {
332 | tmpTime = new Date(time.getFullYear(), time.getMonth() + 1, i);
333 | tmpTime = this.parse(tmpTime, no === 2);
334 | arr.push({
335 | status: this.getTimeStatus(tmpTime, no) || 'mz-calendar-nextmonth',
336 | title: this.stringify(tmpTime),
337 | text: i,
338 | time: tmpTime
339 | });
340 | }
341 | this['date' + no] = arr;
342 | },
343 | //获取时间状态
344 | getTimeStatus: function(time, no, format) {
345 | var status = '',
346 | curTime = new Date(),
347 | selTime = this['time' + no],
348 | tmpTimeVal = this.stringify(time, format || 'yyyy-MM-dd'), //需要查询状态的时间字符串值
349 | curTimeVal = this.stringify(curTime, format || 'yyyy-MM-dd'), //当前时间字符串值
350 | selTimeVal = this.stringify(selTime, format || 'yyyy-MM-dd'); //选中时间字符串值
351 | if (tmpTimeVal === selTimeVal) {
352 | status = 'mz-calendar-selected';
353 | } else if (tmpTimeVal === curTimeVal) {
354 | status = 'mz-calendar-today';
355 | }
356 | if (this.time1 && this.time2 && time >= this.time1 && time <= this.time2) {
357 | status += ' mz-calendar-inrange';
358 | }
359 | if (no == 1 && this.time2) {
360 | var minTime = new Date(this.time2);
361 | if (this.maxRange) {
362 | minTime.setDate(minTime.getDate() - this.maxRange);
363 | if (format === 'yyyy') {
364 | minTime = new Date(minTime.getFullYear(), 0, 1);
365 | }
366 | if (format === 'yyyy-MM') {
367 | minTime = new Date(minTime.getFullYear(), 0, 1);
368 | }
369 | if (time < minTime || time > this.time2) {
370 | status += ' mz-calendar-disabled';
371 | }
372 | } else if (time > this.time2) {
373 | status += ' mz-calendar-disabled';
374 | }
375 | if (time > this.time2) {
376 | status += ' mz-calendar-disabled';
377 | }
378 | }
379 | if (no == 2 && this.time1) {
380 | var maxTime = new Date(this.time1);
381 | if (this.maxRange) {
382 | maxTime.setDate(maxTime.getDate() + this.maxRange);
383 | if (format === 'yyyy') {
384 | maxTime = new Date(maxTime.getFullYear(), 11, 1);
385 | }
386 | if (format === 'yyyy-MM') {
387 | maxTime = new Date(maxTime.getFullYear(), maxTime.getMonth() + 1, 1);
388 | }
389 | if (time > maxTime || time < this.time1) {
390 | status += ' mz-calendar-disabled';
391 | }
392 | } else if (time < this.time1) {
393 | status += ' mz-calendar-disabled';
394 | }
395 | }
396 | return status;
397 | },
398 | //将Date转化为指定格式的String
399 | stringify: function(time, format) {
400 | if (!time) {
401 | return '';
402 | }
403 | format = format || this.format;
404 | var year = time.getFullYear(), //年份
405 | month = time.getMonth() + 1, //月份
406 | day = time.getDate(), //日
407 | hours24 = time.getHours(), //小时
408 | hours = hours24 % 12 === 0 ? 12 : hours24 % 12,
409 | minutes = time.getMinutes(), //分
410 | seconds = time.getSeconds(), //秒
411 | milliseconds = time.getMilliseconds(); //毫秒
412 | var map = {
413 | yyyy: year,
414 | MM: ('0' + month).slice(-2),
415 | M: month,
416 | dd: ('0' + day).slice(-2),
417 | d: day,
418 | HH: ('0' + hours24).slice(-2),
419 | H: hours24,
420 | hh: ('0' + hours).slice(-2),
421 | h: hours,
422 | mm: ('0' + minutes).slice(-2),
423 | m: minutes,
424 | ss: ('0' + seconds).slice(-2),
425 | s: seconds,
426 | S: milliseconds
427 | };
428 | return format.replace(/y+|M+|d+|H+|h+|m+|s+|S+/g, function(str) {
429 | return map[str];
430 | });
431 | },
432 | //显示年份选择器
433 | showYear: function(no) {
434 | var name = 'showYear' + no;
435 | this.hidePanel(name);
436 | this[name] = !this[name];
437 | var time = new Date(this['now' + no] || new Date()),
438 | num = Math.floor(time.getFullYear() % 10), //获取当前时间个位数
439 | arr = [];
440 | time.setDate(1); //先设置为第一天,因为月份天数不一样,要不存在bug
441 | time.setFullYear(time.getFullYear() - num);
442 | while (arr.length < 10) {
443 | no === 2 && time.setMonth(time.getMonth() + 1, 0);
444 | arr.push({
445 | year: time.getFullYear(),
446 | status: this.getTimeStatus(time, no, 'yyyy'),
447 | });
448 | time.setDate(1);
449 | time.setFullYear(time.getFullYear() + 1);
450 | }
451 | this['years' + no] = arr;
452 | },
453 | //显示月份选择器
454 | showMonth: function(no) {
455 | var name = 'showMonth' + no;
456 | this.hidePanel(name);
457 | this[name] = !this[name];
458 | var time = new Date(this['now' + no] || new Date()),
459 | arr = [];
460 | while (arr.length < 12) {
461 | time.setDate(1); //先设置为第一天,因为月份天数不一样,要不存在bug
462 | time.setMonth(arr.length);
463 | no === 2 && time.setMonth(time.getMonth() + 1, 0);
464 | arr.push({
465 | month: arr.length + 1,
466 | status: this.getTimeStatus(time, no, 'yyyy-MM'),
467 | });
468 | }
469 | this['months' + no] = arr;
470 | },
471 | //切换年份选择器
472 | changeYearRange: function(no, flag) {
473 | var arr = this['years' + no],
474 | time = new Date(this['time' + no] || new Date());
475 | for (var i in arr) {
476 | var item = arr[i],
477 | year = item.year + 10 * flag;
478 | time.setDate(1); //先设置为第一天,因为月份天数不一样,要不存在bug
479 | time.setFullYear(year);
480 | no === 2 && time.setMonth(time.getMonth() + 1, 0);
481 | item.year = year;
482 | item.status = this.getTimeStatus(time, no);
483 | }
484 | },
485 | //改变年份
486 | changeYear: function(flag, no) {
487 | var now = this['now' + no];
488 | now.setDate(1); //先设置为第一天,因为月份天数不一样,要不存在bug
489 | now.setFullYear(now.getFullYear() + flag);
490 | no === 2 && now.setMonth(now.getMonth() + 1, 0);
491 | this['now' + no] = new Date(now);
492 | this.hidePanel();
493 | },
494 | //改变月份
495 | changeMonth: function(flag, no) {
496 | var now = this['now' + no];
497 | now.setDate(1); //先设置为第一天,因为月份天数不一样,要不存在bug
498 | now.setMonth(now.getMonth() + flag);
499 | no === 2 && now.setMonth(now.getMonth() + 1, 0);
500 | this['now' + no] = new Date(now);
501 | this.hidePanel();
502 | },
503 | //选择年份
504 | selectYear: function(item, no) {
505 | if (item.status.indexOf('mz-calendar-disabled') !== -1) {
506 | return;
507 | }
508 | var now = this['now' + no];
509 | now.setFullYear(item.year);
510 | this['now' + no] = new Date(now);
511 | this.hidePanel();
512 | },
513 | //选择月份
514 | selectMonth: function(item, no) {
515 | if (item.status.indexOf('mz-calendar-disabled') !== -1) {
516 | return;
517 | }
518 | var now = this['now' + no];
519 | now.setMonth(item.month - 1);
520 | this['now' + no] = new Date(now);
521 | this.hidePanel();
522 | },
523 | //隐藏所有面板
524 | hidePanel: function(name) {
525 | ['showYear1', 'showYear2', 'showMonth1', 'showMonth2'].map(function(item) {
526 | if (item !== name) {
527 | this[item] = false;
528 | }
529 | }.bind(this));
530 | },
531 | //清除时间
532 | clear: function() {
533 | var self = this;
534 | self.time1 = self.time2 = self.startTime = self.endTime = self.time = null;
535 | self.now1 = new Date();
536 | self.now2 = new Date();
537 | }
538 | }
539 | });
540 | }));
--------------------------------------------------------------------------------