需求如下
添加上午、下午时间段选择
要在element日期组件旁边添加一个上午、下午的选项框,没有这样的插槽使用,所以自己封装一个组件。通过定位的方式,将两个选项框移动到该位置。
由于我这边项目父组件是先渲染好组件,再获取数据,所以出现这边子组件渲染好但是没有数据的情况,使用watch监听它的变化
子任务日期限制在父任务日期内
新建子任务的时候,获取父任务时间范围,传递给子组件进行限制
实现
数据库如下
父组件使用子组件:
<!--html-->
<datepickerAMPM
:dateRange="form.dateRange"
:startTimePeriod="form.startTimePeriod"
:endTimePeriod="form.endTimePeriod"
:parentStartTimeStr="parentStartTimeStr"
:parentEndTimeStr="parentEndTimeStr"
@changeDateRange="changeDateRange"
@changeStartP="changeStartP"
@changeEndP="changeEndP"
/>
父组件js
<!--js vue3 setup-->
import datepickerAMPM from "./datepickerAPMP.vue";
let form = ref({
dateRange: [],
startTimePeriod: '',
endTimePeriod: '',
})
新建时,form为空
编辑时,初始化...获取form数据
// 选择父任务后,清空时间
if (form.value.parentId){
form.value.dateRange = []
form.value.startTime = ''
form.value.endTime = ''
getTaskDetail(form.value.parentId)//获取父任务开始、结束时间,给子任务做一个时间限定
.then((res) => {
parentStartTimeStr.value = res.content.startTime
parentEndTimeStr.value = res.content.endTime
})
}else {
parentStartTimeStr.value = ''
parentEndTimeStr.value = ''
}
const changeDateRange = (e) => {
// console.log('e',e)
if (e.startTime!==''){
form.value.startTime = e.startTime
form.value.dateRange[0] = e.startTime
}
if (e.endTime!==''){
form.value.endTime = e.endTime
form.value.dateRange[1] = e.endTime
}
}
const changeStartP = (e) => {
if (e.startTimePeriod!==''){
form.value.startTimePeriod = e.startTimePeriod
// console.log('传输后的SP',form.value.startTimePeriod)
}
}
const changeEndP = (e) => {
if (e.endTimePeriod!==''){
form.value.endTimePeriod = e.endTimePeriod
// console.log('传输后的EP',form.value.startTimePeriod)
}
}
子组件html+js:
<template>
<div style="display: flex" class="selector">
<el-date-picker
style="width: 100%; height: 36px; "
v-model="theDateRange"
@change="changeDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
:disabled-date="pickerOptions0"
>
</el-date-picker>
<el-select
v-model="theStartTimePeriod"
placeholder="时间段"
size="small"
style="width: 85px;height: 36px;position: absolute;left: 30%;top: 2px;"
@change="changeStartP"
>
<el-option
v-for="item in period"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
<el-select
v-model="theEndTimePeriod"
placeholder="时间段"
size="small"
style="width: 85px;height: 36px;position: absolute;left:78%;top: 2px;"
@change="changeEndP"
>
<el-option
v-for="item in period"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</template>
<script>
import {watch, defineComponent, ref, toRefs} from "vue";
export default defineComponent({
name: "datepickerAMPM",
emits: ['changeDateRange','changeStartP','changeEndP'],
props: {
dateRange: {
type: Array,
default: [],
},
startTimePeriod: {
type: String,
default: '上午',
},
endTimePeriod: {
type: String,
default: '上午',
},
parentStartTimeStr: {
type: String,
default: '',
},
parentEndTimeStr: {
type: String,
default: '',
},
},
setup(props, ctx) {
// 转成响应式对象
const { dateRange,startTimePeriod,endTimePeriod } = toRefs(props);
const theDateRange = ref([])
const theStartTimePeriod = ref('')
const theEndTimePeriod = ref('')
// 父任务日期字符串,用于限制子任务日期范围
let theParentStartTimeStr = ref('')
let theParentEndTimeStr = ref('')
// 使用watch监听props的变化
// 监听时间范围
watch(dateRange, (newVal) => {
theDateRange.value = newVal;
});
// 监听开始时间段
watch(startTimePeriod, (newVal) => {
theStartTimePeriod.value = newVal;
});
// 监听结束时间段
watch(endTimePeriod, (newVal) => {
theEndTimePeriod.value = newVal;
});
// 用于传给父组件
let dateP = ref({
startTime: theDateRange[0]===''?'':theDateRange[0],
endTime: theDateRange[1]===''?'':theDateRange[1]
})
let datePS = ref({startTimePeriod: theStartTimePeriod.value})
let datePE = ref({endTimePeriod: theEndTimePeriod.value})
// 若有父任务的时间范围,将子任务时间范围限制在父任务的时间范围内
let pickerOptions0 = (time) => {
if (theParentStartTimeStr.value !== '' || theParentEndTimeStr.value !== '') {
let parentStartTime = new Date(theParentStartTimeStr.value) // 8.64e7就是一天的时间戳
let parentEndTime = new Date(theParentEndTimeStr.value)
// 返回限制日期 它开始时间是包含(限制)的,所以要减1天,让他不包含(限制)
return time.getTime() <= parentStartTime.getTime() - 8.64e7 || time.getTime() >= parentEndTime.getTime()
} else {
// 返回其余不限制的日期
return false
}
}
const period = ref([
{
value: '上午',
label: '上午',
},
{
value: '下午',
label: '下午',
}
])
const changeDateRange = (data) => {
if (data){
//data格式 {0: '2024-01-22', 1: '2024-01-24'}
dateP.value.startTime = data[0]
dateP.value.endTime = data[1]
if (theStartTimePeriod.value!=='') { // 有startP
dateP.value.startTimePeriod = theStartTimePeriod.value
}
if (theEndTimePeriod.value!=='') { // 有endP
dateP.value.endTimePeriod = theEndTimePeriod.value
}
}
// 任何时候都传出去,在外面判断
ctx.emit("changeDateRange", dateP.value);
};
const changeStartP = (sp) =>{
datePS.value.startTimePeriod = sp
// 任何时候都传出去,在外面判断
ctx.emit("changeStartP", datePS.value);
}
const changeEndP = (ep) =>{
datePE.value.endTimePeriod = ep
// 任何时候都传出去,在外面判断
ctx.emit("changeEndP", datePE.value);
}
return {
changeDateRange,
pickerOptions0,
theDateRange,
theStartTimePeriod,
theEndTimePeriod,
period,
changeStartP,
changeEndP,
dateP,
dateRange,
startTimePeriod,
endTimePeriod,
datePS,
datePE
};
},
});
</script>
<style scoped>
.selector /deep/ .el-range-editor--medium .el-range-input {
text-align: left;
margin-left: 10%;
/*color: red;*/
/*border: 1px red solid;*/
}
.selector /deep/ .el-select .el-input__inner {
border: 0;
}
</style>