Files
pqs-9100_client/frontend/src/components/TimeControl/index.vue
2024-12-04 08:49:42 +08:00

319 lines
9.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class='time-control'>
<el-select
class='select'
v-model='timeUnit'
placeholder='选择时间单位'
@change='handleChange'
>
<!-- 采用 v-for 动态渲染 -->
<el-option
v-for='unit in timeUnits'
:key='unit.value'
:label='unit.label'
:value='unit.value'
></el-option>
</el-select>
<!-- 禁用时间选择器 -->
<div class='date-display'>
<el-date-picker
class='date-picker'
v-model='startDate'
type='date'
placeholder='起始时间'
@change='emitDateChange'
:disabled-date='disableStartDate'
:readonly="timeUnit != '自定义'"
></el-date-picker>
<el-text>~</el-text>
<el-date-picker
class='date-picker'
v-model='endDate'
type='date'
placeholder='结束时间'
@change='emitDateChange'
:disabled-date='disableEndDate'
:readonly="timeUnit !== '自定义'"
></el-date-picker>
</div>
<div class='date-display' v-if="timeUnit !== '自定义'">
<el-button
style='width: 10px;'
class='triangle-button'
type='primary'
@click='prevPeriod'
@change='emitDateChange'
>
<div class='left_triangle'></div>
</el-button>
<el-button class='triangle-button' type='primary' @click='goToCurrent'>
当前
</el-button>
<el-button
style='width: 10px;'
class='triangle-button'
type='primary'
@click='nextPeriod'
:disabled='isNextDisabled'
>
<div class='right_triangle'></div>
</el-button>
</div>
</div>
</template>
<script setup lang='ts'>
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: '月',
},
})
// 定义事件
const emit = defineEmits<{
(e: 'update-dates', startDate: string, endDate: string): void;
}>()
const timeUnit = ref<string>(props.default) // 默认选择
const startDate = ref<Date>(new Date()) // 起始日期
const endDate = ref<Date>(new Date()) // 结束日期
const isNextDisabled = ref<boolean>(false) // 控制下一周期按钮的禁用状态
const today = ref<Date>(new Date()) // 当前日期
// 过滤出可用的时间单位
const timeUnits = ref<TimeUnit[]>(
props.include.filter(unit => !props.exclude.includes(unit)).map(unit => ({
label: unit,
value: unit,
})),
)
// 发出日期变化事件
const emitDateChange = () => {
emit('update-dates', formatDate(startDate.value), formatDate(endDate.value))
}
// 在组件挂载时更新日期范围
onMounted(() => {
updateDateRange()
})
const handleChange = (unit: string) => {
// 根据选择的时间单位处理日期变化
if (unit !== '自定义') {
updateDateRange()
} else {
// 自定义选项逻辑
startDate.value = new Date(new Date().setDate(new Date().getDate() - 1))
endDate.value = new Date()
}
timeUnit.value = unit
// 确保开始时间和结束时间不为空
if (!startDate.value) {
startDate.value = new Date()
}
if (!endDate.value) {
endDate.value = new Date()
}
emitDateChange() // 变化时也发出更新事件
updateNextButtonStatus()
}
const updateDateRange = () => {
// 根据选择的时间单位计算起始和结束日期
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);
// // 确保结束日期不超过今天
// if (endDate.value > today.value) {
// endDate.value = new Date(today.value);
// endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999
// }
} 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);
// // 确保结束日期不超过今天
// if (endDate.value > today.value) {
// endDate.value = new Date(today.value);
// endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999
// }
} else if (timeUnit.value === '年') {
startDate.value = new Date(today.value.getFullYear(), 0, 1);
endDate.value = new Date(today.value.getFullYear(), 11, 31);
// // 确保结束日期不超过今天
// if (endDate.value > today.value) {
// endDate.value = new Date(today.value);
// endDate.value.setHours(23, 59, 59, 999); // 设置结束时间为今天的23:59:59.999
// }
}
// 确保开始时间和结束时间不为空
if (!startDate.value) {
startDate.value = new Date()
}
if (!endDate.value) {
endDate.value = new Date()
}
updateNextButtonStatus()
}
const getStartOfWeek = (date: Date) => {
const startOfWeek = new Date(date)
const day = startOfWeek.getDay()
const diff = day === 0 ? -6 : 1 - day // 星期天的情况
startOfWeek.setDate(startOfWeek.getDate() + diff)
return startOfWeek
}
const getEndOfWeek = (date: Date) => {
const endOfWeek = new Date(date)
const day = endOfWeek.getDay()
const diff = day === 0 ? 0 : 7 - day // 星期天的情况
endOfWeek.setDate(endOfWeek.getDate() + diff)
// 获取今天的日期
const today = new Date();
today.setHours(23, 59, 59, 999); // 设置今天的结束时间23:59:59.999
// 返回不超过今天的结束时间
//return endOfWeek > today ? today : endOfWeek;
return endOfWeek
}
const prevPeriod = () => {
const prevStartDate = new Date(startDate.value)
const prevEndDate = new Date(endDate.value)
if (timeUnit.value === '日') {
prevStartDate.setDate(prevStartDate.getDate() - 1)
prevEndDate.setDate(prevEndDate.getDate() - 1)
} else if (timeUnit.value === '周') {
prevStartDate.setDate(prevStartDate.getDate() - 7)
prevEndDate.setDate(prevEndDate.getDate() - 7)
} else if (timeUnit.value === '月') {
prevStartDate.setMonth(prevStartDate.getMonth() - 1)
prevEndDate.setMonth(prevEndDate.getMonth() - 1)
} else if (timeUnit.value === '季度') {
prevStartDate.setMonth(prevStartDate.getMonth() - 3)
prevEndDate.setMonth(prevEndDate.getMonth() - 3)
} else if (timeUnit.value === '年') {
prevStartDate.setFullYear(prevStartDate.getFullYear() - 1)
prevEndDate.setFullYear(prevEndDate.getFullYear() - 1)
}
startDate.value = prevStartDate
endDate.value = prevEndDate
updateNextButtonStatus()
}
const goToCurrent = () => {
if (timeUnit.value !== '自定义') {
updateDateRange() // 更新为当前选择时间单位的时间范围
}
}
const nextPeriod = () => {
const nextStartDate = new Date(startDate.value)
const nextEndDate = new Date(endDate.value)
if (timeUnit.value === '日') {
nextStartDate.setDate(nextStartDate.getDate() + 1)
nextEndDate.setDate(nextEndDate.getDate() + 1)
} else if (timeUnit.value === '周') {
nextStartDate.setDate(nextStartDate.getDate() + 7)
nextEndDate.setDate(nextEndDate.getDate() + 7)
} else if (timeUnit.value === '月') {
nextStartDate.setMonth(nextStartDate.getMonth() + 1)
nextEndDate.setMonth(nextEndDate.getMonth() + 1)
} else if (timeUnit.value === '季度') {
nextStartDate.setMonth(nextStartDate.getMonth() + 3)
nextEndDate.setMonth(nextStartDate.getMonth() + 3)
} else if (timeUnit.value === '年') {
nextStartDate.setFullYear(nextStartDate.getFullYear() + 1)
nextEndDate.setFullYear(nextEndDate.getFullYear() + 1)
}
startDate.value = nextStartDate
endDate.value = nextEndDate
updateNextButtonStatus()
}
const updateNextButtonStatus = () => {
// 更新下一个按钮的禁用状态
const maxDate = new Date() // 假设最新日期为今天
// 将 maxDate 设置为当天的开始时间
maxDate.setHours(0, 0, 0, 0)
// 将 endDate 设置为当天的开始时间并进行比较
const endDateAdjusted = new Date(endDate.value)
endDateAdjusted.setHours(0, 0, 0, 0)
// 仅比较日期部分
isNextDisabled.value = endDateAdjusted >= maxDate
emitDateChange() // 变化时也发出更新事件
}
// 限制开始日期不能选择超过当前日期
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)
}
// 格式化日期yyyy-mm-dd
function formatDate(date: Date | null): string {
if (!date) {
return '';
}
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
</script>
<style scoped lang='scss'>
@import "./index.scss";
</style>