mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-18 11:06:36 +08:00
306 lines
7.5 KiB
Vue
306 lines
7.5 KiB
Vue
<template>
|
||
<div class="date-range">
|
||
<!--<year-range-panel />-->
|
||
<el-select v-model="dateType" :size="size"
|
||
style="max-width: 100px; min-width: 100px; margin-right: 10px;"
|
||
v-if="!hideTypeOnlyOne || validTypeList.length > 1">
|
||
<el-option v-for="type in validTypeList" :key="type.value" :value="type.value" :label="type.label" />
|
||
</el-select>
|
||
<el-date-picker style="flex-grow: 1;" v-model="currentDates"
|
||
:size="size" :placeholder="placeholder" :type="innerDateType"
|
||
:disabled="disabled" :format="innerDateFormat" :readonly="readonly" :editable="editable"
|
||
:clearable="clearable" :start-placeholder="startPlaceholder" :end-placeholder="endPlaceholder"
|
||
:align="align" :range-separator="rangeSeparator" :value-format="valueFormat"
|
||
:prefix-icon="prefixIcon" :clear-icon="clearIcon" @change="onValueChange" />
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { formatDate, parseDate } from 'element-ui/src/utils/date-util';
|
||
|
||
const allTypeList = [{
|
||
value: 'day',
|
||
label: '自然日'
|
||
}, {
|
||
value: 'month',
|
||
label: '自然月'
|
||
}, {
|
||
value: 'year',
|
||
label: '自然年'
|
||
}];
|
||
|
||
export default {
|
||
name: 'DateRange',
|
||
props: {
|
||
/**
|
||
* 绑定的数据
|
||
*/
|
||
value: {
|
||
type: [Array],
|
||
default: () => {
|
||
return []
|
||
}
|
||
},
|
||
/**
|
||
* 默认显示的数据选择方式,如果不存在与allowTypes中则显示allowTypes中的第一个
|
||
*/
|
||
defaultDateType: {
|
||
type: String,
|
||
default: 'day'
|
||
},
|
||
/**
|
||
* 组件大小(medium / small / mini)
|
||
*/
|
||
size: {
|
||
type: String
|
||
},
|
||
/**
|
||
* 数据选择方式只有一个的时候是否隐藏数据选择方式下拉
|
||
*/
|
||
hideTypeOnlyOne: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
/**
|
||
* 允许的数据选择方式(day, month, year)
|
||
* 默认值['day', 'month', 'year']
|
||
*/
|
||
allowTypes: {
|
||
type: Array,
|
||
default: () => {
|
||
return allTypeList.map((item) => {
|
||
return item.value;
|
||
});
|
||
}
|
||
},
|
||
/**
|
||
* 是否范围选择
|
||
*/
|
||
isRange: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
/**
|
||
* 输出字符串的format
|
||
*/
|
||
outputFormat: {
|
||
type: String,
|
||
default: 'yyyy-MM-dd HH:mm:ss'
|
||
},
|
||
/**
|
||
* 非范围选择时的占位内容
|
||
*/
|
||
placeholder: String,
|
||
/**
|
||
* 范围选择时开始日期的占位内容
|
||
*/
|
||
startPlaceholder: String,
|
||
/**
|
||
* 范围选择时结束日期的占位内容
|
||
*/
|
||
endPlaceholder: String,
|
||
/**
|
||
* 完全只读
|
||
*/
|
||
readonly: Boolean,
|
||
/**
|
||
* 禁用
|
||
*/
|
||
disabled: Boolean,
|
||
/**
|
||
* 文本框可输入
|
||
*/
|
||
editable: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
/**
|
||
* 是否显示清除按钮
|
||
*/
|
||
clearable: {
|
||
type: Boolean,
|
||
default: true
|
||
},
|
||
/**
|
||
* 对齐方式(left, center, right)
|
||
*/
|
||
align: {
|
||
type: String,
|
||
default: 'left'
|
||
},
|
||
/**
|
||
* 选择范围时的分隔符
|
||
*/
|
||
rangeSeparator: {
|
||
type: String,
|
||
default: '-'
|
||
},
|
||
/**
|
||
* 可选,绑定值的格式。不指定则绑定值为 Date 对象
|
||
*/
|
||
valueFormat: {
|
||
type: String,
|
||
default: 'yyyy-MM-dd'
|
||
},
|
||
/**
|
||
* 自定义头部图标的类名
|
||
*/
|
||
prefixIcon: {
|
||
type: String,
|
||
default: 'el-icon-date'
|
||
},
|
||
/**
|
||
* 自定义清空图标的类名
|
||
*/
|
||
clearIcon: {
|
||
type: String,
|
||
default: 'el-icon-circle-close'
|
||
}
|
||
},
|
||
data () {
|
||
return {
|
||
dateType: this.defaultDateType,
|
||
currentDates: undefined
|
||
}
|
||
},
|
||
methods: {
|
||
onValueChange (values) {
|
||
this.$nextTick(() => {
|
||
this.emitChange();
|
||
});
|
||
},
|
||
emitChange () {
|
||
let outputDate = [];
|
||
if (this.currentDates != null) {
|
||
if (!this.isRange) {
|
||
outputDate[0] = new Date(this.currentDates);
|
||
outputDate[1] = new Date(this.currentDates);
|
||
} else {
|
||
if (Array.isArray(this.currentDates) && this.currentDates.length === 2) {
|
||
outputDate[0] = new Date(this.currentDates[0]);
|
||
outputDate[1] = new Date(this.currentDates[1]);
|
||
}
|
||
}
|
||
|
||
if (outputDate[0] != null && outputDate[1] != null) {
|
||
outputDate[0].setHours(0, 0, 0, 0);
|
||
outputDate[1].setHours(0, 0, 0, 0);
|
||
switch (this.dateType) {
|
||
case 'day':
|
||
outputDate[1].setDate(outputDate[1].getDate() + 1);
|
||
break;
|
||
case 'month':
|
||
outputDate[1].setDate(1);
|
||
outputDate[0].setDate(1);
|
||
outputDate[1].setMonth(outputDate[1].getMonth() + 1);
|
||
break;
|
||
case 'year':
|
||
outputDate[1].setMonth(0);
|
||
outputDate[1].setDate(1);
|
||
outputDate[0].setMonth(0);
|
||
outputDate[0].setDate(1);
|
||
outputDate[1].setFullYear(outputDate[1].getFullYear() + 1);
|
||
break;
|
||
}
|
||
outputDate[1] = new Date(outputDate[1].getTime() - 1);
|
||
|
||
outputDate[0] = formatDate(outputDate[0], this.outputFormat);
|
||
outputDate[1] = formatDate(outputDate[1], this.outputFormat);
|
||
}
|
||
}
|
||
this.$emit('input', outputDate);
|
||
this.$emit('change', outputDate);
|
||
},
|
||
getCurrentStatsDateType () {
|
||
return this.dateType;
|
||
}
|
||
},
|
||
computed: {
|
||
validTypeList () {
|
||
return allTypeList.filter((item) => {
|
||
return this.allowTypes.indexOf(item.value) !== -1;
|
||
});
|
||
},
|
||
/**
|
||
* el-date-picker使用的type
|
||
*/
|
||
innerDateType () {
|
||
switch (this.dateType) {
|
||
case 'day': return this.isRange ? 'daterange' : 'date';
|
||
case 'month': return this.isRange ? 'monthrange' : 'month';
|
||
case 'year': return this.isRange ? 'monthrange' : 'year';
|
||
default: return this.isRange ? 'daterange' : 'date';
|
||
}
|
||
},
|
||
/**
|
||
* el-date-picker使用的format
|
||
*/
|
||
innerDateFormat () {
|
||
switch (this.dateType) {
|
||
case 'day': return 'yyyy-MM-dd';
|
||
case 'month': return 'yyyy-MM';
|
||
case 'year': return 'yyyy';
|
||
default: return 'yyyy-MM-dd';
|
||
}
|
||
}
|
||
},
|
||
watch: {
|
||
value: {
|
||
handler: function (newValue, oldValue) {
|
||
if (newValue == null || newValue.length < 2) {
|
||
this.currentDates = this.isRange ? [] : undefined;
|
||
} else {
|
||
if (this.currentDates == null) this.currentDates = [];
|
||
if (this.isRange) {
|
||
this.currentDates = [
|
||
parseDate(newValue[0], this.valueFormat),
|
||
parseDate(newValue[1], this.valueFormat)
|
||
];
|
||
} else {
|
||
this.currentDates = parseDate(newValue[0], this.valueFormat);
|
||
}
|
||
}
|
||
},
|
||
immediate: true,
|
||
deep: true
|
||
},
|
||
dateType: {
|
||
handler: function (newValue, oldValue) {
|
||
if (this.allowTypes.indexOf(this.dateType) === -1) {
|
||
this.dateType = this.allowTypes[0] || 'day';
|
||
}
|
||
this.emitChange();
|
||
},
|
||
immediate: true
|
||
},
|
||
defaultDateType: {
|
||
handler: function (newValue, oldValue) {
|
||
if (this.allowTypes.indexOf(newValue) !== -1) {
|
||
this.dateType = newValue;
|
||
} else {
|
||
this.dateType = this.allowTypes[0];
|
||
}
|
||
}
|
||
},
|
||
isRange: {
|
||
handler: function (newValue, oldValue) {
|
||
let temp;
|
||
if (newValue) {
|
||
temp = [this.currentDates, this.currentDates];
|
||
} else {
|
||
temp = this.currentDates[0];
|
||
}
|
||
|
||
this.currentDates = temp;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.date-range {
|
||
display: flex;
|
||
}
|
||
</style>
|