动态时间段的禁用disabledDate
不知道大家遇到过这样的需求没? 每一行的开始日期和结束日期区间不能重叠,但是可以出现中断.如: 第一行开始时间-结束时间:2020.1-2020.3,下一行数据不能在1月到3月,可以为2020.5-2020.7.结束日期默认为至今(本来可以使用 daterange 的,就是因为这句话,避免不了了).点击添加按钮,可以在表格下方新增一行,操作同上.
本来自己想着还挺简单的,可是随着行数添加的越多,发现越复杂,没办法 需求已经确定了改是改不了了,硬刚吧!
实现的效果
点击添加一行,上面两行的已经选过的不能再选(图1),但是你点击已经选过的本行的是可以修改的(图2)
里面其实有好多小的细节,里面都有所处理的,直接上代码了,完整的
<template>
<div class="dateRange">
<div style="margin:20px 0;">
<el-button type="primary" @click="add">添加</el-button>
</div>
<el-table
:data="tableData"
style="width: 100%"
>
<el-table-column
prop="end_date"
label="模型选择"
>
<template slot-scope="scope">
<el-select v-model="scope.row.model_select" placeholder="请选择" style="width:100%;">
<el-option
v-for="item in modelList"
:key="item.indexId"
:label="item.indexName"
:value="item.indexId"
/>
</el-select>
</template>
</el-table-column>
<el-table-column
prop="start_date"
label="开始日期"
type="date"
>
<template slot-scope="scope">
<el-date-picker
v-model="scope.row.start_date"
type="date"
value-format="yyyy-MM-dd"
:picker-options="pickerStartOptions"
@focus="(...arg)=>changeStartDate(...arg,scope.$index,scope.row)"
/>
</template>
</el-table-column>
<el-table-column
prop="end_date"
label="结束日期"
type="date"
>
<template slot-scope="scope">
<el-date-picker
v-model="scope.row.end_date"
type="date"
value-format="yyyy-MM-dd"
:picker-options="pickerEndOptions"
@focus="(...arg)=>changeEndDate(...arg,scope.$index,scope.row)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import dayjs from 'dayjs'
export default {
name: 'Test',
props: {
// table 数据
dateRangeList: {
type: Array,
default: () => {
return []
}
},
// 模型选择的下拉框
modelList: {
type: Array,
default: () => {
return [{
indexId: '0',
indexName: '红烧肉'
}, {
indexId: '1',
indexName: '黄金糕'
}]
}
}
},
data() {
return {
tableData: [{ start_date: '2020-12-07',
end_date: '2020-12-18',
model_select: '0' },
{ start_date: '2020-11-08',
end_date: '2020-11-18',
model_select: '1' }
],
row: null,
rowIndex: null,
// 开始时间
pickerStartOptions: {
disabledDate: (time) => {
const obj = {}
for (let i = 0; i < this.tableData.length; i++) {
if (i !== this.rowIndex) {
// 第一次循环后 为了避免覆盖掉 用obj[time] ||
obj[time] = obj[time] || +dayjs(time).format('YYYYMMDD') >= +dayjs(this.tableData[i].start_date).format('YYYYMMDD') && +dayjs(time).format('YYYYMMDD') <= +dayjs(this.tableData[i].end_date).format('YYYYMMDD')
}
}
return obj[time]
}
},
// 结束时间
pickerEndOptions: {
disabledDate: (time) => {
const obj = {}
for (let i = 0; i < this.tableData.length; i++) {
if (i !== this.rowIndex) {
obj[time] = obj[time] || +dayjs(time).format('YYYYMMDD') >= +dayjs(this.tableData[i].start_date).format('YYYYMMDD') && +dayjs(time).format('YYYYMMDD') <= +dayjs(this.tableData[i].end_date).format('YYYYMMDD')
}
}
return obj[time]
}
}
}
},
watch: {
tableData: {
deep: true,
handler(val) {
console.log('本来想监听排序一下', val)
}
}
},
created() {
this.initList()
},
methods: {
// 初始化表格数据,回显已经保存的数据
initList() {
this.dateRangeList.forEach(item => {
this.tableData.push(item)
})
},
// 数组按照时间排序函数
arrSort(val) {
return val.sort(function(a, b) {
return +dayjs(a.start_date).format('YYYYMMDD') - +dayjs(b.start_date).format('YYYYMMDD')
})
},
// 添加按钮
add() {
const obj = {
start_date: '',
end_date: '',
model_select: ''
}
this.row = this.tableData[this.tableData.length]
this.rowIndex = this.tableData.length
this.tableData.push(obj)
this.arrSort(this.tableData)
},
// 选择/获取焦点开始时间
changeStartDate(val, idx, row) {
this.row = row
this.rowIndex = idx
this.changeDate(val, idx, row)
},
// 选择获取焦点结束时间
changeEndDate(val, idx, row) {
this.row = row
this.rowIndex = idx
this.changeDate(val, idx, row)
},
// 时间重叠判断方法
changeDate(val, idx, row) {
this.tableData.find((item, index) => {
if ((index !== idx) && row.start_date && row.end_date) {
// 之前选择的时间区间只要在新选择的时间区间内,属于重叠
const judge01 = +dayjs(row.start_date).format('YYYYMMDD') <= +dayjs(item.start_date).format('YYYYMMDD') && +dayjs(item.start_date).format('YYYYMMDD') <= +dayjs(row.end_date).format('YYYYMMDD')
const judge02 = +dayjs(row.start_date).format('YYYYMMDD') <= +dayjs(item.end_date).format('YYYYMMDD') && +dayjs(item.end_date).format('YYYYMMDD') <= +dayjs(row.end_date).format('YYYYMMDD')
if (judge01 && judge02) {
this.$message({
type: 'error',
message: '时间区间重叠,请重新选择'
})
this.tableData[idx].start_date = ''
this.tableData[idx].end_date = ''
}
}
})
// 两个都选择好了 排下序
if (row.start_date && row.end_date) {
this.arrSort(this.tableData)
}
},
// 删除 按钮
handleDelete(index, row) {
this.tableData.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.dateRange{
.el-table td {
padding:2px 0;
}
}
</style>
这只是本人做的一个小demo,自己测的没啥问题,如果你需要就拿走,如果有什么问题,欢迎提出大家一块更正