10 changed files with 604 additions and 63 deletions
@ -0,0 +1,167 @@ |
|||
const GetDate = { |
|||
withData: (num) => { |
|||
let param = parseInt(num); |
|||
return param < 10 ? '0' + param : '' + param; |
|||
}, |
|||
getTimes(str){ |
|||
return new Date(str.replace(/-/g,'/')).getTime(); |
|||
}, |
|||
getCurrentTimes(){ |
|||
const date = new Date(); |
|||
const year = date.getFullYear(); |
|||
const month = date.getMonth() + 1; |
|||
const day = date.getDate(); |
|||
const hour = date.getHours(); |
|||
const minute = date.getMinutes(); |
|||
const second = date.getSeconds(); |
|||
return { |
|||
detail: { |
|||
year: year, |
|||
month: month, |
|||
day: day, |
|||
hour: hour, |
|||
minute: minute, |
|||
second: second |
|||
} |
|||
} |
|||
}, |
|||
format(arr){ |
|||
let curarr = []; |
|||
let curarr0 = []; |
|||
let str = ''; |
|||
arr.forEach((cur,index) => { |
|||
let o = GetDate.withData(cur); |
|||
if(index > 2){ |
|||
curarr.push(o); |
|||
}else{ |
|||
curarr0.push(o); |
|||
} |
|||
}) |
|||
if(arr.length < 4){ |
|||
str = curarr0.join('-'); |
|||
}else{ |
|||
str = curarr0.join('-') + ' ' + curarr.join(':'); |
|||
} |
|||
return str; |
|||
}, |
|||
getCurrentStringValue(str){ |
|||
let newstr = str.split(' '); |
|||
if(newstr && newstr[1]){ |
|||
let arr = [...newstr[0].split('-'),...newstr[1].split(':')]; |
|||
return arr; |
|||
} |
|||
return newstr[0].split('-'); |
|||
}, |
|||
getCompare(curp,startp,endp,timesp){ |
|||
let cur = GetDate.getTimes(curp); |
|||
let start = GetDate.getTimes(startp); |
|||
let end = GetDate.getTimes(endp); |
|||
if(cur < start){ |
|||
return GetDate.getTimeIndex(timesp,GetDate.getCurrentStringValue(startp)); |
|||
}else if(cur > end){ |
|||
return GetDate.getTimeIndex(timesp,GetDate.getCurrentStringValue(endp)); |
|||
}else{ |
|||
return GetDate.getTimeIndex(timesp,GetDate.getCurrentStringValue(curp)); |
|||
} |
|||
}, |
|||
getChooseArr(times,indexs){ |
|||
let arr = []; |
|||
times.forEach((cur,index) => arr.push(cur[indexs[index]])); |
|||
return arr; |
|||
}, |
|||
getNewArray(arr){ |
|||
let newarr = []; |
|||
arr.forEach(cur => newarr.push(cur)); |
|||
return newarr; |
|||
}, |
|||
getLoopArray: (start, end) => { |
|||
var start = start || 0; |
|||
var end = end || 1; |
|||
var array = []; |
|||
for (var i = start; i <= end; i++) { |
|||
array.push(GetDate.withData(i)); |
|||
} |
|||
return array; |
|||
}, |
|||
getMonthDay: (year, month) => { |
|||
var flag = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0), array = null; |
|||
|
|||
switch (month) { |
|||
case '01': |
|||
case '03': |
|||
case '05': |
|||
case '07': |
|||
case '08': |
|||
case '10': |
|||
case '12': |
|||
array = GetDate.getLoopArray(1, 31) |
|||
break; |
|||
case '04': |
|||
case '06': |
|||
case '09': |
|||
case '11': |
|||
array = GetDate.getLoopArray(1, 30) |
|||
break; |
|||
case '02': |
|||
array = flag ? GetDate.getLoopArray(1, 29) : GetDate.getLoopArray(1, 28) |
|||
break; |
|||
default: |
|||
array = '月份格式不正确,请重新输入!' |
|||
} |
|||
return array; |
|||
}, |
|||
getDateTimes: (opts) => { |
|||
var years = GetDate.getLoopArray(opts.start, opts.end); |
|||
var months = GetDate.getLoopArray(1, 12); |
|||
var days = GetDate.getMonthDay(opts.curyear, opts.curmonth); |
|||
var hours = GetDate.getLoopArray(0, 23); |
|||
var minutes = GetDate.getLoopArray(0, 59); |
|||
var seconds = GetDate.getLoopArray(0, 59); |
|||
var times = null; |
|||
|
|||
switch (opts.fields) { |
|||
case 'year': |
|||
times = [years] |
|||
break; |
|||
case 'month': |
|||
times = [years, months] |
|||
break; |
|||
case 'day': |
|||
times = [years, months, days] |
|||
break; |
|||
case 'hour': |
|||
times = [years, months, days, hours] |
|||
break; |
|||
case 'minute': |
|||
times = [years, months, days, hours, minutes] |
|||
break; |
|||
case 'second': |
|||
times = [years, months, days, hours, minutes, seconds] |
|||
break; |
|||
default: |
|||
times = [years, months, days, hours, minutes, seconds] |
|||
} |
|||
return times; |
|||
}, |
|||
getIndex(arr,target){ |
|||
let len = arr.length; |
|||
for(let i = 0; i < len; i++){ |
|||
if(arr[i] == target){ |
|||
return i; |
|||
} |
|||
} |
|||
}, |
|||
getTimeIndex(arrs, targets){ |
|||
let len = arrs.length; |
|||
let arr = []; |
|||
for(let i = 0; i < len; i++){ |
|||
arr.push(GetDate.getIndex(arrs[i], targets[i])) |
|||
} |
|||
return arr; |
|||
}, |
|||
error(str){ |
|||
console.error(str); |
|||
} |
|||
} |
|||
|
|||
module.exports = GetDate; |
@ -0,0 +1,221 @@ |
|||
<template> |
|||
<picker class='rui-picker rui-class' mode="multiSelector" :range="times" :value="timesIndex" :disabled="curDisabled" @change='changeDate' @cancel="cancelDate" @columnchange="columnchangeDate"> |
|||
{{curValue}} |
|||
</picker> |
|||
</template> |
|||
|
|||
<script> |
|||
import GetDate from './GetDate.js'; |
|||
export default { |
|||
name: 'rattenking-dtpicker', |
|||
props: { |
|||
/** |
|||
* picker允许选中的最小值 |
|||
*/ |
|||
start: { |
|||
type: String, |
|||
default: '1900-00-00 00:00:00' |
|||
}, |
|||
/** |
|||
* picker允许选中的最大值 |
|||
*/ |
|||
end: { |
|||
type: String, |
|||
default: '2500-12-30 23:59:59' |
|||
}, |
|||
/** |
|||
* picker默认展示的值 |
|||
*/ |
|||
value: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
/** |
|||
* picker的时间粒度 |
|||
*/ |
|||
fields: { |
|||
type: String, |
|||
default: 'second' |
|||
}, |
|||
/** |
|||
* picker是否禁止 |
|||
*/ |
|||
disabled: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
times:[['2019','2020'],['01','02']], |
|||
timesIndex: [1,1], |
|||
timesString: null, |
|||
curValue: this.value, |
|||
curDisabled: this.disabled, |
|||
cancel: null |
|||
} |
|||
}, |
|||
watch: { |
|||
value(val) { |
|||
this.curValue = val; |
|||
}, |
|||
disabled(val){ |
|||
this.curDisabled = val; |
|||
}, |
|||
curDisabled(val){ |
|||
this.curDisabled = val; |
|||
}, |
|||
curValue(val) { |
|||
this.curValue = val; |
|||
this.$emit('change', val); |
|||
}, |
|||
times(val){ |
|||
this.times = val; |
|||
}, |
|||
timesIndex(val){ |
|||
this.timesIndex = val; |
|||
}, |
|||
cancel(val) { |
|||
this.$emit('cancel', val); |
|||
} |
|||
}, |
|||
created() { |
|||
if(this.value === ''){ |
|||
let time = GetDate.getCurrentTimes(); |
|||
let arr = []; |
|||
for (let key in time.detail) { |
|||
arr.push(time.detail[key]); |
|||
if(key === this.fields){ |
|||
break; |
|||
} |
|||
} |
|||
this.value = GetDate.format(arr); |
|||
this.curValue = GetDate.format(arr); |
|||
} |
|||
switch (this.fields){ |
|||
case 'year': |
|||
if (this.value.length !== 4) {GetDate.error('时间粒度和时间格式不一致');this.curDisabled = true;return false;} |
|||
if (this.start.length !== 4) { GetDate.error('时间粒度和开始时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.end.length !== 4) { GetDate.error('时间粒度和结束时间格式不一致'); this.curDisabled = true; return false;} |
|||
break; |
|||
case 'month': |
|||
if (this.value.length !== 7) { GetDate.error('时间粒度和时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.start.length !== 7) { GetDate.error('时间粒度和开始时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.end.length !== 7) { GetDate.error('时间粒度和结束时间格式不一致'); this.curDisabled = true; return false;} |
|||
break; |
|||
case 'day': |
|||
if (this.value.length !== 10) { GetDate.error('时间粒度和时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.start.length !== 10) { GetDate.error('时间粒度和开始时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.end.length !== 10) { GetDate.error('时间粒度和结束时间格式不一致'); this.curDisabled = true; return false;} |
|||
break; |
|||
case 'hour': |
|||
if (this.value.length !== 13) { GetDate.error('时间粒度和时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.start.length !== 13) { GetDate.error('时间粒度和开始时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.end.length !== 13) { GetDate.error('时间粒度和结束时间格式不一致'); this.curDisabled = true; return false;} |
|||
break; |
|||
case 'minute': |
|||
if (this.value.length !== 16) { GetDate.error('时间粒度和时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.start.length !== 16) { GetDate.error('时间粒度和开始时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.end.length !== 16) { GetDate.error('时间粒度和结束时间格式不一致'); this.curDisabled = true; return false;} |
|||
break; |
|||
case 'second': |
|||
if (this.value.length !== 19) { GetDate.error('时间粒度和时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.start.length !== 19) { GetDate.error('时间粒度和开始时间格式不一致'); this.curDisabled = true; return false;} |
|||
if (this.end.length !== 19) { GetDate.error('时间粒度和结束时间格式不一致'); this.curDisabled = true; return false;} |
|||
break; |
|||
default: |
|||
GetDate.error('时间粒度不存在') |
|||
break; |
|||
} |
|||
let values = this.value.split(' '); |
|||
let targets = GetDate.getCurrentStringValue(this.value); |
|||
|
|||
if (GetDate.getTimes(this.value) < GetDate.getTimes(this.start)){ |
|||
GetDate.error('默认时间不能小于开始时间') |
|||
this.curDisabled = true |
|||
return false; |
|||
} |
|||
if (GetDate.getTimes(this.value) > GetDate.getTimes(this.end)) { |
|||
GetDate.error('默认时间不能大于开始时间') |
|||
this.curDisabled = true |
|||
return false; |
|||
} |
|||
let times = GetDate.getDateTimes({ |
|||
start: this.start.substring(0, 4), |
|||
end: this.end.substring(0, 4), |
|||
curyear: this.value.substring(0, 4), |
|||
curmonth: this.value.substring(5, 7), |
|||
fields: this.fields |
|||
}) |
|||
let timesIndex = GetDate.getTimeIndex(times, targets); |
|||
let timesString = []; |
|||
timesIndex.forEach(o => timesString.push(o)); |
|||
|
|||
this.times = times; |
|||
this.timesIndex = timesIndex; |
|||
this.timesString = timesString; |
|||
}, |
|||
methods: { |
|||
changeDate(e){ |
|||
let values = e.detail.value; |
|||
let times = this.times; |
|||
let curarr = []; |
|||
for (let i = 0, len = values.length; i < len; i++) { |
|||
curarr.push(times[i][values[i]]) |
|||
} |
|||
let str = GetDate.format(curarr); |
|||
this.curValue = str; |
|||
}, |
|||
columnchangeDate(e){ |
|||
// 如果是年和月粒度,那么只需要改变时间格式的index,否则需要判断当月天数 |
|||
if ((this.fields === 'year' || this.fields === 'month')){ |
|||
let timesIndex = GetDate.getNewArray(this.timesIndex); |
|||
timesIndex[e.detail.column] = e.detail.value; |
|||
// let arr = GetDate.getCompare(GetDate.format(GetDate.getChooseArr(this.times,timesIndex)),this.start,this.end,this.times); |
|||
// console.log(arr) |
|||
this.timesIndex = timesIndex; |
|||
return false; |
|||
}else{ |
|||
// 如果改变的是年和月,重新获取天数,同时判断天数的index是否大于当前天数,大于就设置为当月最后一天,否则不变。 |
|||
if(e.detail.column === 0 || e.detail.column === 1){ |
|||
let times = GetDate.getNewArray(this.times); |
|||
let timesIndex = GetDate.getNewArray(this.timesIndex); |
|||
timesIndex[e.detail.column] = e.detail.value; |
|||
let days = GetDate.getMonthDay(times[0][timesIndex[0]], times[1][timesIndex[1]]); |
|||
times[2] = days; |
|||
if(timesIndex[2] > days.length - 1){ |
|||
timesIndex[2] = days.length - 1; |
|||
} |
|||
this.times = times; |
|||
// let arr = GetDate.getCompare(GetDate.format(GetDate.getChooseArr(this.times,timesIndex)),this.start,this.end,this.times); |
|||
this.timesIndex = timesIndex; |
|||
}else{ |
|||
let timesIndex = GetDate.getNewArray(this.timesIndex); |
|||
timesIndex[e.detail.column] = e.detail.value; |
|||
// let arr = GetDate.getCompare(GetDate.format(GetDate.getChooseArr(this.times,timesIndex)),this.start,this.end,this.times); |
|||
// console.log(arr) |
|||
this.timesIndex = timesIndex; |
|||
} |
|||
} |
|||
}, |
|||
cancelDate(e){ |
|||
this.cancel = e |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.rui-picker{ |
|||
height: 10vw; |
|||
font-size: 4vw; |
|||
color: #000; |
|||
display: -webkit-flex; |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 0 10px; |
|||
box-sizing: border-box; |
|||
border: 1px solid #aaa; |
|||
border-radius: 3px; |
|||
} |
|||
</style> |
@ -0,0 +1,69 @@ |
|||
### DatePicker 多粒度时间选择器 |
|||
|
|||
可进行多粒度的时间选择器,组件名:``rattenking-dtpicker``,代码块: ruiDatePicker。 |
|||
|
|||
**使用方式:** |
|||
|
|||
在 ``script`` 中引用组件 |
|||
|
|||
```javascript |
|||
import ruiDatePicker from '@/components/rattenking-dtpicker/rattenking-dtpicker.vue'; |
|||
export default { |
|||
components: {ruiDatePicker} |
|||
} |
|||
``` |
|||
|
|||
在 ``template`` 中使用组件 |
|||
|
|||
```html |
|||
<ruiDatePicker |
|||
fields="second" |
|||
start="2010-00-00 00:00:00" |
|||
end="2030-12-30 23:59:59" |
|||
:value="value" |
|||
@change="bindChange" |
|||
@cancel="bindCancel" |
|||
></ruiDatePicker> |
|||
``` |
|||
|
|||
实际效果参考:[https://github.com/Rattenking/rui-uni-components](https://github.com/Rattenking/rui-uni-components) |
|||
|
|||
**DatePicker 属性说明:** |
|||
|
|||
|属性名 |类型 |默认值 |说明 | |
|||
|--- |---- |--- |--- | |
|||
|start |String |'1900-00-00 00:00:00' |限制选择器选择的最小时间 | |
|||
|end |String |'2500-12-30 23:59:59' |限制选择器选择的最大时间 | |
|||
|value |String |'' |当前时间选择器显示的时间 | |
|||
|fields |String |'second' |时间选择器的粒度 | |
|||
|disabled |Boolean|false |是否为禁用状态 | |
|||
|
|||
|
|||
**fields 值说明:** |
|||
|
|||
|值 |类型 |说明 | |
|||
|--- |---- |--- | |
|||
|year |String |选择器粒度为年 | |
|||
|month |String |选择器粒度为月份 | |
|||
|day |String |选择器粒度为天 | |
|||
|hour |String |选择器粒度为小时 | |
|||
|minute |String |选择器粒度为分钟 | |
|||
|second |String |选择器粒度为秒 | |
|||
|
|||
**事件说明:** |
|||
|
|||
|事件名称 |说明 | |
|||
|---|---| |
|||
|change |时间选择器点击【确定】按钮时时触发的事件,参数为picker的当前的 value| |
|||
|cancel |时间选择器点击【取消】按钮时时触发的事件| |
|||
|
|||
**修复BUG说明:** |
|||
|
|||
1. 修复每个月都是 31 天的 bug ! |
|||
2. 修复 value 值做出改变,在外部赋值才改变的 bug ,当前版本只要 value 改变,显示值就会改变! |
|||
3. 优化了默认显示值问题,如果用户不填写,直接默认当前设备的当前时间! |
|||
4. 修复二月份能够选择 31 号的 bug! |
|||
|
|||
**感谢:** |
|||
|
|||
> 在这里特别感谢**AimerQAQ**、**icare**、**281245387@qq.com**、**椰子皮**等反馈的 bug 和给出的优化建议。有更多优化建议和需求,请联系作者。谢谢! |
@ -1,47 +0,0 @@ |
|||
<template> |
|||
<view> |
|||
<view @tap="$refs.calendar.open()" hover-class="cc-active"> |
|||
<view class="iconfont icon-calendar timer"><text class="padding-left-xs">{{ date }}</text></view> |
|||
</view> |
|||
<uni-calendar @confirm="handleChange" :insert="false" :range="false" :show-month="true" ref="calendar" /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'DateSelector', |
|||
data() { |
|||
const time = this.$moment().format('YYYY-MM-DD hh:mm:ss'); |
|||
return { |
|||
time, |
|||
}; |
|||
}, |
|||
|
|||
computed: { |
|||
date() { |
|||
const { |
|||
time |
|||
} = this; |
|||
return time; |
|||
}, |
|||
}, |
|||
|
|||
methods: { |
|||
/** |
|||
* 日历确认选择了时间段 |
|||
* @param {object} value 日历返回对象 |
|||
*/ |
|||
handleChange(value) { |
|||
this.time = value.fulldate; |
|||
this.$emit('change', this.time); |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.timer { |
|||
font-size: 34rpx !important; |
|||
color: $gray; |
|||
} |
|||
</style> |
@ -0,0 +1,68 @@ |
|||
<template> |
|||
<view class="date-bg"> |
|||
<view hover-class="cc-active"> |
|||
<view class="iconfont icon-calendar timer"><text class="padding-left-xs">{{ endDate }}</text></view> |
|||
</view> |
|||
|
|||
<view class="startTime"> |
|||
<ruiDatePicker |
|||
fields="second" |
|||
start="2010-00-00 00:00:00" |
|||
end="2030-12-30 23:59:59" |
|||
:value="valueEnd" |
|||
@change="bindChangeEnd" |
|||
></ruiDatePicker> |
|||
</view> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import ruiDatePicker from 'components/rattenking-dtpicker/rattenking-dtpicker.vue'; |
|||
|
|||
export default { |
|||
name: 'EndDateSelector', |
|||
components: {ruiDatePicker}, |
|||
|
|||
data() { |
|||
return { |
|||
valueEnd: this.$moment(new Date()).format('YYYY-MM-DD hh:mm:ss') |
|||
}; |
|||
}, |
|||
|
|||
computed: { |
|||
endDate() { |
|||
const { |
|||
valueEnd |
|||
} = this; |
|||
return valueEnd; |
|||
}, |
|||
}, |
|||
|
|||
methods: { |
|||
bindChangeEnd(value){ |
|||
console.log('抵达时间',value) |
|||
this.valueEnd = value; |
|||
this.$emit('change', this.valueEnd); |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.timer { |
|||
font-size: 34rpx !important; |
|||
color: $gray; |
|||
} |
|||
|
|||
.date-bg{ |
|||
position: relative; |
|||
} |
|||
|
|||
.startTime{ |
|||
opacity: 0; |
|||
position: absolute; |
|||
top: -14rpx; |
|||
left: 50rpx; |
|||
} |
|||
</style> |
@ -0,0 +1,68 @@ |
|||
<template> |
|||
<view class="date-bg"> |
|||
<view hover-class="cc-active"> |
|||
<view class="iconfont icon-calendar timer"><text class="padding-left-xs">{{ startDate }}</text></view> |
|||
</view> |
|||
|
|||
<view class="startTime"> |
|||
<ruiDatePicker |
|||
fields="second" |
|||
start="2010-00-00 00:00:00" |
|||
end="2030-12-30 23:59:59" |
|||
:value="valueStart" |
|||
@change="bindChangeStart" |
|||
></ruiDatePicker> |
|||
</view> |
|||
|
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import ruiDatePicker from 'components/rattenking-dtpicker/rattenking-dtpicker.vue'; |
|||
|
|||
export default { |
|||
name: 'StartDateSelector', |
|||
components: {ruiDatePicker}, |
|||
|
|||
data() { |
|||
return { |
|||
valueStart: this.$moment(new Date()).format('YYYY-MM-DD hh:mm:ss') |
|||
}; |
|||
}, |
|||
|
|||
computed: { |
|||
startDate() { |
|||
const { |
|||
valueStart |
|||
} = this; |
|||
return valueStart; |
|||
}, |
|||
}, |
|||
|
|||
methods: { |
|||
bindChangeStart(value){ |
|||
console.log('抵达时间',value) |
|||
this.valueStart = value; |
|||
this.$emit('change', this.valueStart); |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.timer { |
|||
font-size: 34rpx !important; |
|||
color: $gray; |
|||
} |
|||
|
|||
.date-bg{ |
|||
position: relative; |
|||
} |
|||
|
|||
.startTime{ |
|||
opacity: 0; |
|||
position: absolute; |
|||
top: -14rpx; |
|||
left: 50rpx; |
|||
} |
|||
</style> |
Loading…
Reference in new issue