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

feat: add the prop time-select-options (#227)

This commit is contained in:
mengxiong10
2019-06-25 17:12:33 +08:00
parent e134442bc7
commit a55b4b6f95
5 changed files with 175 additions and 100 deletions
+8
View File
@@ -102,6 +102,7 @@ export default {
| disabled-days | Disable Days | `(date) => boolean` | - | | disabled-days | Disable Days | `(date) => boolean` | - |
| shortcuts | the shortcuts for the range picker | [shortcuts](#shortcuts) | true | | shortcuts | the shortcuts for the range picker | [shortcuts](#shortcuts) | true |
| time-picker-options | custom time-picker | [time-picker-options](#time-picker-options) | null | | time-picker-options | custom time-picker | [time-picker-options](#time-picker-options) | null |
| time-select-options | custom time-select | [time-select-options](#time-select-options) | null |
| minute-step | if > 0 don't show the second picker | 0 - 60 | 0 | | minute-step | if > 0 don't show the second picker | 0 - 60 | 0 |
| first-day-of-week | set the first day of week | 1 - 7 | 7 | | first-day-of-week | set the first day of week | 1 - 7 | 7 |
| input-class | the input class name | `string` | 'mx-input' | | input-class | the input class name | `string` | 'mx-input' |
@@ -151,6 +152,13 @@ custom time-picker
| {start: '00:00', step:'00:30' , end: '23:30'} | | {start: '00:00', step:'00:30' , end: '23:30'} |
| () => Array<{ label: string; values: { hours: number; minutes: number } }> | | () => Array<{ label: string; values: { hours: number; minutes: number } }> |
#### time-select-options
custom time-select for columns
| Type |
|------|
| {hours: [9, 10, 11], minutes: [10, 20], seconds: [10, 20] } |
### Events ### Events
| Name | Description | Callback Arguments | | Name | Description | Callback Arguments |
|-----------------|--------------------------------------------------------|------------------------| |-----------------|--------------------------------------------------------|------------------------|
+8
View File
@@ -102,6 +102,7 @@ export default {
| disabled-days | 自定义禁止的日期 | `(date) => boolean` | - | | disabled-days | 自定义禁止的日期 | `(date) => boolean` | - |
| shortcuts | 自定义范围选择的时候快捷选项 | [shortcuts](#shortcuts) | true | | shortcuts | 自定义范围选择的时候快捷选项 | [shortcuts](#shortcuts) | true |
| time-picker-options | 自定义时间选择的开始,结束,步进 | [time-picker-options](#time-picker-options) | null | | time-picker-options | 自定义时间选择的开始,结束,步进 | [time-picker-options](#time-picker-options) | null |
| time-select-options | 自定义时间列的选择 | [time-select-options](#time-select-options) | null |
| minute-step | 设置分钟的步进, 设置大于0不显示秒的选择(0-60) | 0 - 60 | 0 | | minute-step | 设置分钟的步进, 设置大于0不显示秒的选择(0-60) | 0 - 60 | 0 |
| first-day-of-week | 设置日历星期几开头 | 1 - 7 | 7 | | first-day-of-week | 设置日历星期几开头 | 1 - 7 | 7 |
| input-class | 自定义input元素的类名 | `string` | 'mx-input' | | input-class | 自定义input元素的类名 | `string` | 'mx-input' |
@@ -150,6 +151,13 @@ export default {
| {start: '00:00', step:'00:30' , end: '23:30'} | | {start: '00:00', step:'00:30' , end: '23:30'} |
| () => Array<{ label: string; values: { hours: number; minutes: number } }> | | () => Array<{ label: string; values: { hours: number; minutes: number } }> |
#### time-select-options
自定义时间选择列
| 可选值 |
|------|
| {hours: [9, 10, 11], minutes: [10, 20], seconds: [10, 20] } |
### 事件 ### 事件
| Name | 说明 | 回调参数 | Name | 说明 | 回调参数
|-----------------|----------------------------- |---------------- |-----------------|----------------------------- |----------------
+14 -1
View File
@@ -19,7 +19,8 @@ new Vue({
value9: '', value9: '',
value10: new Date(), value10: new Date(),
value11: new Date(), value11: new Date(),
value12: '' value12: '',
value13: ''
} }
}, },
methods: { methods: {
@@ -80,6 +81,18 @@ new Vue({
format="YYYY-MM-DD hh:mm:ss a" format="YYYY-MM-DD hh:mm:ss a"
:minute-step="10" :minute-step="10"
></date-picker>`, ></date-picker>`,
'datetime with time-select-options': `
<date-picker
v-model="value13"
lang="en"
type="datetime"
format="YYYY-MM-DD hh:mm:ss a"
:time-select-options="{
hours: [9, 10, 11, 12, 13, 14, 15, 16],
minutes: [0, 10,20,30,40,50],
seconds: []
}"
></date-picker>`,
'datetime range': ` 'datetime range': `
<date-picker <date-picker
v-model="value5" v-model="value5"
+72 -44
View File
@@ -1,38 +1,22 @@
<template> <template>
<div class="mx-calendar" <div class="mx-calendar" :class="'mx-calendar-panel-' + panel.toLowerCase()">
:class="'mx-calendar-panel-' + panel.toLowerCase()">
<div class="mx-calendar-header"> <div class="mx-calendar-header">
<a <a v-show="panel !== 'TIME'" class="mx-icon-last-year" @click="handleIconYear(-1)">&#171;</a>
v-show="panel !== 'TIME'" <a v-show="panel === 'DATE'" class="mx-icon-last-month" @click="handleIconMonth(-1)">&#8249;</a>
class="mx-icon-last-year" <a v-show="panel !== 'TIME'" class="mx-icon-next-year" @click="handleIconYear(1)">&#187;</a>
@click="handleIconYear(-1)">&#171;</a> <a v-show="panel === 'DATE'" class="mx-icon-next-month" @click="handleIconMonth(1)">&#8250;</a>
<a
v-show="panel === 'DATE'"
class="mx-icon-last-month"
@click="handleIconMonth(-1)">&#8249;</a>
<a
v-show="panel !== 'TIME'"
class="mx-icon-next-year"
@click="handleIconYear(1)">&#187;</a>
<a
v-show="panel === 'DATE'"
class="mx-icon-next-month"
@click="handleIconMonth(1)">&#8250;</a>
<a <a
v-show="panel === 'DATE'" v-show="panel === 'DATE'"
class="mx-current-month" class="mx-current-month"
@click="handleBtnMonth">{{months[calendarMonth]}}</a> @click="handleBtnMonth"
>{{months[calendarMonth]}}</a>
<a <a
v-show="panel === 'DATE' || panel === 'MONTH'" v-show="panel === 'DATE' || panel === 'MONTH'"
class="mx-current-year" class="mx-current-year"
@click="handleBtnYear">{{calendarYear}}</a> @click="handleBtnYear"
<a >{{calendarYear}}</a>
v-show="panel === 'YEAR'" <a v-show="panel === 'YEAR'" class="mx-current-year">{{yearHeader}}</a>
class="mx-current-year">{{yearHeader}}</a> <a v-show="panel === 'TIME'" class="mx-time-header" @click="handleTimeHeader">{{timeHeader}}</a>
<a
v-show="panel === 'TIME'"
class="mx-time-header"
@click="handleTimeHeader">{{timeHeader}}</a>
</div> </div>
<div class="mx-calendar-content"> <div class="mx-calendar-content">
<panel-date <panel-date
@@ -45,28 +29,33 @@
:end-at="endAt" :end-at="endAt"
:first-day-of-week="firstDayOfWeek" :first-day-of-week="firstDayOfWeek"
:disabled-date="isDisabledDate" :disabled-date="isDisabledDate"
@select="selectDate"/> @select="selectDate"
/>
<panel-year <panel-year
v-show="panel === 'YEAR'" v-show="panel === 'YEAR'"
:value="value" :value="value"
:disabled-year="isDisabledYear" :disabled-year="isDisabledYear"
:first-year="firstYear" :first-year="firstYear"
@select="selectYear" /> @select="selectYear"
/>
<panel-month <panel-month
v-show="panel === 'MONTH'" v-show="panel === 'MONTH'"
:value="value" :value="value"
:disabled-month="isDisabledMonth" :disabled-month="isDisabledMonth"
:calendar-year="calendarYear" :calendar-year="calendarYear"
@select="selectMonth" /> @select="selectMonth"
/>
<panel-time <panel-time
v-show="panel === 'TIME'" v-show="panel === 'TIME'"
:minute-step="minuteStep" :minute-step="minuteStep"
:time-picker-options="timePickerOptions" :time-picker-options="timePickerOptions"
:time-select-options="timeSelectOptions"
:value="value" :value="value"
:disabled-time="isDisabledTime" :disabled-time="isDisabledTime"
:time-type="timeType" :time-type="timeType"
@select="selectTime" @select="selectTime"
@pick="pickTime" /> @pick="pickTime"
/>
</div> </div>
</div> </div>
</template> </template>
@@ -141,6 +130,12 @@ export default {
default: 0, default: 0,
validator: val => val >= 0 && val <= 60 validator: val => val >= 0 && val <= 60
}, },
timeSelectOptions: {
type: Object,
default () {
return null
}
},
timePickerOptions: { timePickerOptions: {
type: [Object, Function], type: [Object, Function],
default () { default () {
@@ -242,16 +237,21 @@ export default {
} }
}, },
getNow (value) { getNow (value) {
return value ? new Date(value) : ( return value
(this.defaultValue && isValidDate(this.defaultValue)) ? new Date(this.defaultValue) : new Date() ? new Date(value)
) : this.defaultValue && isValidDate(this.defaultValue)
? new Date(this.defaultValue)
: new Date()
}, },
// 根据value更新日历 // 根据value更新日历
updateNow (value) { updateNow (value) {
const oldNow = this.now const oldNow = this.now
this.now = this.getNow(value) this.now = this.getNow(value)
if (this.visible && this.now !== oldNow) { if (this.visible && this.now !== oldNow) {
this.dispatch('DatePicker', 'calendar-change', [new Date(this.now), new Date(oldNow)]) this.dispatch('DatePicker', 'calendar-change', [
new Date(this.now),
new Date(oldNow)
])
} }
}, },
getCriticalTime (value) { getCriticalTime (value) {
@@ -272,15 +272,19 @@ export default {
if (startAt === undefined) { if (startAt === undefined) {
startAt = this.startAt startAt = this.startAt
} }
return (this.notBeforeTime && time < this.notBeforeTime) || return (
(this.notBeforeTime && time < this.notBeforeTime) ||
(startAt && time < this.getCriticalTime(startAt)) (startAt && time < this.getCriticalTime(startAt))
)
}, },
inAfter (time, endAt) { inAfter (time, endAt) {
if (endAt === undefined) { if (endAt === undefined) {
endAt = this.endAt endAt = this.endAt
} }
return (this.notAfterTime && time > this.notAfterTime) || return (
(this.notAfterTime && time > this.notAfterTime) ||
(endAt && time > this.getCriticalTime(endAt)) (endAt && time > this.getCriticalTime(endAt))
)
}, },
inDisabledDays (time) { inDisabledDays (time) {
if (Array.isArray(this.disabledDays)) { if (Array.isArray(this.disabledDays)) {
@@ -293,21 +297,37 @@ export default {
isDisabledYear (year) { isDisabledYear (year) {
const time = new Date(year, 0).getTime() const time = new Date(year, 0).getTime()
const maxTime = new Date(year + 1, 0).getTime() - 1 const maxTime = new Date(year + 1, 0).getTime() - 1
return this.inBefore(maxTime) || this.inAfter(time) || (this.type === 'year' && this.inDisabledDays(time)) return (
this.inBefore(maxTime) ||
this.inAfter(time) ||
(this.type === 'year' && this.inDisabledDays(time))
)
}, },
isDisabledMonth (month) { isDisabledMonth (month) {
const time = new Date(this.calendarYear, month).getTime() const time = new Date(this.calendarYear, month).getTime()
const maxTime = new Date(this.calendarYear, month + 1).getTime() - 1 const maxTime = new Date(this.calendarYear, month + 1).getTime() - 1
return this.inBefore(maxTime) || this.inAfter(time) || (this.type === 'month' && this.inDisabledDays(time)) return (
this.inBefore(maxTime) ||
this.inAfter(time) ||
(this.type === 'month' && this.inDisabledDays(time))
)
}, },
isDisabledDate (date) { isDisabledDate (date) {
const time = new Date(date).getTime() const time = new Date(date).getTime()
const maxTime = new Date(date).setHours(23, 59, 59, 999) const maxTime = new Date(date).setHours(23, 59, 59, 999)
return this.inBefore(maxTime) || this.inAfter(time) || this.inDisabledDays(time) return (
this.inBefore(maxTime) ||
this.inAfter(time) ||
this.inDisabledDays(time)
)
}, },
isDisabledTime (date, startAt, endAt) { isDisabledTime (date, startAt, endAt) {
const time = new Date(date).getTime() const time = new Date(date).getTime()
return this.inBefore(time, startAt) || this.inAfter(time, endAt) || this.inDisabledDays(time) return (
this.inBefore(time, startAt) ||
this.inAfter(time, endAt) ||
this.inDisabledDays(time)
)
}, },
selectDate (date) { selectDate (date) {
if (this.type === 'datetime') { if (this.type === 'datetime') {
@@ -321,10 +341,16 @@ export default {
} }
if (this.isDisabledTime(time)) { if (this.isDisabledTime(time)) {
time.setHours(0, 0, 0, 0) time.setHours(0, 0, 0, 0)
if (this.notBefore && time.getTime() < new Date(this.notBefore).getTime()) { if (
this.notBefore &&
time.getTime() < new Date(this.notBefore).getTime()
) {
time = new Date(this.notBefore) time = new Date(this.notBefore)
} }
if (this.startAt && time.getTime() < new Date(this.startAt).getTime()) { if (
this.startAt &&
time.getTime() < new Date(this.startAt).getTime()
) {
time = new Date(this.startAt) time = new Date(this.startAt)
} }
} }
@@ -363,7 +389,9 @@ export default {
this.updateNow(new Date(this.calendarYear, month)) this.updateNow(new Date(this.calendarYear, month))
}, },
getSibling () { getSibling () {
const calendars = this.$parent.$children.filter(v => v.$options.name === this.$options.name) const calendars = this.$parent.$children.filter(
v => v.$options.name === this.$options.name
)
const index = calendars.indexOf(this) const index = calendars.indexOf(this)
const sibling = calendars[index ^ 1] const sibling = calendars[index ^ 1]
return sibling return sibling
+73 -55
View File
@@ -9,6 +9,12 @@ export default {
return null return null
} }
}, },
timeSelectOptions: {
type: Object,
default () {
return null
}
},
minuteStep: { minuteStep: {
type: Number, type: Number,
default: 0, default: 0,
@@ -50,7 +56,7 @@ export default {
} }
this.$emit('pick', new Date(time)) this.$emit('pick', new Date(time))
}, },
getTimeSelectOptions () { getTimePickerOptions () {
const result = [] const result = []
const options = this.timePickerOptions const options = this.timePickerOptions
if (!options) { if (!options) {
@@ -91,7 +97,7 @@ export default {
const disabledTime = const disabledTime =
typeof this.disabledTime === 'function' && this.disabledTime typeof this.disabledTime === 'function' && this.disabledTime
let pickers = this.getTimeSelectOptions() let pickers = this.getTimePickerOptions()
if (Array.isArray(pickers) && pickers.length) { if (Array.isArray(pickers) && pickers.length) {
pickers = pickers.map(picker => { pickers = pickers.map(picker => {
const pickHours = picker.value.hours const pickHours = picker.value.hours
@@ -120,62 +126,74 @@ export default {
) )
} }
const hours = Array.apply(null, { length: 24 }).map((_, i) => { const minuteStep = this.minuteStep || 1
const time = new Date(date).setHours(i) const minuteLength = parseInt(60 / minuteStep)
return ( let hours = Array.apply(null, { length: 24 }).map((_, i) => i)
<li let minutes = Array.apply(null, { length: minuteLength }).map(
class={{ (_, i) => i * minuteStep
cell: true, )
actived: i === this.currentHours, let seconds =
disabled: disabledTime && disabledTime(time) this.minuteStep === 0
}} ? Array.apply(null, { length: 60 }).map((_, i) => i)
onClick={this.selectTime.bind(this, time)} : []
> let columns = { hours, minutes, seconds }
{this.stringifyText(i)}
</li>
)
})
const step = this.minuteStep || 1 if (this.timeSelectOptions && typeof this.timeSelectOptions === 'object') {
const length = parseInt(60 / step) columns = { ...columns, ...this.timeSelectOptions }
const minutes = Array.apply(null, { length }).map((_, i) => {
const value = i * step
const time = new Date(date).setMinutes(value)
return (
<li
class={{
cell: true,
actived: value === this.currentMinutes,
disabled: disabledTime && disabledTime(time)
}}
onClick={this.selectTime.bind(this, time)}
>
{this.stringifyText(value)}
</li>
)
})
const seconds = Array.apply(null, { length: 60 }).map((_, i) => {
const time = new Date(date).setSeconds(i)
return (
<li
class={{
cell: true,
actived: i === this.currentSeconds,
disabled: disabledTime && disabledTime(time)
}}
onClick={this.selectTime.bind(this, time)}
>
{this.stringifyText(i)}
</li>
)
})
let times = [hours, minutes]
if (this.minuteStep === 0) {
times.push(seconds)
} }
const hoursColumn = columns.hours.map(v => {
const time = new Date(date).setHours(v)
return (
<li
class={{
cell: true,
actived: v === this.currentHours,
disabled: disabledTime && disabledTime(time)
}}
onClick={this.selectTime.bind(this, time)}
>
{this.stringifyText(v)}
</li>
)
})
const minutesColumn = columns.minutes.map(v => {
const time = new Date(date).setMinutes(v)
return (
<li
class={{
cell: true,
actived: v === this.currentMinutes,
disabled: disabledTime && disabledTime(time)
}}
onClick={this.selectTime.bind(this, time)}
>
{this.stringifyText(v)}
</li>
)
})
const secondsColumn = columns.seconds.map(v => {
const time = new Date(date).setSeconds(v)
return (
<li
class={{
cell: true,
actived: v === this.currentSeconds,
disabled: disabledTime && disabledTime(time)
}}
onClick={this.selectTime.bind(this, time)}
>
{this.stringifyText(v)}
</li>
)
})
let times = [hoursColumn, minutesColumn, secondsColumn].filter(
v => v.length > 0
)
times = times.map(list => ( times = times.map(list => (
<ul class="mx-time-list" style={{ width: 100 / times.length + '%' }}> <ul class="mx-time-list" style={{ width: 100 / times.length + '%' }}>
{list} {list}