<!-- 日期选择封装 -->
<template>
<div class="date-input-container">
<el-date-picker ref="dateInput"
v-model="inputModel"
style="width: 100%"
:type="type"
size="small"
:value-format="valueFormat"
format="yyyy-MM-dd HH:mm:ss"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:clearable="clearable"
:picker-options="pickerOptions"
:default-time="['00:00:00', '23:59:59']"
@blur="timeRangeBlur"
@change="timeRangeChange" />
</div>
</template>
<script>
// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
// 例如:import 《组件名称》 from '《组件路径》';
export default {
// import引入的组件需要注入到对象中才能使用
components: {},
props: {
value: {
type: [Array, String],
default: () => []
},
value1: {
type: [Number, String],
default: ''
},
value2: {
type: [Number, String],
default: ''
},
// pickerOptions: {
// type: Object,
// default: () => { }
// },
type: {
type: String,
default: 'datetimerange'
},
valueFormat: {
type: String,
default: 'timestamp'
},
clearable: {
type: Boolean,
default: true
}
},
data () {
// 这里存放数据
return {
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}, {
text: '最近三个月',
onClick (picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
picker.$emit('pick', [start, end])
}
}, {
text: '第一季度',
onClick (picker) {
const end = new Date('2022-03-31 23:59:59')
const start = new Date('2022-01-1 00:00:00')
console.log(start, end)
picker.$emit('pick', [start, end])
}
}, {
text: '第二季度',
onClick (picker) {
const end = new Date('2022-06-30 23:59:59')
const start = new Date('2022-04-1 00:00:00')
picker.$emit('pick', [start, end])
}
}, {
text: '第三季度',
onClick (picker) {
const end = new Date('2022-09-30 23:59:59')
const start = new Date('2022-07-1 00:00:00')
picker.$emit('pick', [start, end])
}
}, {
text: '第四季度',
onClick (picker) {
const end = new Date('2022-12-31 23:59:59')
const start = new Date('2022-10-1 00:00:00')
picker.$emit('pick', [start, end])
}
}]
},
inputModel: this.value,
input1: null,
input2: null,
changeFlag: 2, // 0:第一个输入框改变 1:第二个输入框改变 2:日期选择模式(默认)
inputValue1: this.value[0],
inputValue2: this.value[1],
inputValue_copy: null,
tempValue: this.value
}
},
// 监听属性 类似于data概念
computed: {
},
// 监控data中的数据变化
watch: {
value (n, o) { // n为新值,o为旧值;
this.inputModel = n
},
value1 () {
this.changeValue()
}
},
// 生命周期 - 创建完成(可以访问当前this实例)
created () {
if ((!this.value || this.value.length === 0) && this.value1 && this.value2) {
this.value = [this.value1, this.value2]
}
},
// 生命周期 - 挂载完成(可以访问DOM元素)
mounted () {
this.input1 = document.querySelector('.date-input-container').querySelectorAll('input')[0]
this.input2 = document.querySelector('.date-input-container').querySelectorAll('input')[1]
let _this = this
this.input1.addEventListener('keydown', function (e) {
_this.inputValue_copy = _this.input1.value
}, false)
this.input2.addEventListener('keydown', function (e) {
_this.inputValue_copy = _this.input2.value
}, false)
this.input1.addEventListener('keyup', function (e) {
let keyCode = e.keyCode || e.which
_this.dealFormatFun(this, 0, keyCode)
}, false)
this.input2.addEventListener('keyup', function (e) {
let keyCode = e.keyCode || e.which
_this.dealFormatFun(this, 1, keyCode)
}, false)
},
// 方法集合
methods: {
setParentModeVal (value) {
this.$emit('update:value', value)
this.changeFlag = 2 // 恢复默认模式
this.$emit('timeChange', value)
},
dealFormatFun ($this, flag, keyCode) {
this.changeFlag = flag
keyCode = keyCode >= 96 && keyCode <= 105 ? keyCode - 48 : keyCode
let inputDom = flag === 0 ? this.input1 : this.input2
var pos
// ---------- 获取当前光标位置 ---------------
if ($this.setSelectionRange) {
// 标准浏览器
pos = $this.selectionStart
} else {
// IE浏览器
var selectStart
var selectEnd
var selectText
var emptyValue = -1
var range = document.selection.createRange()
selectText = range.text
range.moveStart('character', -$this.value.length)
pos = range.text.length
selectStart = pos - (selectText.length)
selectEnd = selectStart + (selectText.length)
if (selectStart !== selectEnd) {
pos = emptyValue
} else {
selectStart = emptyValue
selectEnd = emptyValue
}
}
// ---------- 处理输入结果及光标位 ---------------
if (keyCode >= 48 && keyCode <= 57) { // 仅能输入数字
if (inputDom.value.length > 19) {
let month = Number(inputDom.value.substring(5, 7))
let month_flag = [1, 3, 5, 7, 8, 10, 12].indexOf(month) > -1
let month_first = Number(inputDom.value.substring(5, 6))
let day_first = Number(inputDom.value.substring(8, 9))
let hour_first = Number(inputDom.value.substring(12, 13))
// 处理月份(十位大于1、个位大于2)、天数(十位大于3、十位为3时个位大于1)、小时(十位大于2、十位为2个位大于3)、分钟及秒(十位大于5)时的格式问题
if ((pos === 6 && keyCode > 49) || (pos === 7 && month_first === 1 && keyCode > 50) || (pos === 9 && keyCode > 51) || (pos === 10 && day_first === 3 && ((month_flag && keyCode > 49) || (!month_flag && keyCode > 48))) || (pos === 12 && keyCode > 50) || (pos === 13 && hour_first === 2 && keyCode > 51) || ((pos === 15 || pos === 18) && keyCode > 53)) {
inputDom.value = inputDom.value.substring(0, pos - 1) + inputDom.value.substring(pos, inputDom.value.length)
inputDom.value = this.replaceStr(inputDom.value, 4, '-')
inputDom.value = this.replaceStr(inputDom.value, 7, '-')
inputDom.value = this.replaceStr(inputDom.value, 10, ' ')
inputDom.value = this.replaceStr(inputDom.value, 13, ':')
inputDom.value = this.replaceStr(inputDom.value, 16, ':')
// ---------- 重置光标位置 ---------------
// pos 光标的位置 -1为最后一位
if (pos < 0) pos = inputDom.value.length
if ($this.setSelectionRange) {
// 兼容火狐,谷歌
setTimeout(() => {
$this.setSelectionRange(pos - 1, pos - 1)
inputDom.focus()
}, 0)
} else if ($this.createTextRange) {
// 兼容IE
var rng = $this.createTextRange()
rng.move('character', pos - 1)
rng.select()
}
} else {
// 若输入的为数字 则执行替换操作
inputDom.value = inputDom.value.substring(0, pos) + inputDom.value.substring(pos + 1, inputDom.value.length)
let substr = inputDom.value.substring(pos, pos + 1)
if (substr === '-' || substr === ' ' || substr === ':') {
pos++
}
if (inputDom.value.length >= 20) {
inputDom.value = inputDom.value.substring(0, 19)
}
inputDom.value = this.replaceStr(inputDom.value, 4, '-')
inputDom.value = this.replaceStr(inputDom.value, 7, '-')
inputDom.value = this.replaceStr(inputDom.value, 10, ' ')
inputDom.value = this.replaceStr(inputDom.value, 13, ':')
inputDom.value = this.replaceStr(inputDom.value, 16, ':')
if (pos === 6 && keyCode === 49) { // 处理月份
let month_late = Number(inputDom.value.substring(pos, pos + 1))
if (month_late > 2) {
inputDom.value = this.replaceStr(inputDom.value, pos, '2')
}
}
if (pos === 9 && keyCode === 51) { // 处理天数
let day_late = Number(inputDom.value.substring(pos, pos + 1))
if (day_late > 2) {
if ([1, 3, 5, 7, 8, 10, 12].indexOf(Number(inputDom.value.substring(5, 7))) > -1) {
inputDom.value = this.replaceStr(inputDom.value, pos, '1')
} else {
inputDom.value = this.replaceStr(inputDom.value, pos, '0')
}
}
}
if (pos === 12 && keyCode === 50) { // 处理小时
let hour_late = Number(inputDom.value.substring(pos, pos + 1))
if (hour_late > 3) {
inputDom.value = this.replaceStr(inputDom.value, pos, '3')
}
}
// ---------- 重置光标位置 ---------------
// pos 光标的位置 -1为最后一位
if (pos < 0) pos = inputDom.value.length
if ($this.setSelectionRange) {
// 兼容火狐,谷歌
setTimeout(() => {
$this.setSelectionRange(pos, pos)
inputDom.focus()
}, 0)
} else if ($this.createTextRange) {
// 兼容IE
rng = $this.createTextRange()
rng.move('character', pos)
rng.select()
}
}
}
} else {
// 若为非数字且不是"左移"、"右移"操作 则执行删除操作
if (keyCode !== 37 && keyCode !== 39) {
inputDom.value = inputDom.value.substring(0, pos - 1) + inputDom.value.substring(pos, inputDom.value.length)
// ---------- 重置光标位置 ---------------
// pos 光标的位置 -1为最后一位
if (pos < 0) pos = inputDom.value.length
if ($this.setSelectionRange) {
// 兼容火狐,谷歌
setTimeout(() => {
$this.setSelectionRange(pos - 1, pos - 1)
inputDom.focus()
}, 0)
} else if ($this.createTextRange) {
// 兼容IE
rng = $this.createTextRange()
rng.move('character', pos - 1)
rng.select()
}
}
}
if (flag === 0) {
this.inputValue1 = (new Date(inputDom.value).getTime()) || (new Date().getTime())
} else {
this.inputValue2 = (new Date(inputDom.value).getTime()) || (new Date().getTime())
}
if (this.inputValue1 > this.inputValue2) {
this.inputValue2 = this.inputValue1
}
// this.inputModel = [this.inputValue1, this.inputValue2]
},
replaceStr (str, index, char) {
return str.substring(0, index) + char + str.substring(index + 1)
},
changeValue () {
if (!this.value1 || !this.value2) {
this.inputModel = []
} else if (this.value1 > this.value2) {
this.inputModel = []
} else {
this.inputModel = [this.value1, this.value2]
}
},
timeRangeChange (value) {
console.log(value)
let value1, value2
if (value && value.length > 0) {
value1 = value[0]
if (this.valueFormat === 'timestamp' && this.type === 'daterange') {
value2 = value[1] // + (3600 * 24 * 1000) - 1
// value2 = value[1] - 1
} else {
value2 = value[1]
}
this.setParentModeVal([this.inputValue1, this.inputValue2])
} else {
value1 = null
value2 = null
this.setParentModeVal([])
}
if (this.changeFlag === 2) {
this.inputValue2 = value2
this.inputValue1 = value1
}
this.$emit('update:value1', value1)
this.$emit('update:value2', value2)
},
clear () {
this.inputModel = []
},
timeRangeBlur () {
this.inputModel = [this.inputValue1, this.inputValue2]
this.setParentModeVal([this.inputValue1, this.inputValue2])
}
}
}
</script>
<style rel='stylesheet/scss' lang='scss' scoped>
.date-input-container {
width: 100%;
.el-date-editor--datetimerange.el-input__inner {
width: 100%;
}
}
</style>
2使用
<span class="date-editor">
<DateInput ref="recharge"
:value.sync="timeRange"
@timeChange="timeRangeChange" />
</span>