2024-10-22 13:19:13 +08:00
|
|
|
|
<template>
|
2024-10-22 14:47:25 +08:00
|
|
|
|
<div class='time-control'>
|
2024-10-22 13:19:13 +08:00
|
|
|
|
<el-select
|
2024-10-22 14:47:25 +08:00
|
|
|
|
class='select'
|
|
|
|
|
|
v-model='timeUnit'
|
|
|
|
|
|
placeholder='选择时间单位'
|
|
|
|
|
|
@change='handleChange'
|
2024-10-22 13:19:13 +08:00
|
|
|
|
>
|
2024-10-23 19:30:11 +08:00
|
|
|
|
<!-- 采用 v-for 动态渲染 -->
|
|
|
|
|
|
<el-option
|
|
|
|
|
|
v-for="unit in timeUnits"
|
|
|
|
|
|
:key="unit.value"
|
|
|
|
|
|
:label="unit.label"
|
|
|
|
|
|
:value="unit.value"
|
|
|
|
|
|
></el-option>
|
2024-10-22 13:19:13 +08:00
|
|
|
|
</el-select>
|
|
|
|
|
|
|
2024-10-22 14:47:25 +08:00
|
|
|
|
<!-- 禁用时间选择器 -->
|
|
|
|
|
|
<div class='date-display'>
|
2024-10-22 13:19:13 +08:00
|
|
|
|
<el-date-picker
|
2024-10-22 14:47:25 +08:00
|
|
|
|
class='date-picker'
|
|
|
|
|
|
v-model='startDate'
|
|
|
|
|
|
type='date'
|
|
|
|
|
|
placeholder='起始时间'
|
2024-10-28 08:39:09 +08:00
|
|
|
|
@change="emitDateChange"
|
2024-10-23 19:30:11 +08:00
|
|
|
|
:disabled-date="disableStartDate"
|
2024-10-22 14:47:25 +08:00
|
|
|
|
:readonly="timeUnit != '自定义'"
|
2024-10-22 13:19:13 +08:00
|
|
|
|
></el-date-picker>
|
|
|
|
|
|
<el-text>~</el-text>
|
|
|
|
|
|
<el-date-picker
|
2024-10-22 14:47:25 +08:00
|
|
|
|
class='date-picker'
|
|
|
|
|
|
v-model='endDate'
|
|
|
|
|
|
type='date'
|
|
|
|
|
|
placeholder='结束时间'
|
2024-10-28 08:39:09 +08:00
|
|
|
|
@change="emitDateChange"
|
2024-10-23 19:30:11 +08:00
|
|
|
|
:disabled-date="disableEndDate"
|
2024-10-22 13:19:13 +08:00
|
|
|
|
:readonly="timeUnit !== '自定义'"
|
|
|
|
|
|
></el-date-picker>
|
|
|
|
|
|
</div>
|
2024-10-22 14:47:25 +08:00
|
|
|
|
<div class='date-display' v-if="timeUnit !== '自定义'">
|
2024-10-22 13:19:13 +08:00
|
|
|
|
<el-button
|
2024-10-22 14:47:25 +08:00
|
|
|
|
style='width: 10px;'
|
|
|
|
|
|
class='triangle-button'
|
|
|
|
|
|
type='primary'
|
|
|
|
|
|
@click='prevPeriod'
|
2024-10-29 11:17:04 +08:00
|
|
|
|
@change="emitDateChange"
|
2024-10-22 13:19:13 +08:00
|
|
|
|
>
|
2024-10-22 14:47:25 +08:00
|
|
|
|
<div class='left_triangle'></div>
|
2024-10-22 13:19:13 +08:00
|
|
|
|
</el-button>
|
2024-10-29 11:17:04 +08:00
|
|
|
|
<el-button class='triangle-button' type='primary' @click='goToCurrent' >
|
2024-10-28 08:39:09 +08:00
|
|
|
|
当前
|
2024-10-22 13:19:13 +08:00
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button
|
2024-10-22 14:47:25 +08:00
|
|
|
|
style='width: 10px;'
|
|
|
|
|
|
class='triangle-button'
|
|
|
|
|
|
type='primary'
|
|
|
|
|
|
@click='nextPeriod'
|
|
|
|
|
|
:disabled='isNextDisabled'
|
2024-10-22 13:19:13 +08:00
|
|
|
|
>
|
2024-10-22 14:47:25 +08:00
|
|
|
|
<div class='right_triangle'></div>
|
2024-10-22 13:19:13 +08:00
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
2024-10-23 19:30:11 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2024-10-28 08:39:09 +08:00
|
|
|
|
import { ref ,onMounted, defineProps, defineEmits } from 'vue';
|
|
|
|
|
|
|
|
|
|
|
|
// 定义时间单位的类型
|
|
|
|
|
|
interface TimeUnit {
|
|
|
|
|
|
label: string;
|
|
|
|
|
|
value: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 定义组件的props,包含包括和排除的时间单位
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
include: {
|
|
|
|
|
|
type: Array as () => string[],
|
|
|
|
|
|
default: () => ['日', '周', '月', '季度', '年', '自定义'],
|
|
|
|
|
|
},
|
|
|
|
|
|
exclude: {
|
|
|
|
|
|
type: Array as () => string[],
|
|
|
|
|
|
default: () => [],
|
|
|
|
|
|
},
|
|
|
|
|
|
default: {
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
default: '日',
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
2024-10-23 19:30:11 +08:00
|
|
|
|
|
2024-10-28 08:39:09 +08:00
|
|
|
|
// 定义事件
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
|
|
(e: 'update-dates', startDate: Date, endDate: Date): void;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
const timeUnit = ref<string>(props.default); // 默认选择
|
2024-10-23 19:30:11 +08:00
|
|
|
|
const startDate = ref<Date>(new Date()); // 起始日期
|
|
|
|
|
|
const endDate = ref<Date>(new Date()); // 结束日期
|
|
|
|
|
|
const isNextDisabled = ref<boolean>(false); // 控制下一周期按钮的禁用状态
|
|
|
|
|
|
const today = ref<Date>(new Date()); // 当前日期
|
2024-10-28 08:39:09 +08:00
|
|
|
|
// 过滤出可用的时间单位
|
|
|
|
|
|
const timeUnits = ref<TimeUnit[]>(
|
|
|
|
|
|
props.include.filter(unit => !props.exclude.includes(unit)).map(unit => ({
|
|
|
|
|
|
label: unit,
|
|
|
|
|
|
value: unit,
|
|
|
|
|
|
}))
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 发出日期变化事件
|
|
|
|
|
|
const emitDateChange = () => {
|
|
|
|
|
|
emit('update-dates', startDate.value, endDate.value);
|
2024-10-29 11:17:04 +08:00
|
|
|
|
//console.log('emitDateChange', startDate.value, endDate.value);
|
2024-10-28 08:39:09 +08:00
|
|
|
|
};
|
2024-10-23 19:30:11 +08:00
|
|
|
|
|
|
|
|
|
|
// 在组件挂载时更新日期范围
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
updateDateRange();
|
|
|
|
|
|
});
|
|
|
|
|
|
const handleChange = (unit: string)=> {
|
2024-10-22 13:19:13 +08:00
|
|
|
|
// 根据选择的时间单位处理日期变化
|
2024-10-23 19:30:11 +08:00
|
|
|
|
if (unit !== '自定义') {
|
|
|
|
|
|
updateDateRange()
|
2024-10-22 13:19:13 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 自定义选项逻辑
|
2024-10-23 19:30:11 +08:00
|
|
|
|
startDate.value = new Date(new Date().setDate(new Date().getDate() - 1))
|
|
|
|
|
|
endDate.value = new Date()
|
2024-10-22 13:19:13 +08:00
|
|
|
|
}
|
2024-10-28 08:39:09 +08:00
|
|
|
|
timeUnit.value = unit;
|
|
|
|
|
|
emitDateChange(); // 变化时也发出更新事件
|
2024-10-23 19:30:11 +08:00
|
|
|
|
updateNextButtonStatus()
|
|
|
|
|
|
}
|
|
|
|
|
|
const updateDateRange = () => {
|
|
|
|
|
|
|
2024-10-22 13:19:13 +08:00
|
|
|
|
// 根据选择的时间单位计算起始和结束日期
|
2024-10-23 19:30:11 +08:00
|
|
|
|
if (timeUnit.value === '日') {
|
|
|
|
|
|
startDate.value = today.value
|
|
|
|
|
|
endDate.value = today.value
|
|
|
|
|
|
} else if (timeUnit.value === '周') {
|
|
|
|
|
|
startDate.value = getStartOfWeek(today.value)
|
|
|
|
|
|
endDate.value = getEndOfWeek(today.value)
|
|
|
|
|
|
} else if (timeUnit.value === '月') {
|
|
|
|
|
|
startDate.value = new Date(today.value.getFullYear(), today.value.getMonth(), 1)
|
|
|
|
|
|
endDate.value = new Date(today.value.getFullYear(), today.value.getMonth() + 1, 0)
|
|
|
|
|
|
} else if (timeUnit.value === '季度') {
|
|
|
|
|
|
const quarter = Math.floor(today.value.getMonth() / 3)
|
|
|
|
|
|
startDate.value = new Date(today.value.getFullYear(), quarter * 3, 1)
|
|
|
|
|
|
endDate.value = new Date(today.value.getFullYear(), quarter * 3 + 3, 0)
|
|
|
|
|
|
} else if (timeUnit.value === '年') {
|
|
|
|
|
|
startDate.value = new Date(today.value.getFullYear(), 0, 1)
|
|
|
|
|
|
endDate.value = new Date(today.value.getFullYear(), 11, 31)
|
2024-10-22 13:19:13 +08:00
|
|
|
|
}
|
2024-10-23 19:30:11 +08:00
|
|
|
|
updateNextButtonStatus()
|
|
|
|
|
|
}
|
|
|
|
|
|
const getStartOfWeek =(date:Date)=> {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
const startOfWeek = new Date(date)
|
|
|
|
|
|
const day = startOfWeek.getDay()
|
|
|
|
|
|
const diff = day === 0 ? -6 : 1 - day // 星期天的情况
|
|
|
|
|
|
startOfWeek.setDate(startOfWeek.getDate() + diff)
|
|
|
|
|
|
return startOfWeek
|
2024-10-23 19:30:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
const getEndOfWeek =(date:Date) =>{
|
2024-10-22 14:47:25 +08:00
|
|
|
|
const endOfWeek = new Date(date)
|
|
|
|
|
|
const day = endOfWeek.getDay()
|
|
|
|
|
|
const diff = day === 0 ? 0 : 7 - day // 星期天的情况
|
|
|
|
|
|
endOfWeek.setDate(endOfWeek.getDate() + diff)
|
|
|
|
|
|
return endOfWeek
|
2024-10-23 19:30:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
const prevPeriod =()=> {
|
|
|
|
|
|
const prevStartDate = new Date(startDate.value)
|
|
|
|
|
|
const prevEndDate = new Date(endDate.value)
|
2024-10-22 14:47:25 +08:00
|
|
|
|
|
2024-10-23 19:30:11 +08:00
|
|
|
|
if (timeUnit.value === '日') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
prevStartDate.setDate(prevStartDate.getDate() - 1)
|
|
|
|
|
|
prevEndDate.setDate(prevEndDate.getDate() - 1)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '周') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
prevStartDate.setDate(prevStartDate.getDate() - 7)
|
|
|
|
|
|
prevEndDate.setDate(prevEndDate.getDate() - 7)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '月') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
prevStartDate.setMonth(prevStartDate.getMonth() - 1)
|
|
|
|
|
|
prevEndDate.setMonth(prevEndDate.getMonth() - 1)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '季度') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
prevStartDate.setMonth(prevStartDate.getMonth() - 3)
|
|
|
|
|
|
prevEndDate.setMonth(prevEndDate.getMonth() - 3)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '年') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
prevStartDate.setFullYear(prevStartDate.getFullYear() - 1)
|
|
|
|
|
|
prevEndDate.setFullYear(prevEndDate.getFullYear() - 1)
|
2024-10-22 13:19:13 +08:00
|
|
|
|
}
|
2024-10-22 14:47:25 +08:00
|
|
|
|
|
2024-10-23 19:30:11 +08:00
|
|
|
|
startDate.value = prevStartDate
|
|
|
|
|
|
endDate.value = prevEndDate
|
|
|
|
|
|
updateNextButtonStatus()
|
|
|
|
|
|
}
|
|
|
|
|
|
const goToCurrent =()=> {
|
|
|
|
|
|
if (timeUnit.value !== '自定义') {
|
|
|
|
|
|
updateDateRange() // 更新为当前选择时间单位的时间范围
|
2024-10-22 13:19:13 +08:00
|
|
|
|
}
|
2024-10-23 19:30:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
const nextPeriod = ()=> {
|
|
|
|
|
|
const nextStartDate = new Date(startDate.value)
|
|
|
|
|
|
const nextEndDate = new Date(endDate.value)
|
2024-10-22 14:47:25 +08:00
|
|
|
|
|
2024-10-23 19:30:11 +08:00
|
|
|
|
if (timeUnit.value === '日') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
nextStartDate.setDate(nextStartDate.getDate() + 1)
|
|
|
|
|
|
nextEndDate.setDate(nextEndDate.getDate() + 1)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '周') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
nextStartDate.setDate(nextStartDate.getDate() + 7)
|
|
|
|
|
|
nextEndDate.setDate(nextEndDate.getDate() + 7)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '月') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
nextStartDate.setMonth(nextStartDate.getMonth() + 1)
|
|
|
|
|
|
nextEndDate.setMonth(nextEndDate.getMonth() + 1)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '季度') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
nextStartDate.setMonth(nextStartDate.getMonth() + 3)
|
|
|
|
|
|
nextEndDate.setMonth(nextStartDate.getMonth() + 3)
|
2024-10-23 19:30:11 +08:00
|
|
|
|
} else if (timeUnit.value === '年') {
|
2024-10-22 14:47:25 +08:00
|
|
|
|
nextStartDate.setFullYear(nextStartDate.getFullYear() + 1)
|
|
|
|
|
|
nextEndDate.setFullYear(nextEndDate.getFullYear() + 1)
|
2024-10-22 13:19:13 +08:00
|
|
|
|
}
|
2024-10-22 14:47:25 +08:00
|
|
|
|
|
2024-10-23 19:30:11 +08:00
|
|
|
|
startDate.value = nextStartDate
|
|
|
|
|
|
endDate.value = nextEndDate
|
|
|
|
|
|
updateNextButtonStatus()
|
|
|
|
|
|
}
|
|
|
|
|
|
const updateNextButtonStatus =()=> {
|
2024-10-22 13:19:13 +08:00
|
|
|
|
// 更新下一个按钮的禁用状态
|
2024-10-22 14:47:25 +08:00
|
|
|
|
const maxDate = new Date() // 假设最新日期为今天
|
2024-10-23 19:30:11 +08:00
|
|
|
|
// 将 maxDate 设置为当天的开始时间
|
|
|
|
|
|
maxDate.setHours(0, 0, 0, 0);
|
|
|
|
|
|
// 将 endDate 设置为当天的开始时间并进行比较
|
|
|
|
|
|
const endDateAdjusted = new Date(endDate.value);
|
|
|
|
|
|
endDateAdjusted.setHours(0, 0, 0, 0);
|
|
|
|
|
|
// 仅比较日期部分
|
|
|
|
|
|
isNextDisabled.value = endDateAdjusted >= maxDate;
|
2024-10-29 11:17:04 +08:00
|
|
|
|
emitDateChange(); // 变化时也发出更新事件
|
2024-10-23 19:30:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 限制开始日期不能选择超过当前日期
|
|
|
|
|
|
const disableStartDate = (date:Date)=> {
|
|
|
|
|
|
return date > today.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 限制结束日期不能超过当前日期且必须大于开始日期
|
|
|
|
|
|
const disableEndDate = (date:Date)=> {
|
|
|
|
|
|
if (timeUnit.value !== '自定义') return false; // 如果不是自定义时间单位,则不限制
|
|
|
|
|
|
const start = new Date(startDate.value);
|
|
|
|
|
|
return date > today.value || (start && date <= start);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-29 11:17:04 +08:00
|
|
|
|
|
2024-10-22 14:47:25 +08:00
|
|
|
|
|
2024-10-22 13:19:13 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
2024-10-22 14:47:25 +08:00
|
|
|
|
<style scoped lang='scss'>
|
2024-10-22 13:19:13 +08:00
|
|
|
|
@import "./index.scss";
|
|
|
|
|
|
</style>
|
2024-10-28 08:39:09 +08:00
|
|
|
|
|