2
0
mirror of https://github.com/tenrok/vue2-datepicker.git synced 2026-06-20 19:30:35 +03:00

打包文件,修改引入方式

This commit is contained in:
mxie
2017-11-30 12:50:32 +08:00
parent 47a33f17d7
commit 2f547731e5
12 changed files with 8471 additions and 251 deletions
+11
View File
@@ -0,0 +1,11 @@
{
"presets": [
[
"env",
{
"modules": false
}
],
"stage-3"
]
}
-1
View File
@@ -2,4 +2,3 @@
node_modules/ node_modules/
npm-debug.log npm-debug.log
yarn-error.log yarn-error.log
package-lock.json
+8
View File
@@ -0,0 +1,8 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
// to edit target browsers: use "browserlist" field in package.json
"autoprefixer": {}
}
}
+1 -1
View File
@@ -61,7 +61,7 @@ export default {
| shortcuts | Boolean/Array | true | the shortcuts for the range picker | | shortcuts | Boolean/Array | true | the shortcuts for the range picker |
| first-day-of-week | Number | 7 | set the first day of week (1-7) | | first-day-of-week | Number | 7 | set the first day of week (1-7) |
| minute-step | Number | 0 | if > 0 don't show the second picker(0 - 60) | | minute-step | Number | 0 | if > 0 don't show the second picker(0 - 60) |
| input-class | String | 'input' | the input class name | | input-class | String | 'mx-input' | the input class name |
| confirm-text | String | 'OK' | the default text to display on confirm button | | confirm-text | String | 'OK' | the default text to display on confirm button |
+141 -126
View File
@@ -1,18 +1,18 @@
<template> <template>
<div class="calendar"> <div class="mx-calendar">
<div class="calendar-header" v-if="currentPanel === 'time'"> <div class="mx-calendar-header" v-if="currentPanel === 'time'">
<a @click="currentPanel = 'date'">{{now.toLocaleDateString()}}</a> <a @click="currentPanel = 'date'">{{now.toLocaleDateString()}}</a>
</div> </div>
<div class="calendar-header" v-else> <div class="mx-calendar-header" v-else>
<a class="calendar__prev-icon" @click="changeYear(-1)">&laquo;</a> <a class="mx-calendar__prev-icon" @click="changeYear(-1)">&laquo;</a>
<a v-show="currentPanel === 'date'" class="calendar__prev-icon" @click="changeMonth(-1)">&lsaquo;</a> <a v-show="currentPanel === 'date'" class="mx-calendar__prev-icon" @click="changeMonth(-1)">&lsaquo;</a>
<a class="calendar__next-icon" @click="changeYear(1)">&raquo;</a> <a class="mx-calendar__next-icon" @click="changeYear(1)">&raquo;</a>
<a v-show="currentPanel === 'date'" class="calendar__next-icon" @click="changeMonth(1)">&rsaquo;</a> <a v-show="currentPanel === 'date'" class="mx-calendar__next-icon" @click="changeMonth(1)">&rsaquo;</a>
<a @click="showMonths">{{months[currentMonth]}}</a> <a @click="showMonths">{{months[currentMonth]}}</a>
<a @click="showYears">{{currentYear}}</a> <a @click="showYears">{{currentYear}}</a>
</div> </div>
<div class="calendar-content"> <div class="mx-calendar-content">
<table class="calendar-table" v-show="currentPanel === 'date'"> <table class="mx-calendar-table" v-show="currentPanel === 'date'">
<thead> <thead>
<tr> <tr>
<th v-for="(day, index) in days" :key="index">{{day}}</th> <th v-for="(day, index) in days" :key="index">{{day}}</th>
@@ -24,20 +24,20 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="calendar-year" v-show="currentPanel === 'years'"> <div class="mx-calendar-year" v-show="currentPanel === 'years'">
<a v-for="year in years" @click="selectYear(year)" :class="{'current': currentYear === year}">{{year}}</a> <a v-for="year in years" @click="selectYear(year)" :class="{'current': currentYear === year}">{{year}}</a>
</div> </div>
<div class="calendar-month" v-show="currentPanel === 'months'"> <div class="mx-calendar-month" v-show="currentPanel === 'months'">
<a v-for="(month, index) in months" @click="selectMonth(index)" :class="{'current': currentMonth === index}">{{month}}</a> <a v-for="(month, index) in months" @click="selectMonth(index)" :class="{'current': currentMonth === index}">{{month}}</a>
</div> </div>
<div class="calendar-time" <div class="mx-calendar-time"
v-show="currentPanel === 'time'" > v-show="currentPanel === 'time'" >
<div class="time-list-wrapper" <div class="mx-time-list-wrapper"
:style="{width: 100 / times.length + '%' }" :style="{width: 100 / times.length + '%' }"
v-for="(time, index) in times" v-for="(time, index) in times"
:key="index"> :key="index">
<ul class="time-list"> <ul class="mx-time-list">
<li class="time-item" <li class="mx-time-item"
v-for="num in time" v-for="num in time"
:class="getTimeClasses(num, index)" :class="getTimeClasses(num, index)"
:key="num" :key="num"
@@ -51,10 +51,9 @@
</template> </template>
<script> <script>
function getTimeArray(len, step = 1) {
function getTimeArray (len, step = 1) {
const length = parseInt(len / step) const length = parseInt(len / step)
return Array.apply(null, {length}).map((v, i) => i * step) return Array.apply(null, { length }).map((v, i) => i * step)
} }
export default { export default {
@@ -64,7 +63,7 @@ export default {
value: null, value: null,
show: Boolean show: Boolean
}, },
data () { data() {
const translation = this.$parent.translation const translation = this.$parent.translation
const minuteStep = this.$parent.minuteStep const minuteStep = this.$parent.minuteStep
const times = [getTimeArray(24, 1), getTimeArray(60, minuteStep || 1)] const times = [getTimeArray(24, 1), getTimeArray(60, minuteStep || 1)]
@@ -82,32 +81,32 @@ export default {
}, },
computed: { computed: {
// 日历显示头 // 日历显示头
days () { days() {
const days = this.$parent.translation.days const days = this.$parent.translation.days
const firstday = +this.$parent.firstDayOfWeek const firstday = +this.$parent.firstDayOfWeek
return days.concat(days).slice(firstday, firstday + 7) return days.concat(days).slice(firstday, firstday + 7)
}, },
currentYear () { currentYear() {
return this.now.getFullYear() return this.now.getFullYear()
}, },
currentMonth () { currentMonth() {
return this.now.getMonth() return this.now.getMonth()
}, },
curHour () { curHour() {
return this.now.getHours() return this.now.getHours()
}, },
curMinute () { curMinute() {
return this.now.getMinutes() return this.now.getMinutes()
}, },
curSecond () { curSecond() {
return this.now.getSeconds() return this.now.getSeconds()
} }
}, },
created () { created() {
this.updateCalendar() this.updateCalendar()
}, },
watch: { watch: {
show (val) { show(val) {
if (val) { if (val) {
this.currentPanel = 'date' this.currentPanel = 'date'
this.updateNow() this.updateNow()
@@ -120,20 +119,28 @@ export default {
now: 'updateCalendar' now: 'updateCalendar'
}, },
filters: { filters: {
timeText (value) { timeText(value) {
return ('00' + value).slice(String(value).length) return ('00' + value).slice(String(value).length)
} }
}, },
methods: { methods: {
updateNow () { updateNow() {
this.now = this.value ? new Date(this.value) : new Date() this.now = this.value ? new Date(this.value) : new Date()
}, },
// 更新面板选择时间 // 更新面板选择时间
updateCalendar () { updateCalendar() {
function getCalendar (time, firstday, length, classes) { function getCalendar(time, firstday, length, classes) {
return Array.apply(null, { length }).map((v, i) => { // eslint-disable-line return Array.apply(null, { length }).map((v, i) => {
// eslint-disable-line
let day = firstday + i let day = firstday + i
const date = new Date(time.getFullYear(), time.getMonth(), day, 0, 0, 0) const date = new Date(
time.getFullYear(),
time.getMonth(),
day,
0,
0,
0
)
date.setDate(day) date.setDate(day)
return { return {
title: date.toLocaleDateString(), title: date.toLocaleDateString(),
@@ -146,9 +153,14 @@ export default {
const firstDayOfWeek = this.$parent.firstDayOfWeek const firstDayOfWeek = this.$parent.firstDayOfWeek
const time = new Date(this.now) const time = new Date(this.now)
time.setDate(0) // 把时间切换到上个月最后一天 time.setDate(0) // 把时间切换到上个月最后一天
const lastMonthLength = (time.getDay() + 7 - firstDayOfWeek) % 7 + 1 // time.getDay() 0是星期天, 1是星期一 ... const lastMonthLength = (time.getDay() + 7 - firstDayOfWeek) % 7 + 1 // time.getDay() 0是星期天, 1是星期一 ...
const lastMonthfirst = time.getDate() - (lastMonthLength - 1) const lastMonthfirst = time.getDate() - (lastMonthLength - 1)
const lastMonth = getCalendar(time, lastMonthfirst, lastMonthLength, 'lastMonth') const lastMonth = getCalendar(
time,
lastMonthfirst,
lastMonthLength,
'lastMonth'
)
time.setMonth(time.getMonth() + 2, 0) // 切换到这个月最后一天 time.setMonth(time.getMonth() + 2, 0) // 切换到这个月最后一天
const curMonthLength = time.getDate() const curMonthLength = time.getDate()
@@ -164,22 +176,28 @@ export default {
const arr = lastMonth.concat(curMonth, nextMonth) const arr = lastMonth.concat(curMonth, nextMonth)
const result = new Array(6) const result = new Array(6)
while (index < 42) { while (index < 42) {
result[resIndex++] = arr.slice(index, index += 7) result[resIndex++] = arr.slice(index, (index += 7))
} }
this.dates = result this.dates = result
}, },
getDateClasses (cell) { getDateClasses(cell) {
const classes = [] const classes = []
const cellTime = new Date(cell.date).setHours(0, 0, 0, 0) const cellTime = new Date(cell.date).setHours(0, 0, 0, 0)
const cellEndTime = new Date(cell.date).setHours(23, 59, 59, 999) const cellEndTime = new Date(cell.date).setHours(23, 59, 59, 999)
const curTime = this.value ? new Date(this.value).setHours(0, 0, 0, 0) : 0 const curTime = this.value ? new Date(this.value).setHours(0, 0, 0, 0) : 0
const startTime = this.startAt ? new Date(this.startAt).setHours(0, 0, 0, 0) : 0 const startTime = this.startAt
? new Date(this.startAt).setHours(0, 0, 0, 0)
: 0
const endTime = this.endAt ? new Date(this.endAt).setHours(0, 0, 0, 0) : 0 const endTime = this.endAt ? new Date(this.endAt).setHours(0, 0, 0, 0) : 0
const today = new Date().setHours(0, 0, 0, 0) const today = new Date().setHours(0, 0, 0, 0)
if (this.$parent.disabledDays.some(v => +new Date(v) === +cell.date) || if (
(this.$parent.notBefore !== '' && cellEndTime < (new Date(this.$parent.notBefore)).getTime()) || this.$parent.disabledDays.some(v => +new Date(v) === +cell.date) ||
(this.$parent.notAfter !== '' && cellTime > (new Date(this.$parent.notAfter)).getTime())) { (this.$parent.notBefore !== '' &&
cellEndTime < new Date(this.$parent.notBefore).getTime()) ||
(this.$parent.notAfter !== '' &&
cellTime > new Date(this.$parent.notAfter).getTime())
) {
return 'disabled' return 'disabled'
} }
@@ -207,7 +225,7 @@ export default {
} }
return classes.join(' ') return classes.join(' ')
}, },
getTimeClasses (value, index) { getTimeClasses(value, index) {
let curValue let curValue
let cellTime let cellTime
const startTime = this.startAt ? new Date(this.startAt) : 0 const startTime = this.startAt ? new Date(this.startAt) : 0
@@ -228,9 +246,11 @@ export default {
break break
} }
if ( if (
this.$parent.notBefore !== '' && cellTime < new Date(this.$parent.notBefore).getTime() || (this.$parent.notBefore !== '' &&
this.$parent.notAfter !== '' && cellTime > new Date(this.$parent.notAfter).getTime() cellTime < new Date(this.$parent.notBefore).getTime()) ||
) { (this.$parent.notAfter !== '' &&
cellTime > new Date(this.$parent.notAfter).getTime())
) {
return 'disabled' return 'disabled'
} }
@@ -247,14 +267,14 @@ export default {
} }
return classes.join(' ') return classes.join(' ')
}, },
showMonths () { showMonths() {
if (this.currentPanel === 'months') { if (this.currentPanel === 'months') {
this.currentPanel = 'date' this.currentPanel = 'date'
} else { } else {
this.currentPanel = 'months' this.currentPanel = 'months'
} }
}, },
showYears () { showYears() {
// 当前年代 // 当前年代
if (this.currentPanel === 'years') { if (this.currentPanel === 'years') {
this.currentPanel = 'date' this.currentPanel = 'date'
@@ -269,7 +289,7 @@ export default {
} }
}, },
// 前进或后退一年 // 前进或后退一年
changeYear (flag) { changeYear(flag) {
if (this.currentPanel === 'years') { if (this.currentPanel === 'years') {
this.years = this.years.map(v => v + flag * 10) this.years = this.years.map(v => v + flag * 10)
} else { } else {
@@ -278,12 +298,12 @@ export default {
this.now = now this.now = now
} }
}, },
changeMonth (flag) { changeMonth(flag) {
const now = new Date(this.now) const now = new Date(this.now)
now.setMonth(now.getMonth() + flag, 1) now.setMonth(now.getMonth() + flag, 1)
this.now = now this.now = now
}, },
selectDate (cell) { selectDate(cell) {
const classes = this.getDateClasses(cell) const classes = this.getDateClasses(cell)
if (classes.indexOf('disabled') !== -1) { if (classes.indexOf('disabled') !== -1) {
return return
@@ -293,37 +313,47 @@ export default {
if (this.$parent.type === 'datetime') { if (this.$parent.type === 'datetime') {
// 保留时分秒 // 保留时分秒
if (this.value instanceof Date) { if (this.value instanceof Date) {
date.setHours(this.value.getHours(), this.value.getMinutes(), this.value.getSeconds()) date.setHours(
this.value.getHours(),
this.value.getMinutes(),
this.value.getSeconds()
)
} }
if (this.startAt && date.getTime() < new Date(this.startAt).getTime()){ if (this.startAt && date.getTime() < new Date(this.startAt).getTime()) {
date = new Date(this.startAt) date = new Date(this.startAt)
} else if (this.endAt && date.getTime() > new Date(this.endAt).getTime()) { } else if (
this.endAt &&
date.getTime() > new Date(this.endAt).getTime()
) {
date = new Date(this.endAt) date = new Date(this.endAt)
} }
this.currentPanel = 'time' this.currentPanel = 'time'
this.$nextTick(() => { this.$nextTick(() => {
Array.prototype.forEach.call(this.$el.querySelectorAll('.cur-time'), function (el) { Array.prototype.forEach.call(
el.scrollIntoView() this.$el.querySelectorAll('.cur-time'),
}) function(el) {
el.scrollIntoView()
}
)
}) })
} }
this.now = date this.now = date
this.$emit('input', date) this.$emit('input', date)
this.$emit('select') this.$emit('select')
}, },
selectYear (year) { selectYear(year) {
const now = new Date(this.now) const now = new Date(this.now)
now.setFullYear(year) now.setFullYear(year)
this.now = now this.now = now
this.currentPanel = 'months' this.currentPanel = 'months'
}, },
selectMonth (month) { selectMonth(month) {
const now = new Date(this.now) const now = new Date(this.now)
now.setMonth(month) now.setMonth(month)
this.now = now this.now = now
this.currentPanel = 'date' this.currentPanel = 'date'
}, },
selectTime (value, index) { selectTime(value, index) {
const classes = this.getTimeClasses(value, index) const classes = this.getTimeClasses(value, index)
if (classes.indexOf('disabled') !== -1) { if (classes.indexOf('disabled') !== -1) {
return return
@@ -344,119 +374,112 @@ export default {
} }
</script> </script>
<style scoped> <style lang="scss">
.calendar { .mx-calendar {
float: left; float: left;
width: 100%; width: 100%;
padding: 6px 12px; padding: 6px 12px;
a {
color: inherit;
text-decoration: none;
cursor: pointer;
}
} }
.mx-calendar-header {
.calendar * {
box-sizing: border-box;
}
.calendar a {
color: inherit;
text-decoration: none;
cursor: pointer;
}
.calendar-header {
line-height: 34px; line-height: 34px;
text-align: center; text-align: center;
& > a:hover {
color: #1284e7;
}
} }
.calendar__next-icon, .mx-calendar__next-icon,
.calendar__prev-icon { .mx-calendar__prev-icon {
font-size: 20px; font-size: 20px;
padding: 0 6px; padding: 0 6px;
} }
.calendar-header>a:hover { .mx-calendar__prev-icon {
color: #1284e7;
}
.calendar__prev-icon {
float: left; float: left;
} }
.calendar__next-icon { .mx-calendar__next-icon {
float: right; float: right;
} }
.calendar-table { .mx-calendar-table {
width: 100%; width: 100%;
font-size: 12px; font-size: 12px;
table-layout: fixed; table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
border-spacing: 0; border-spacing: 0;
td {
cursor: pointer;
}
.today {
color: #20a0ff;
}
.lastMonth,
.nextMonth {
color: #ddd;
}
} }
.calendar-table td, .mx-calendar-table td,
.calendar-table th { .mx-calendar-table th {
width: 32px; width: 32px;
height: 32px; height: 32px;
text-align: center; text-align: center;
} }
.calendar-table td { .mx-calendar-table td {
cursor: pointer; cursor: pointer;
} }
.calendar-table td.inrange, .mx-calendar-table td.inrange,
.calendar-table td:hover, .mx-calendar-table td:hover,
.calendar-year>a:hover, .mx-calendar-year > a:hover,
.calendar-month>a:hover { .mx-calendar-month > a:hover {
background-color: #eaf8fe; background-color: #eaf8fe;
} }
.calendar-table td.current, .mx-calendar-table td.current,
.calendar-year>a.current, .mx-calendar-year > a.current,
.calendar-month>a.current { .mx-calendar-month > a.current {
color: #fff; color: #fff;
background-color: #1284e7; background-color: #1284e7;
} }
.calendar-table td.disabled { .mx-calendar-table td.disabled {
cursor: not-allowed; cursor: not-allowed;
color: #ccc; color: #ccc;
background-color: #f3f3f3; background-color: #f3f3f3;
} }
.lastMonth, .mx-calendar-year,
.nextMonth { .mx-calendar-month,
color: #ddd; .mx-calendar-time {
}
.today {
color: #20a0ff;
}
.calendar-year,
.calendar-month,
.calendar-time {
width: 100%; width: 100%;
height: 224px; height: 224px;
padding: 7px 0; padding: 7px 0;
text-align: center; text-align: center;
} }
.calendar-year>a { .mx-calendar-year > a {
display: inline-block; display: inline-block;
width: 40%; width: 40%;
margin: 1px 5%; margin: 1px 5%;
line-height: 40px; line-height: 40px;
} }
.calendar-month>a { .mx-calendar-month > a {
display: inline-block; display: inline-block;
width: 30%; width: 30%;
line-height: 40px; line-height: 40px;
margin: 8px 1.5%; margin: 8px 1.5%;
} }
.mx-time-list-wrapper {
.time-list-wrapper {
display: inline-block; display: inline-block;
width: 50%; width: 50%;
height: 100%; height: 100%;
@@ -466,57 +489,49 @@ export default {
overflow-y: auto; overflow-y: auto;
} }
.time-list-wrapper::-webkit-scrollbar { .mx-time-list-wrapper::-webkit-scrollbar {
width: 8px; width: 8px;
height: 8px; height: 8px;
} }
/* 滚动条滑块 */ /* 滚动条滑块 */
.time-list-wrapper::-webkit-scrollbar-thumb { .mx-time-list-wrapper::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.05); background-color: rgba(0, 0, 0, 0.05);
border-radius: 10px; border-radius: 10px;
box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.1); box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.1);
} }
.time-list-wrapper:hover::-webkit-scrollbar-thumb { .mx-time-list-wrapper:hover::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
} }
.mx-time-list-wrapper:first-child {
.time-list-wrapper:first-child {
border-left: 0; border-left: 0;
} }
.time-list { .mx-time-list {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
text-align: center; text-align: center;
} }
.time-item { .mx-time-item {
width: 100%; width: 100%;
font-size: 12px; font-size: 12px;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
cursor: pointer; cursor: pointer;
} }
.time-item:hover { .mx-time-item:hover {
background-color: #eaf8fe; background-color: #eaf8fe;
} }
.time-item.cur-time { .mx-time-item.cur-time {
color: #fff; color: #fff;
background-color: #1284e7; background-color: #1284e7;
} }
.time-item.disabled { .mx-time-item.disabled {
cursor: not-allowed; cursor: not-allowed;
color: #ccc; color: #ccc;
background-color: #f3f3f3; background-color: #f3f3f3;
} }
/* .time-hint {
position: sticky;
top: 0px;
line-height: 30px;
color: #ccc;
background: #fff;
} */
</style> </style>
+141 -115
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="datepicker" <div class="mx-datepicker"
:style="{'width': width + 'px','min-width':range ? (type === 'datetime' ? '320px' : '210px') : '140px'}" :style="{'width': width + 'px','min-width':range ? (type === 'datetime' ? '320px' : '210px') : '140px'}"
v-clickoutside="closePopup"> v-clickoutside="closePopup">
<input readonly <input readonly
@@ -9,12 +9,12 @@
ref="input" ref="input"
@click="togglePopup" @click="togglePopup"
@mousedown="$event.preventDefault()"> @mousedown="$event.preventDefault()">
<i class="input-icon" <i class="mx-input-icon"
:class="showCloseIcon ? 'input-icon__close' : 'input-icon__calendar'" :class="showCloseIcon ? 'mx-input-icon__close' : 'mx-input-icon__calendar'"
@mouseenter="hoverIcon" @mouseenter="hoverIcon"
@mouseleave="hoverIcon" @mouseleave="hoverIcon"
@click="clickIcon" ></i> @click="clickIcon" ></i>
<div class="datepicker-popup" <div class="mx-datepicker-popup"
:class="{'range':range}" :class="{'range':range}"
:style="position" :style="position"
ref="calendar" ref="calendar"
@@ -26,7 +26,7 @@
@select="selectDate" @select="selectDate"
:show="showPopup"></calendar-panel> :show="showPopup"></calendar-panel>
<div v-else style="overflow:hidden" > <div v-else style="overflow:hidden" >
<div class="datepicker-top" v-if="ranges.length"> <div class="mx-datepicker-top" v-if="ranges.length">
<span v-for="range in ranges" @click="selectRange(range)">{{range.text}}</span> <span v-for="range in ranges" @click="selectRange(range)">{{range.text}}</span>
</div> </div>
<calendar-panel style="width:50%;box-shadow:1px 0 rgba(0, 0, 0, .1)" <calendar-panel style="width:50%;box-shadow:1px 0 rgba(0, 0, 0, .1)"
@@ -40,8 +40,8 @@
@select="selectDate" @select="selectDate"
:show="showPopup"></calendar-panel> :show="showPopup"></calendar-panel>
</div> </div>
<div class="datepicker-footer" v-if="confirm"> <div class="mx-datepicker-footer" v-if="confirm">
<button type="button" class="datepicker-btn datepicker-btn-confirm" @click="confirmDate"> {{ confirmText }}</button> <button type="button" class="mx-datepicker-btn mx-datepicker-btn-confirm" @click="confirmDate"> {{ confirmText }}</button>
</div> </div>
</div> </div>
</div> </div>
@@ -52,6 +52,7 @@ import CalendarPanel from './calendar-panel.vue'
import Languages from './languages.js' import Languages from './languages.js'
export default { export default {
name: 'DatePicker',
components: { CalendarPanel }, components: { CalendarPanel },
props: { props: {
value: null, value: null,
@@ -65,7 +66,7 @@ export default {
}, },
type: { type: {
type: String, type: String,
default: 'date' // ['date', 'datetime'] default: 'date' // ['date', 'datetime']
}, },
width: { width: {
type: [String, Number], type: [String, Number],
@@ -82,7 +83,9 @@ export default {
}, },
disabledDays: { disabledDays: {
type: Array, type: Array,
default: function () { return [] } default: function() {
return []
}
}, },
notBefore: { notBefore: {
default: '' default: ''
@@ -106,69 +109,78 @@ export default {
}, },
inputClass: { inputClass: {
type: String, type: String,
default: 'input' default: 'mx-input'
}, },
confirmText: { confirmText: {
type: String, type: String,
default: 'OK' default: 'OK'
} }
}, },
data () { data() {
return { return {
showPopup: false, showPopup: false,
showCloseIcon: false, showCloseIcon: false,
currentValue: this.value, currentValue: this.value,
position: null, position: null,
ranges: [] // 快捷选项 ranges: [] // 快捷选项
} }
}, },
watch: { watch: {
value: { value: {
handler (val) { handler(val) {
if (!this.range) { if (!this.range) {
this.currentValue = this.isValidDate(val) ? val : undefined this.currentValue = this.isValidDate(val) ? val : undefined
} else { } else {
this.currentValue = this.isValidRange(val) ? val.slice(0, 2) : [undefined, undefined] this.currentValue = this.isValidRange(val)
? val.slice(0, 2)
: [undefined, undefined]
} }
}, },
immediate: true immediate: true
}, },
showPopup (val) { showPopup(val) {
if (val) { if (val) {
this.$nextTick(this.displayPopup) this.$nextTick(this.displayPopup)
} }
} }
}, },
computed: { computed: {
translation () { translation() {
return Languages[this.lang] || Languages['en'] return Languages[this.lang] || Languages['en']
}, },
innerPlaceholder () { innerPlaceholder() {
return this.placeholder || (this.range ? this.translation.placeholder.dateRange : this.translation.placeholder.date) return (
this.placeholder ||
(this.range
? this.translation.placeholder.dateRange
: this.translation.placeholder.date)
)
}, },
text () { text() {
if (!this.range && this.isValidDate(this.value)) { if (!this.range && this.isValidDate(this.value)) {
return this.stringify(this.value) return this.stringify(this.value)
} }
if (this.range && this.isValidRange(this.value)) { if (this.range && this.isValidRange(this.value)) {
return this.stringify(this.value[0]) + ' ~ ' + this.stringify(this.value[1]) return (
this.stringify(this.value[0]) + ' ~ ' + this.stringify(this.value[1])
)
} }
return '' return ''
} }
}, },
methods: { methods: {
updateDate () { updateDate() {
const val = this.currentValue const val = this.currentValue
if ((!this.range && val) || (this.range && val[0] && val[1])) { if ((!this.range && val) || (this.range && val[0] && val[1])) {
this.$emit('input', val) this.$emit('input', val)
} }
}, },
confirmDate () { confirmDate() {
this.updateDate() this.updateDate()
this.closePopup() this.closePopup()
this.$emit('confirm', this.currentValue) this.$emit('confirm', this.currentValue)
}, },
selectDate () { selectDate() {
if (!this.confirm) { if (!this.confirm) {
this.updateDate() this.updateDate()
if (this.type === 'date' && !this.range) { if (this.type === 'date' && !this.range) {
@@ -176,10 +188,10 @@ export default {
} }
} }
}, },
closePopup () { closePopup() {
this.showPopup = false this.showPopup = false
}, },
togglePopup () { togglePopup() {
if (this.showPopup) { if (this.showPopup) {
this.$refs.input.blur() this.$refs.input.blur()
this.showPopup = false this.showPopup = false
@@ -188,7 +200,7 @@ export default {
this.showPopup = true this.showPopup = true
} }
}, },
hoverIcon (e) { hoverIcon(e) {
if (e.type === 'mouseenter' && this.text) { if (e.type === 'mouseenter' && this.text) {
this.showCloseIcon = true this.showCloseIcon = true
} }
@@ -196,14 +208,14 @@ export default {
this.showCloseIcon = false this.showCloseIcon = false
} }
}, },
clickIcon () { clickIcon() {
if (this.showCloseIcon) { if (this.showCloseIcon) {
this.$emit('input', '') this.$emit('input', '')
} else { } else {
this.togglePopup() this.togglePopup()
} }
}, },
formatDate (date, fmt) { formatDate(date, fmt) {
const map = { const map = {
'M+': date.getMonth() + 1, // 月份 'M+': date.getMonth() + 1, // 月份
'[Dd]+': date.getDate(), // 日 '[Dd]+': date.getDate(), // 日
@@ -211,55 +223,62 @@ export default {
'm+': date.getMinutes(), // 分 'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒 's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
'S': date.getMilliseconds() // 毫秒 S: date.getMilliseconds() // 毫秒
} }
let str = fmt.replace(/[Yy]+/g, function (str) { let str = fmt.replace(/[Yy]+/g, function(str) {
return ('' + date.getFullYear()).slice(4 - str.length) return ('' + date.getFullYear()).slice(4 - str.length)
}) })
Object.keys(map).forEach((key) => { Object.keys(map).forEach(key => {
str = str.replace(new RegExp(key), function (str) { str = str.replace(new RegExp(key), function(str) {
const value = '' + map[key] const value = '' + map[key]
return str.length === 1 ? value : ('00' + value).slice(value.length) return str.length === 1 ? value : ('00' + value).slice(value.length)
}) })
}) })
return str return str
}, },
stringify (date) { stringify(date) {
return this.formatDate(new Date(date), this.format) return this.formatDate(new Date(date), this.format)
}, },
isValidDate (date) { isValidDate(date) {
return !!new Date(date).getTime() return !!new Date(date).getTime()
}, },
isValidRange (date) { isValidRange(date) {
return Array.isArray(date) && return (
Array.isArray(date) &&
date.length === 2 && date.length === 2 &&
this.isValidDate(date[0]) && this.isValidDate(date[0]) &&
this.isValidDate(date[1]) this.isValidDate(date[1])
)
}, },
selectRange (range) { selectRange(range) {
this.$emit('input', [range.start, range.end]) this.$emit('input', [range.start, range.end])
}, },
initRanges () { initRanges() {
if (Array.isArray(this.shortcuts)) { if (Array.isArray(this.shortcuts)) {
this.ranges = this.shortcuts this.ranges = this.shortcuts
} else if (this.shortcuts) { } else if (this.shortcuts) {
this.ranges = [{ this.ranges = [
text: '未来7天', {
start: new Date(), text: '未来7天',
end: new Date(Date.now() + 3600 * 1000 * 24 * 7) start: new Date(),
}, { end: new Date(Date.now() + 3600 * 1000 * 24 * 7)
text: '未来30天', },
start: new Date(), {
end: new Date(Date.now() + 3600 * 1000 * 24 * 30) text: '未来30天',
}, { start: new Date(),
text: '最近7天', end: new Date(Date.now() + 3600 * 1000 * 24 * 30)
start: new Date(Date.now() - 3600 * 1000 * 24 * 7), },
end: new Date() {
}, { text: '最近7天',
text: '最近30天', start: new Date(Date.now() - 3600 * 1000 * 24 * 7),
start: new Date(Date.now() - 3600 * 1000 * 24 * 30), end: new Date()
end: new Date() },
}] {
text: '最近30天',
start: new Date(Date.now() - 3600 * 1000 * 24 * 30),
end: new Date()
}
]
this.ranges.forEach((v, i) => { this.ranges.forEach((v, i) => {
v.text = this.translation.pickers[i] v.text = this.translation.pickers[i]
}) })
@@ -267,20 +286,26 @@ export default {
this.ranges = [] this.ranges = []
} }
}, },
displayPopup () { displayPopup() {
const dw = document.documentElement.clientWidth const dw = document.documentElement.clientWidth
const dh = document.documentElement.clientHeight const dh = document.documentElement.clientHeight
const InputRect = this.$el.getBoundingClientRect() const InputRect = this.$el.getBoundingClientRect()
const PopupRect = this.$refs.calendar.getBoundingClientRect() const PopupRect = this.$refs.calendar.getBoundingClientRect()
this.position = {} this.position = {}
if (dw - InputRect.left < PopupRect.width && InputRect.right < PopupRect.width) { if (
dw - InputRect.left < PopupRect.width &&
InputRect.right < PopupRect.width
) {
this.position.left = 1 - InputRect.left + 'px' this.position.left = 1 - InputRect.left + 'px'
} else if (InputRect.left + InputRect.width / 2 <= dw / 2) { } else if (InputRect.left + InputRect.width / 2 <= dw / 2) {
this.position.left = 0 this.position.left = 0
} else { } else {
this.position.right = 0 this.position.right = 0
} }
if (InputRect.top <= PopupRect.height + 1 && dh - InputRect.bottom <= PopupRect.height + 1) { if (
InputRect.top <= PopupRect.height + 1 &&
dh - InputRect.bottom <= PopupRect.height + 1
) {
this.position.top = dh - InputRect.top - PopupRect.height - 1 + 'px' this.position.top = dh - InputRect.top - PopupRect.height - 1 + 'px'
} else if (InputRect.top + InputRect.height / 2 <= dh / 2) { } else if (InputRect.top + InputRect.height / 2 <= dh / 2) {
this.position.top = '100%' this.position.top = '100%'
@@ -289,20 +314,24 @@ export default {
} }
} }
}, },
created () { created() {
this.initRanges() this.initRanges()
}, },
directives: { directives: {
clickoutside: { clickoutside: {
bind (el, binding, vnode) { bind(el, binding, vnode) {
el['@clickoutside'] = (e) => { el['@clickoutside'] = e => {
if (!el.contains(e.target) && binding.expression && vnode.context[binding.expression]) { if (
!el.contains(e.target) &&
binding.expression &&
vnode.context[binding.expression]
) {
binding.value() binding.value()
} }
} }
document.addEventListener('click', el['@clickoutside'], true) document.addEventListener('click', el['@clickoutside'], true)
}, },
unbind (el) { unbind(el) {
document.removeEventListener('click', el['@clickoutside'], true) document.removeEventListener('click', el['@clickoutside'], true)
} }
} }
@@ -311,35 +340,32 @@ export default {
</script> </script>
<style scoped> <style lang="scss">
.datepicker { .mx-datepicker {
position: relative; position: relative;
display: inline-block; display: inline-block;
color:#73879c; color: #73879c;
font: 14px/1.5 "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei", sans-serif; font: 14px/1.5 'Helvetica Neue', Helvetica, Arial, 'Microsoft Yahei',
sans-serif;
* {
box-sizing: border-box;
}
} }
.mx-datepicker-popup {
.datepicker * {
box-sizing: border-box;
}
.datepicker-popup {
position: absolute; position: absolute;
width: 250px; width: 250px;
margin-top: 1px; margin-top: 1px;
margin-bottom: 1px; margin-bottom: 1px;
border: 1px solid #d9d9d9; border: 1px solid #d9d9d9;
background-color: #fff; background-color: #fff;
box-shadow: 0 6px 12px rgba(0, 0, 0, .175); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
z-index: 1000; z-index: 1000;
&.range {
width: 496px;
}
} }
.range { .mx-input {
width: 496px;
}
.input {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
height: 34px; height: 34px;
@@ -350,10 +376,10 @@ export default {
background-color: #fff; background-color: #fff;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; border-radius: 4px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
} }
.input-icon { .mx-input-icon {
top: 0; top: 0;
right: 0; right: 0;
position: absolute; position: absolute;
@@ -362,51 +388,51 @@ export default {
color: #888; color: #888;
text-align: center; text-align: center;
font-style: normal; font-style: normal;
&::after {
content: '';
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
} }
.input-icon::after{
content:''; .mx-input-icon__calendar {
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
.input-icon__calendar{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA00lEQVQ4T72SzQ2CQBCF54UGKIES6EAswQq0BS/A3PQ0hAt0oKVQgiVYAkcuZMwSMOyCyRKNe9uf+d6b2Qf6csGtL8sy7vu+Zebn/E5EoiAIwjRNH/PzBUBEGiJqmPniAMw+YeZkFSAiJwA3j45aVT0wsxGitwOjDGDnASBVvU4OLQARRURk9e4CAcSqWn8CLHp3Ae6MXAe/B4yzUeMkz/P9ZgdFUQzFIwD/B4yKgwMTos0OtvzCHcDRJ0gAzlmW1VYSq6oKu66LfQBTjC2AT+Hamxcml5IRpPq3VQAAAABJRU5ErkJggg==); background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA00lEQVQ4T72SzQ2CQBCF54UGKIES6EAswQq0BS/A3PQ0hAt0oKVQgiVYAkcuZMwSMOyCyRKNe9uf+d6b2Qf6csGtL8sy7vu+Zebn/E5EoiAIwjRNH/PzBUBEGiJqmPniAMw+YeZkFSAiJwA3j45aVT0wsxGitwOjDGDnASBVvU4OLQARRURk9e4CAcSqWn8CLHp3Ae6MXAe/B4yzUeMkz/P9ZgdFUQzFIwD/B4yKgwMTos0OtvzCHcDRJ0gAzlmW1VYSq6oKu66LfQBTjC2AT+Hamxcml5IRpPq3VQAAAABJRU5ErkJggg==);
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.input-icon__close::before { .mx-input-icon__close::before {
content: '\2716'; content: '\2716';
vertical-align: middle; vertical-align: middle;
} }
.datepicker-top { .mx-datepicker-top {
text-align: left;
padding: 0 12px; padding: 0 12px;
line-height: 34px; line-height: 34px;
border-bottom: 1px solid rgba(0, 0, 0, .05); border-bottom: 1px solid rgba(0, 0, 0, 0.05);
& > span {
white-space: nowrap;
cursor: pointer;
&:hover {
color: #1284e7;
}
&:after {
content: '|';
margin: 0 10px;
color: #48576a;
}
}
} }
.datepicker-top>span { .mx-datepicker-footer {
white-space: nowrap;
cursor: pointer;
}
.datepicker-top>span:hover {
color: #1284e7;
}
.datepicker-top>span:after {
content: "|";
margin: 0 10px;
color: #48576a;
}
.datepicker-footer {
padding: 4px; padding: 4px;
clear: both; clear: both;
text-align: right; text-align: right;
border-top: 1px solid rgba(0, 0, 0, .05); border-top: 1px solid rgba(0, 0, 0, 0.05);
} }
.datepicker-btn { .mx-datepicker-btn {
font-size: 12px; font-size: 12px;
line-height: 1; line-height: 1;
padding: 7px 15px; padding: 7px 15px;
@@ -417,12 +443,12 @@ export default {
border: none; border: none;
border-radius: 3px; border-radius: 3px;
} }
.datepicker-btn-confirm { .mx-datepicker-btn-confirm {
border: 1px solid rgba(0, 0, 0, 0.1); border: 1px solid rgba(0, 0, 0, 0.1);
color: #73879c; color: #73879c;
} &:hover {
.datepicker-btn-confirm:hover { color: #1284e7;
color: #1284e7; border-color: #1284e7;
border-color: #1284e7; }
} }
</style> </style>
+1 -1
View File
@@ -67,7 +67,7 @@
</template> </template>
<script> <script>
import DatePicker from '../datepicker/index.vue' import DatePicker from '../dist/build'
export default { export default {
name: 'app', name: 'app',
+1
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -0,0 +1,7 @@
import DatePicker from './datepicker/index.vue'
DatePicker.install = function (Vue) {
Vue.component(DatePicker.name, DatePicker)
}
export default DatePicker
+8135
View File
File diff suppressed because it is too large Load Diff
+21 -6
View File
@@ -1,8 +1,8 @@
{ {
"name": "vue2-datepicker", "name": "vue2-datepicker",
"description": "A Datepicker Component For Vue2", "description": "A Datepicker Component For Vue2",
"main": "datepicker/index.vue", "main": "dist/build.js",
"version": "1.6.3", "version": "1.7.0",
"scripts": { "scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules" "build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
@@ -25,13 +25,28 @@
"vue": "^2.2.1" "vue": "^2.2.1"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^7.1.6",
"babel-core": "^6.0.0", "babel-core": "^6.0.0",
"babel-loader": "^6.0.0", "babel-eslint": "^8.0.2",
"babel-preset-latest": "^6.0.0", "babel-loader": "^7.0.0",
"cross-env": "^3.0.0", "babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.0",
"css-loader": "^0.25.0", "css-loader": "^0.25.0",
"eslint": "^4.12.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-html": "^4.0.1",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-standard": "^3.0.1",
"file-loader": "^0.9.0", "file-loader": "^0.9.0",
"vue-loader": "^11.1.4", "node-sass": "^4.7.2",
"postcss-loader": "^2.0.9",
"sass-loader": "^6.0.6",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.2.1", "vue-template-compiler": "^2.2.1",
"webpack": "^2.2.0", "webpack": "^2.2.0",
"webpack-dev-server": "^2.2.0" "webpack-dev-server": "^2.2.0"
+4 -1
View File
@@ -6,7 +6,9 @@ module.exports = {
output: { output: {
path: path.resolve(__dirname, './dist'), path: path.resolve(__dirname, './dist'),
publicPath: '/dist/', publicPath: '/dist/',
filename: 'build.js' filename: 'build.js',
library: "DatePicker",
libraryTarget: "umd"
}, },
module: { module: {
rules: [ rules: [
@@ -50,6 +52,7 @@ module.exports = {
} }
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
module.exports.entry = './index.js'
module.exports.devtool = '#source-map' module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html // http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([ module.exports.plugins = (module.exports.plugins || []).concat([