├── 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 | ![image](https://github.com/weifeiyue/vue-datepicker/raw/master/screenshots/datepicker.png) 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 | '
' + 21 | '
' + 22 | '' + 25 | '
' + 26 | '
' + 27 | '' + 48 | '
' + 49 | '' + 50 | '
' + 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 | })); --------------------------------------------------------------------------------