| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| <template> |
| <div :class="`${pre}`"> |
| <div :class="`${pre}-head`"> |
| <a :class="`${pre}-prev-decade-btn`" v-show="showYears" @click="year-=10"><svg class="icon sm cp"> |
| <use xlink:href="#angle-double-left"></use> |
| </svg></a> |
| <a :class="`${pre}-prev-year-btn`" v-show="!showYears" @click="year--"><svg class="icon sm cp"> |
| <use xlink:href="#angle-double-left"></use> |
| </svg></a> |
| <a :class="`${pre}-prev-month-btn`" v-show="!showYears&&!showMonths" @click="pm"> |
| <svg class="icon lg cp"> |
| <use xlink:href="#chevron-left"></use> |
| </svg></a> |
| <a :class="`${pre}-year-select`" v-show="showYears">{{ys+'-'+ye}}</a> |
| <template v-if="local.yearSuffix"> |
| <a :class="`${pre}-year-select`" @click="showYears=!showYears" v-show="!showYears">{{year}}{{local.yearSuffix}}</a> |
| <a :class="`${pre}-month-select`" @click="showMonths=!showMonths" v-show="!showYears&&!showMonths">{{local.monthsHead[month]}}</a> |
| </template> |
| <template v-else> |
| <a :class="`${pre}-month-select`" @click="showMonths=!showMonths" v-show="!showYears&&!showMonths">{{local.monthsHead[month]}}</a> |
| <a :class="`${pre}-year-select`" @click="showYears=!showYears" v-show="!showYears">{{year}}</a> |
| </template> |
| <a :class="`${pre}-next-month-btn`" v-show="!showYears&&!showMonths" @click="nm"> |
| <svg class="icon lg cp"> |
| <use xlink:href="#chevron-right"></use> |
| </svg></a> |
| <a :class="`${pre}-next-year-btn`" v-show="!showYears" @click="year++"><svg class="icon sm cp"> |
| <use xlink:href="#angle-double-right"></use> |
| </svg></a> |
| <a :class="`${pre}-next-decade-btn`" v-show="showYears" @click="year+=10"><svg class="icon sm cp"> |
| <use xlink:href="#angle-double-right"></use> |
| </svg></a> |
| </div> |
| <div :class="`${pre}-body`"> |
| <div :class="`${pre}-days`"> |
| <a :class="`${pre}-week`" v-for="i in local.weeks" :key="i">{{i}}</a> |
| <a v-for="(j,i) in days" @click="is($event)&&(day=j.i,ok(j))" :class="[(j.p||j.n)?`${pre}-date-out`:'',status(j.y,j.m,j.i,hour,minute,second,'YYYYMMDD')]" :key="i">{{j.i}}</a> |
| </div> |
| <div :class="`${pre}-months`" v-show="showMonths"> |
| <a v-for="(i,j) in local.months" @click="is($event)&&(showMonths=(m==='M'),month=j,(m==='M'&&ok('m')))" :class="[status(year,j,day,hour,minute,second,'YYYYMM')]" :key="j">{{i}}</a> |
| </div> |
| <div :class="`${pre}-years`" v-show="showYears"> |
| <a v-for="(i,j) in years" @click="is($event)&&(showYears=(m==='Y'),year=i,(m==='Y'&&ok('y')))" :class="[(j===0||j===11)?`${pre}-date-out`:'',status(i,month,day,hour,minute,second,'YYYY')]" :key="j">{{i}}</a> |
| </div> |
| <div :class="`${pre}-hours scroll_hide`" v-show="showHours"> |
| <div :class="`${pre}-title`">{{local.hourTip}}</div> |
| <div class="scroll_hide calendar-overflow"> |
| <a v-for="(j,i) in 24" @click="is($event)&&(showHours=false,hour=i,ok('h'))" :class="[status(year,month,day,i,minute,second,'YYYYMMDDHH')]" :key="i">{{i}}</a> |
| </div> |
| </div> |
| <div :class="`${pre}-minutes`" v-show="showMinutes"> |
| <div :class="`${pre}-title`">{{local.minuteTip}}</div> |
| <div class="scroll_hide calendar-overflow"> |
| <a v-for="(j,i) in 60" @click="is($event)&&(showMinutes=false,minute=i,ok('h'))" :class="[status(year,month,day,hour,i,second,'YYYYMMDDHHmm')]" :key="i">{{i}}</a> |
| </div> |
| </div> |
| <div :class="`${pre}-seconds`" v-show="showSeconds"> |
| <div :class="`${pre}-title`">{{local.secondTip}}</div> |
| <div class="scroll_hide calendar-overflow"> |
| <a v-for="(j,i) in 60" @click="is($event)&&(showSeconds=false,second=i,ok('h'))" :class="[status(year,month,day,hour,minute,i,'YYYYMMDDHHmmss')]" :key="i">{{i}}</a> |
| </div> |
| </div> |
| </div> |
| <div :class="`${pre}-foot`" v-if="m==='H'"> |
| <div :class="`${pre}-hour`"> |
| <a :title="local.hourTip" @click="showHours=!showHours,showMinutes=showSeconds=false" :class="{on:showHours}">{{hour|dd}}</a> |
| <span>:</span> |
| <a :title="local.minuteTip" @click="showMinutes=!showMinutes,showHours=showSeconds=false" :class="{on:showMinutes}">{{minute|dd}}</a> |
| <span>:</span> |
| <a :title="local.secondTip" @click="showSeconds=!showSeconds,showHours=showMinutes=false" :class="{on:showSeconds}">{{second|dd}}</a> |
| </div> |
| </div> |
| </div> |
| </template> |
| |
| <script lang="js"> |
| /* eslint-disable */ |
| /* tslint:disable */ |
| export default { |
| name: 'VueDatepickerLocalCalendar', |
| props: { |
| value: { default: null }, |
| left: { default: false }, |
| right: { default: false }, |
| }, |
| data() { |
| const get = (time) => { |
| return { |
| year: time.getFullYear(), |
| month: time.getMonth(), |
| day: time.getDate(), |
| hour: time.getHours(), |
| minute: time.getMinutes(), |
| second: time.getSeconds(), |
| }; |
| }; |
| const time = get(this.value); |
| return { |
| pre: 'calendar', |
| m: 'D', |
| showYears: false, |
| showMonths: false, |
| showHours: false, |
| showMinutes: false, |
| showSeconds: false, |
| year: time.year, |
| month: time.month, |
| day: time.day, |
| hour: time.hour, |
| minute: time.minute, |
| second: time.second, |
| }; |
| }, |
| watch: { |
| value(val) { |
| const $this = this; |
| const time = $this.get(val); |
| $this.year = time.year; |
| $this.month = time.month; |
| $this.day = time.day; |
| $this.hour = time.hour; |
| $this.minute = time.minute; |
| $this.second = time.second; |
| }, |
| }, |
| computed: { |
| local() { |
| return this.$parent.local; |
| }, |
| format() { |
| return this.$parent.format; |
| }, |
| start() { |
| return this.parse(this.$parent.dates[0]); |
| }, |
| end() { |
| return this.parse(this.$parent.dates[1]); |
| }, |
| ys() { |
| return Math.floor(this.year / 10) * 10; |
| }, |
| ye() { |
| return this.ys + 10; |
| }, |
| years() { |
| const arr = []; |
| let start = this.ys - 1; |
| while (arr.length < 12) { |
| arr.push(start += 1); |
| } |
| return arr; |
| }, |
| days() { |
| const days = []; |
| const $this = this; |
| const year = $this.year; |
| const month = $this.month; |
| const time = new Date(year, month, 1); |
| const dow = $this.local.dow || 7; |
| time.setDate(0); // switch to the last day of last month |
| let lastDay = time.getDate(); |
| const week = time.getDay() || 7; |
| let count = dow <= week ? week - dow + 1 : week + (7 - dow + 1); |
| while (count > 0) { |
| days.push({ |
| i: lastDay - count + 1, |
| y: month > 0 ? year : year - 1, |
| m: month > 0 ? month - 1 : 11, |
| p: true, |
| }); |
| count--; |
| } |
| time.setMonth(time.getMonth() + 2, 0); // switch to the last day of the current month |
| lastDay = time.getDate(); |
| let i = 1; |
| for (i = 1; i <= lastDay; i++) { |
| days.push({ |
| i: i, |
| y: year, |
| m: month, |
| }); |
| } |
| for (i = 1; days.length < 42; i++) { |
| days.push({ |
| i: i, |
| y: month < 11 ? year : year + 1, |
| m: month < 11 ? month + 1 : 0, |
| n: true, |
| }); |
| } |
| return days; |
| }, |
| }, |
| filters: { |
| dd: val => ('0' + val).slice(-2), |
| }, |
| methods: { |
| get(time) { |
| return { |
| year: time.getFullYear(), |
| month: time.getMonth(), |
| day: time.getDate(), |
| hour: time.getHours(), |
| minute: time.getMinutes(), |
| second: time.getSeconds(), |
| }; |
| }, |
| parse(num) { |
| return Math.floor(num / 1000); |
| }, |
| status(year, month, day, hour, minute, second, format) { |
| const $this = this; |
| const maxDay = new Date(year, month + 1, 0).getDate(); |
| const time = new Date( |
| year, |
| month, |
| day > maxDay ? maxDay : day, |
| hour, |
| minute, |
| second |
| ); |
| const t = $this.parse(time); |
| const f = $this.$parent.tf; |
| const classObj = {}; |
| let flag = false; |
| if (format === 'YYYY') { |
| flag = year === $this.year; |
| } else if (format === 'YYYYMM') { |
| flag = month === $this.month; |
| } else { |
| flag = f($this.value, format) === f(time, format); |
| } |
| classObj[`${$this.pre}-date`] = true; |
| classObj[`${$this.pre}-date-disabled`] = |
| ($this.right && t < $this.start) || |
| $this.$parent.disabledDate(time, format); |
| classObj[`${$this.pre}-date-on`] = |
| ($this.left && t > $this.start) || ($this.right && t < $this.end); |
| classObj[`${$this.pre}-date-selected`] = flag; |
| return classObj; |
| }, |
| nm() { |
| if (this.month < 11) { |
| this.month++; |
| } else { |
| this.month = 0; |
| this.year++; |
| } |
| }, |
| pm() { |
| if (this.month > 0) { |
| this.month--; |
| } else { |
| this.month = 11; |
| this.year--; |
| } |
| }, |
| is(e) { |
| return e.target.className.indexOf(`${this.pre}-date-disabled`) === -1; |
| }, |
| ok(info) { |
| const $this = this; |
| let year = ''; |
| let month = ''; |
| let day = ''; |
| info && info.n && $this.nm(); |
| info && info.p && $this.pm(); |
| if (info === 'h') { |
| const time = $this.get(this.value); |
| year = time.year; |
| month = time.month; |
| } else if (info === 'm' || info === 'y') { |
| day = '1'; |
| } |
| const _time = new Date( |
| year || $this.year, |
| month || $this.month, |
| day || $this.day, |
| $this.hour, |
| $this.minute, |
| $this.second |
| ); |
| if ($this.left && Math.floor(_time.getTime() / 1000) > $this.end) { |
| this.$parent.dates[1] = _time; |
| } |
| $this.$emit('input', _time); |
| $this.$parent.ok(info === 'h'); |
| }, |
| }, |
| mounted() { |
| const $this = this; |
| const is = c => $this.format.indexOf(c) !== -1; |
| if (is('s') && is('m') && (is('h') || is('H'))) { |
| $this.m = 'H'; |
| } else if (is('D')) { |
| $this.m = 'D'; |
| } else if (is('M')) { |
| $this.m = 'M'; |
| $this.showMonths = true; |
| } else if (is('Y')) { |
| $this.m = 'Y'; |
| $this.showYears = true; |
| } |
| }, |
| }; |
| </script> |
| |
| <style scoped> |
| .calendar { |
| float: left; |
| -webkit-user-select: none; |
| -moz-user-select: none; |
| -ms-user-select: none; |
| user-select: none; |
| color: #3d444f; |
| } |
| .calendar + .calendar { |
| border-left: solid 1px #eaeaea; |
| margin-left: 5px; |
| padding-left: 5px; |
| } |
| .calendar-head { |
| line-height: 34px; |
| height: 34px; |
| text-align: center; |
| position: relative; |
| } |
| |
| .calendar-head a { |
| color: #666; |
| cursor: pointer; |
| display: inline-block; |
| text-align: center; |
| position: absolute; |
| padding: 0 5px; |
| font-size: 16px; |
| } |
| |
| .calendar-head a:hover { |
| color: #3f97e3; |
| } |
| |
| .calendar-head .calendar-year-select, |
| .calendar-head .calendar-month-select { |
| font-size: 12px; |
| padding: 0 2px; |
| position: relative; |
| } |
| |
| .calendar-prev-decade-btn, |
| .calendar-prev-year-btn { |
| left: 6px; |
| } |
| |
| .calendar-prev-month-btn { |
| left: 24px; |
| } |
| |
| .calendar-next-decade-btn, |
| .calendar-next-year-btn { |
| right: 6px; |
| } |
| |
| .calendar-next-month-btn { |
| right: 24px; |
| } |
| .calendar-next-month-btn .icon.lg, .calendar-prev-month-btn .icon.lg{ |
| margin-top: 8px; |
| } |
| .calendar-body { |
| position: relative; |
| width: 196px; |
| height: 196px; |
| } |
| |
| .calendar-days { |
| width: 100%; |
| height: 100%; |
| } |
| |
| .calendar-week, |
| .calendar-date { |
| font-weight: normal; |
| width: 14.28%; |
| height: 14.28%; |
| text-align: center; |
| box-sizing: border-box; |
| overflow: hidden; |
| float: left; |
| } |
| |
| .calendar-week:before, |
| .calendar-date:before { |
| content: ''; |
| display: inline-block; |
| height: 100%; |
| vertical-align: middle; |
| } |
| |
| .calendar-date { |
| cursor: pointer; |
| line-height: 29px; |
| transition: background-color .3s; |
| } |
| |
| .calendar-date-out { |
| color: #ccc; |
| } |
| |
| .calendar-date:hover, |
| .calendar-date-on { |
| color: #3f97e3; |
| background-color: #f8f8f8; |
| } |
| |
| .calendar-date-selected, |
| .calendar-date-selected:hover { |
| color: #fff; |
| font-weight: bold; |
| border-radius: 14px; |
| background: #3f97e3; |
| } |
| |
| .calendar-date-disabled { |
| cursor: not-allowed !important; |
| color: #ccc !important; |
| background: #fff !important; |
| } |
| |
| .calendar-foot { |
| margin-top: 5px; |
| } |
| |
| .calendar-hour { |
| display: inline-block; |
| border: 1px solid #e6e5e5; |
| color: #9e9e9e; |
| } |
| |
| .calendar-hour a { |
| display: inline-block; |
| padding: 2px 4px; |
| cursor: pointer; |
| } |
| |
| .calendar-hour a:hover, |
| .calendar-hour a.on { |
| color: #3f97e3; |
| } |
| |
| .calendar-years, |
| .calendar-months, |
| .calendar-hours, |
| .calendar-minutes, |
| .calendar-seconds { |
| width: 100%; |
| height: 100%; |
| position: absolute; |
| background: #fff; |
| left: 0; |
| top: 0; |
| } |
| |
| .calendar-months a { |
| width: 33.33%; |
| height: 25%; |
| } |
| |
| .calendar-years a { |
| width: 33.33%; |
| height: 25%; |
| } |
| |
| .calendar-overflow{ |
| overflow-x:scroll; |
| height: 100%; |
| } |
| |
| /* .calendar-hours a { |
| width: 20%; |
| height: 20%; |
| } |
| |
| .calendar-minutes a, |
| .calendar-seconds a { |
| width: 16.66%; |
| height: 10%; |
| } */ |
| |
| .calendar-title { |
| margin-top: -30px; |
| height: 30px; |
| line-height: 30px; |
| background: #fff; |
| text-align: center; |
| font-weight: bold; |
| } |
| </style> |
| |