You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
478 lines
16 KiB
478 lines
16 KiB
10 months ago
|
import baseComponent from '../helpers/baseComponent'
|
||
|
import classNames from '../helpers/classNames'
|
||
|
import locales from './locales/index'
|
||
|
import { props } from './props'
|
||
|
|
||
|
const DATETIME = 'datetime'
|
||
|
const DATE = 'date'
|
||
|
const TIME = 'time'
|
||
|
const MONTH = 'month'
|
||
|
const YEAR = 'year'
|
||
|
const ONE_DAY = 24 * 60 * 60 * 1000
|
||
|
|
||
|
function fomartArray(min, max, step = 1) {
|
||
|
let i = min
|
||
|
let result = []
|
||
|
while (i <= max) {
|
||
|
result.push(i)
|
||
|
i+=step
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
function getDaysInMonth(date) {
|
||
|
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
|
||
|
}
|
||
|
|
||
|
function pad(n) {
|
||
|
return n < 10 ? `0${n}` : n + ''
|
||
|
}
|
||
|
|
||
|
function cloneDate(date) {
|
||
|
return new Date(+date)
|
||
|
}
|
||
|
|
||
|
function setMonth(date, month) {
|
||
|
date.setDate(Math.min(date.getDate(), getDaysInMonth(new Date(date.getFullYear(), month))))
|
||
|
date.setMonth(month)
|
||
|
}
|
||
|
|
||
|
function valueToDate(value, props = {}) {
|
||
|
if (!Array.isArray(value)) {
|
||
|
if (typeof value === 'string') {
|
||
|
value = value.replace(/\-/g, '/')
|
||
|
}
|
||
|
if (!isNaN(Number(value))) {
|
||
|
value = Number(value)
|
||
|
}
|
||
|
return new Date(value)
|
||
|
}
|
||
|
|
||
|
const { mode, use12Hours } = props
|
||
|
const now = new Date()
|
||
|
const year = now.getFullYear()
|
||
|
const month = now.getMonth()
|
||
|
const day = now.getDate()
|
||
|
const newValue = value.map((v) => Number(v))
|
||
|
if (use12Hours && [DATETIME, TIME].includes(mode)) {
|
||
|
const hourIndex = mode === DATETIME ? 3 : 0
|
||
|
const ampmIndex = newValue.length - 1
|
||
|
const ampm = Number(newValue[ampmIndex])
|
||
|
let nhour = Number(newValue[hourIndex])
|
||
|
|
||
|
if (ampm === 1) {
|
||
|
if (nhour <= 12) {
|
||
|
nhour += 12
|
||
|
}
|
||
|
nhour = nhour >= 24 ? 0 : nhour
|
||
|
} else {
|
||
|
if (nhour === 0) {
|
||
|
nhour = 12
|
||
|
}
|
||
|
if (nhour > 12) {
|
||
|
nhour -= 12
|
||
|
}
|
||
|
nhour = nhour >= 12 ? 0 : nhour
|
||
|
}
|
||
|
|
||
|
newValue.splice(hourIndex, 1, nhour)
|
||
|
newValue.splice(ampmIndex, 1)
|
||
|
}
|
||
|
if (mode === TIME) {
|
||
|
newValue.unshift(day)
|
||
|
newValue.unshift(month)
|
||
|
newValue.unshift(year)
|
||
|
} else if (mode === MONTH) {
|
||
|
newValue.push(day)
|
||
|
} else if (mode === YEAR) {
|
||
|
newValue.push(month)
|
||
|
newValue.push(day)
|
||
|
}
|
||
|
while (newValue.length <= 6) {
|
||
|
newValue.push(0)
|
||
|
}
|
||
|
return new Date(...newValue)
|
||
|
}
|
||
|
|
||
|
baseComponent({
|
||
|
properties: props,
|
||
|
data: {
|
||
|
inputValue: [],
|
||
|
options: [],
|
||
|
},
|
||
|
observers: {
|
||
|
inputValue() {
|
||
|
this.updatedCols()
|
||
|
},
|
||
|
value(value) {
|
||
|
this.setValue(value)
|
||
|
},
|
||
|
['mode, minuteStep, use12Hours, minDate, maxDate, minHour, maxHour, minMinute, maxMinute, lang']() {
|
||
|
this.setValue(this.data.inputValue)
|
||
|
},
|
||
|
},
|
||
|
methods: {
|
||
|
getDefaultMinDate() {
|
||
|
if (!this.defaultMinDate) {
|
||
|
this.defaultMinDate = new Date(2000, 1, 1, 0, 0, 0)
|
||
|
}
|
||
|
return this.defaultMinDate
|
||
|
},
|
||
|
getDefaultMaxDate() {
|
||
|
if (!this.defaultMaxDate) {
|
||
|
this.defaultMaxDate = new Date(2030, 1, 1, 23, 59, 59)
|
||
|
}
|
||
|
return this.defaultMaxDate
|
||
|
},
|
||
|
getMinDate() {
|
||
|
return this.data.minDate ? valueToDate(this.data.minDate, this.data) : this.getDefaultMinDate()
|
||
|
},
|
||
|
getMaxDate() {
|
||
|
return this.data.maxDate ? valueToDate(this.data.maxDate, this.data) : this.getDefaultMaxDate()
|
||
|
},
|
||
|
getDateMember(type = 'min', member = 'year') {
|
||
|
const methods = {
|
||
|
min: 'getMinDate',
|
||
|
max: 'getMaxDate',
|
||
|
year: 'getFullYear',
|
||
|
month: 'getMonth',
|
||
|
day: 'getDate',
|
||
|
hour: 'getHours',
|
||
|
minute: 'getMinutes',
|
||
|
}
|
||
|
return this[methods[type]]()[methods[member]]()
|
||
|
},
|
||
|
getDisplayHour(rawHour) {
|
||
|
// 12 hour am (midnight 00:00) -> 12 hour pm (noon 12:00) -> 12 hour am (midnight 00:00)
|
||
|
if (this.data.use12Hours) {
|
||
|
if (rawHour === 0) {
|
||
|
rawHour = 12
|
||
|
}
|
||
|
if (rawHour > 12) {
|
||
|
rawHour -= 12
|
||
|
}
|
||
|
return rawHour
|
||
|
}
|
||
|
return rawHour
|
||
|
},
|
||
|
setHours(date, hour) {
|
||
|
if (this.data.use12Hours) {
|
||
|
const dh = date.getHours()
|
||
|
let nhour = hour
|
||
|
nhour = dh >= 12 ? hour + 12 : hour
|
||
|
nhour = nhour >= 24 ? 0 : nhour // Make sure no more than one day
|
||
|
date.setHours(nhour)
|
||
|
} else {
|
||
|
date.setHours(hour)
|
||
|
}
|
||
|
},
|
||
|
setAmPm(date, index) {
|
||
|
if (index === 0) {
|
||
|
date.setTime(+date - ONE_DAY / 2)
|
||
|
} else {
|
||
|
date.setTime(+date + ONE_DAY / 2)
|
||
|
}
|
||
|
},
|
||
|
getNewDate(values, index) {
|
||
|
const value = parseInt(values[index], 10)
|
||
|
const { mode } = this.data
|
||
|
let newValue = cloneDate(this.getDate())
|
||
|
if (mode === DATETIME || mode === DATE || mode === YEAR || mode === MONTH) {
|
||
|
switch (index) {
|
||
|
case 0:
|
||
|
newValue.setFullYear(value)
|
||
|
break
|
||
|
case 1:
|
||
|
setMonth(newValue, value)
|
||
|
break
|
||
|
case 2:
|
||
|
newValue.setDate(value)
|
||
|
break
|
||
|
case 3:
|
||
|
this.setHours(newValue, value)
|
||
|
break
|
||
|
case 4:
|
||
|
newValue.setMinutes(value)
|
||
|
break
|
||
|
case 5:
|
||
|
this.setAmPm(newValue, value)
|
||
|
break
|
||
|
default:
|
||
|
break
|
||
|
}
|
||
|
} else if (mode === TIME) {
|
||
|
switch (index) {
|
||
|
case 0:
|
||
|
this.setHours(newValue, value)
|
||
|
break
|
||
|
case 1:
|
||
|
newValue.setMinutes(value)
|
||
|
break
|
||
|
case 2:
|
||
|
this.setAmPm(newValue, value)
|
||
|
break
|
||
|
default:
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return this.clipDate(newValue)
|
||
|
},
|
||
|
clipDate(date) {
|
||
|
const { mode } = this.data
|
||
|
const minDate = this.getMinDate()
|
||
|
const maxDate = this.getMaxDate()
|
||
|
if (mode === DATETIME) {
|
||
|
if (date < minDate) {
|
||
|
return cloneDate(minDate)
|
||
|
}
|
||
|
if (date > maxDate) {
|
||
|
return cloneDate(maxDate)
|
||
|
}
|
||
|
} else if (mode === DATE || mode === YEAR || mode === MONTH) {
|
||
|
if (+date + ONE_DAY <= minDate) {
|
||
|
return cloneDate(minDate)
|
||
|
}
|
||
|
if (date >= +maxDate + ONE_DAY) {
|
||
|
return cloneDate(maxDate)
|
||
|
}
|
||
|
} else if (mode === TIME) {
|
||
|
const maxHour = maxDate.getHours()
|
||
|
const maxMinutes = maxDate.getMinutes()
|
||
|
const minHour = minDate.getHours()
|
||
|
const minMinutes = minDate.getMinutes()
|
||
|
const hour = date.getHours()
|
||
|
const minutes = date.getMinutes()
|
||
|
if (hour < minHour || hour === minHour && minutes < minMinutes) {
|
||
|
return cloneDate(minDate)
|
||
|
}
|
||
|
if (hour > maxHour || hour === maxHour && minutes > maxMinutes) {
|
||
|
return cloneDate(maxDate)
|
||
|
}
|
||
|
}
|
||
|
return date
|
||
|
},
|
||
|
getDate(d) {
|
||
|
const date = d ? d : this.data.value
|
||
|
return this.clipDate(date ? valueToDate(date, this.data) : this.getMinDate())
|
||
|
},
|
||
|
getDateData(date) {
|
||
|
const { mode, lang } = this.data
|
||
|
const locale = locales[lang]
|
||
|
const selYear = date.getFullYear()
|
||
|
const selMonth = date.getMonth()
|
||
|
|
||
|
const minDateYear = this.getDateMember('min', 'year')
|
||
|
const maxDateYear = this.getDateMember('max', 'year')
|
||
|
const minDateMonth = this.getDateMember('min', 'month')
|
||
|
const maxDateMonth = this.getDateMember('max', 'month')
|
||
|
const minDateDay = this.getDateMember('min', 'day')
|
||
|
const maxDateDay = this.getDateMember('max', 'day')
|
||
|
|
||
|
const years = fomartArray(minDateYear, maxDateYear).map((i) => ({
|
||
|
value: i + '',
|
||
|
label: i + locale.year + '',
|
||
|
}))
|
||
|
|
||
|
if (mode === YEAR) {
|
||
|
return [years]
|
||
|
}
|
||
|
|
||
|
const minMonth = minDateYear === selYear ? minDateMonth : 0
|
||
|
const maxMonth = maxDateYear === selYear ? maxDateMonth : 11
|
||
|
const months = fomartArray(minMonth, maxMonth).map((i) => ({
|
||
|
value: i + '',
|
||
|
label: i + 1 + locale.month + '',
|
||
|
}))
|
||
|
|
||
|
if (mode === MONTH) {
|
||
|
return [years, months]
|
||
|
}
|
||
|
|
||
|
const minDay = minDateYear === selYear && minDateMonth === selMonth ? minDateDay : 1
|
||
|
const maxDay = maxDateYear === selYear && maxDateMonth === selMonth ? maxDateDay : getDaysInMonth(date)
|
||
|
|
||
|
const days = fomartArray(minDay, maxDay).map((i) => ({
|
||
|
value: i + '',
|
||
|
label: i + locale.day + '',
|
||
|
}))
|
||
|
|
||
|
return [years, months, days]
|
||
|
},
|
||
|
getTimeData(date) {
|
||
|
let { minHour, maxHour, minMinute, maxMinute } = this.data
|
||
|
const { mode, minuteStep, use12Hours, lang } = this.data
|
||
|
const locale = locales[lang]
|
||
|
const minDateMinute = this.getDateMember('min', 'minute')
|
||
|
const maxDateMinute = this.getDateMember('max', 'minute')
|
||
|
const minDateHour = this.getDateMember('min', 'hour')
|
||
|
const maxDateHour = this.getDateMember('max', 'hour')
|
||
|
const hour = date.getHours()
|
||
|
|
||
|
if (mode === DATETIME) {
|
||
|
const year = date.getFullYear()
|
||
|
const month = date.getMonth()
|
||
|
const day = date.getDate()
|
||
|
const minDateYear = this.getDateMember('min', 'year')
|
||
|
const maxDateYear = this.getDateMember('max', 'year')
|
||
|
const minDateMonth = this.getDateMember('min', 'month')
|
||
|
const maxDateMonth = this.getDateMember('max', 'month')
|
||
|
const minDateDay = this.getDateMember('min', 'day')
|
||
|
const maxDateDay = this.getDateMember('max', 'day')
|
||
|
if (minDateYear === year && minDateMonth === month && minDateDay === day) {
|
||
|
minHour = minDateHour
|
||
|
if (minDateHour === hour) {
|
||
|
minMinute = minDateMinute
|
||
|
}
|
||
|
}
|
||
|
if (maxDateYear === year && maxDateMonth === month && maxDateDay === day) {
|
||
|
maxHour = maxDateHour
|
||
|
if (maxDateHour === hour) {
|
||
|
maxMinute = maxDateMinute
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
minHour = minDateHour
|
||
|
if (minDateHour === hour) {
|
||
|
minMinute = minDateMinute
|
||
|
}
|
||
|
maxHour = maxDateHour
|
||
|
if (maxDateHour === hour) {
|
||
|
maxMinute = maxDateMinute
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let hours = []
|
||
|
if (minHour === 0 && maxHour === 0 || minHour !== 0 && maxHour !== 0) {
|
||
|
minHour = this.getDisplayHour(minHour)
|
||
|
} else if (minHour === 0 && use12Hours) {
|
||
|
minHour = 1
|
||
|
hours.push({
|
||
|
value: '0',
|
||
|
label: locale.hour ? '12' + locale.hour : '12',
|
||
|
})
|
||
|
}
|
||
|
maxHour = this.getDisplayHour(maxHour)
|
||
|
hours = [...hours, ...fomartArray(minHour, maxHour).map((i) => ({
|
||
|
value: i + '',
|
||
|
label: locale.hour ? i + locale.hour + '' : pad(i),
|
||
|
}))]
|
||
|
|
||
|
const minutes = []
|
||
|
const selMinute = date.getMinutes()
|
||
|
for (let i = minMinute; i <= maxMinute; i += minuteStep) {
|
||
|
minutes.push({
|
||
|
value: i + '',
|
||
|
label: locale.minute ? i + locale.minute + '' : pad(i),
|
||
|
})
|
||
|
if (selMinute > i && selMinute < i + minuteStep) {
|
||
|
minutes.push({
|
||
|
value: selMinute + '',
|
||
|
label: locale.minute ? selMinute + locale.minute + '' : pad(selMinute),
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const ampm = [{ value: '0', label: locale.am }, { value: '1', label: locale.pm }]
|
||
|
|
||
|
return [hours, minutes].concat(use12Hours ? [ampm] : [])
|
||
|
},
|
||
|
getValueCols(d) {
|
||
|
const { mode, use12Hours } = this.data
|
||
|
const date = this.getDate(d)
|
||
|
let cols = []
|
||
|
let value = []
|
||
|
|
||
|
if (mode === YEAR) {
|
||
|
return {
|
||
|
cols: this.getDateData(date),
|
||
|
value: [date.getFullYear() + ''],
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mode === MONTH) {
|
||
|
return {
|
||
|
cols: this.getDateData(date),
|
||
|
value: [date.getFullYear() + '', date.getMonth() + ''],
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mode === DATETIME || mode === DATE) {
|
||
|
cols = this.getDateData(date)
|
||
|
value = [date.getFullYear() + '', date.getMonth() + '', date.getDate() + '']
|
||
|
}
|
||
|
|
||
|
if (mode === DATETIME || mode === TIME) {
|
||
|
cols = cols.concat(this.getTimeData(date))
|
||
|
const hour = date.getHours()
|
||
|
const selMinute = date.getMinutes()
|
||
|
let dtValue = [hour + '', selMinute + '']
|
||
|
let nhour = hour
|
||
|
if (use12Hours) {
|
||
|
nhour = hour === 0 ? 12 : (hour > 12 ? hour - 12 : hour)
|
||
|
dtValue = [nhour + '', selMinute + '', (hour >= 12 ? 1 : 0) + '']
|
||
|
}
|
||
|
value = value.concat(dtValue)
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
value,
|
||
|
cols,
|
||
|
}
|
||
|
},
|
||
|
onValueChange(e) {
|
||
|
const { value, index } = e.detail
|
||
|
const newDate = this.getNewDate(value, index)
|
||
|
const { value: newValue, cols: newCols } = this.getValueCols(newDate)
|
||
|
const values = this.getValue(newValue, newCols)
|
||
|
this.triggerEvent('valueChange', { ...e.detail, ...values, date: +newDate })
|
||
|
},
|
||
|
updatedCols() {
|
||
|
const { cols } = this.getValueCols()
|
||
|
this.setData({ cols })
|
||
|
},
|
||
|
updated(inputValue) {
|
||
|
if (this.data.inputValue !== inputValue) {
|
||
|
this.setData({
|
||
|
inputValue,
|
||
|
})
|
||
|
}
|
||
|
},
|
||
|
setValue(value = this.data.inputValue) {
|
||
|
const { value: inputValue } = this.getValueCols()
|
||
|
this.updated(inputValue)
|
||
|
},
|
||
|
getValue(value = this.data.inputValue, cols = this.data.cols) {
|
||
|
this.picker = this.picker || this.selectComponent('#wux-picker')
|
||
|
return {
|
||
|
...this.picker.getValue(value, cols),
|
||
|
date: +this.getDate(),
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
attached() {
|
||
|
this.setValue(this.data.value)
|
||
|
},
|
||
|
})
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|