Files
AIProd/pages/Launches/components/OptionDates.vue
2025-10-31 15:58:11 +08:00

319 lines
8.0 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="date-picker-core">
<!-- 日期// 选择区 -->
<div class="picker-container">
<!-- 日模式 -->
<div v-if="mode === 'Daily'" class="daily-picker">
<HorizontalDateList>
<button
style="width: 36px"
v-for="day in dailyDays"
:key="day.dateStr"
:class="{ 'selected': day.dateStr === selectedDate }"
@click="handleSelect(day.dateStr)"
>{{ day.day }}</button>
</HorizontalDateList>
</div>
<!-- 周模式 -->
<div v-else-if="mode === 'Weekly'" class="weekly-picker">
<HorizontalDateList>
<button
style="margin: 0 30px; width: 105px"
v-for="week in weeklyRanges"
:key="week.start"
:class="{ 'selected': week.start === selectedDate[0] && week.end === selectedDate[1] }"
@click="handleSelect([week.start, week.end])"
>{{ week.label }}</button>
</HorizontalDateList>
</div>
<!-- 月模式 -->
<div v-else class="monthly-picker">
<HorizontalDateList>
<button
style="margin: 0 9px; width: 55px"
v-for="(monthAbbr, index) in monthAbbrs"
:key="index"
:class="{ 'selected': (index + 1) === selectedMonth }"
@click="handleMonthSelect(index + 1)"
>{{ monthAbbr }}</button>
</HorizontalDateList>
</div>
</div>
</div>
</template>
<script>
import HorizontalDateList from '@/components/HorizontalDateList.vue';
export default {
name: 'OptionDates',
components: {
HorizontalDateList
},
props: {
// 当前年份,由外部传入
year: {
type: Number,
required: true
},
// 当前模式,由外部传入 (Daily, Weekly, Monthly)
mode: {
type: String,
required: true,
validator: (val) => ['Daily', 'Weekly', 'Monthly'].includes(val)
},
// 日模式下的当前月份,由外部传入
month: {
type: Number,
default: () => new Date().getMonth() + 1,
validator: (val) => val >= 1 && val <= 12
}
},
data() {
return {
selectedDate: this.mode === 'Daily' ? '' : ['', ''], // 选中的日期/日期范围
selectedMonth: this.month // 月模式下选中的月份
};
},
computed: {
// 日模式:生成"当前年月"的所有日期
dailyDays() {
const daysInMonth = this.getDaysInMonth(this.year, this.month);
return Array.from({ length: daysInMonth }, (_, i) => {
const day = i + 1;
const date = new Date(this.year, this.month - 1, day);
return {
day,
dateStr: this.formatDate(date)
};
});
},
// 周模式:生成"当前年份"的所有完整周区间
weeklyRanges() {
return this.getWeekRanges(this.year);
},
// 月模式12个月份的英文简写
monthAbbrs() {
return ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
}
},
created() {
// 组件创建时自动选中当前日期或周
this.autoSelectCurrentDate();
},
methods: {
// 自动选中当前日期或周
autoSelectCurrentDate(shouldEmit = true) {
const now = new Date();
const currentYear = now.getFullYear();
const currentMonth = now.getMonth() + 1;
const currentDateStr = this.formatDate(now);
// 只有当年份和月份匹配当前日期时才自动选中
if (this.year === currentYear) {
if (this.mode === 'Daily' && this.month === currentMonth) {
this.selectedDate = currentDateStr;
if (shouldEmit) {
this.$emit('select', currentDateStr);
}
} else if (this.mode === 'Weekly') {
// 找到当前日期所在的周
const currentWeek = this.getWeekForDate(now);
if (currentWeek) {
this.selectedDate = [currentWeek.start, currentWeek.end];
if (shouldEmit) {
this.$emit('select', [currentWeek.start, currentWeek.end]);
}
}
} else if (this.mode === 'Monthly') {
// 月模式下自动选中当前月并导出日期范围
this.selectedMonth = currentMonth;
const [start, end] = this.getMonthRange(this.year, currentMonth);
if (shouldEmit) {
this.$emit('select', [start, end]);
}
}
}
},
// 获取指定日期所在的周
getWeekForDate(date) {
const weeks = this.getWeekRanges(this.year);
const dateStr = this.formatDate(date);
for (const week of weeks) {
// 检查日期是否在该周范围内
if (dateStr >= week.start && dateStr <= week.end) {
return week;
}
}
return null;
},
// 处理日/周模式的选择
handleSelect(value) {
this.selectedDate = value;
this.$emit('select', value);
},
// 处理月模式的选择
handleMonthSelect(month) {
this.selectedMonth = month;
const [start, end] = this.getMonthRange(this.year, month);
this.$emit('select', [start, end]);
},
// 辅助获取某月的天数month1-12
getDaysInMonth(year, month) {
return new Date(year, month, 0).getDate();
},
// 辅助:格式化日期为 yyyy-mm-dd
formatDate(date) {
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}`;
},
// 辅助获取某月的首尾日期month1-12
getMonthRange(year, month) {
const start = new Date(year, month - 1, 1);
const end = new Date(year, month, 0);
return [this.formatDate(start), this.formatDate(end)];
},
// 辅助:获取某年的所有完整周区间(假设周从周日开始,到周六结束)
getWeekRanges(year) {
const ranges = [];
let currentDate = new Date(year, 0, 1); // 当年1月1日
// 找到第一个周日(作为周起始)
while (currentDate.getDay() !== 0) {
currentDate.setDate(currentDate.getDate() + 1);
}
// 生成所有"结束日期在当年"的完整周
while (currentDate.getFullYear() === year) {
const start = new Date(currentDate);
const end = new Date(currentDate);
end.setDate(end.getDate() + 6); // 周日到周六共7天
if (end.getFullYear() === year) { // 确保周结束在当年
ranges.push({
label: `${this.monthAbbrs[start.getMonth()]} ${start.getDate()}-${end.getDate()}`,
start: this.formatDate(start),
end: this.formatDate(end)
});
}
currentDate.setDate(currentDate.getDate() + 7); // 下一周
}
return ranges;
},
// 重置选择状态
resetSelection() {
if (this.mode === 'Daily') {
this.selectedDate = '';
} else if (this.mode === 'Weekly') {
this.selectedDate = ['', ''];
} else {
this.selectedMonth = this.month;
}
}
},
watch: {
// 监听年份变化,重置选择
year() {
this.resetSelection();
this.autoSelectCurrentDate();
},
mode: {
handler(newMode, oldMode) {
if (newMode !== oldMode) {
this.resetSelection();
// 切换模式时不立即触发 emit让组件自行处理
this.autoSelectCurrentDate(false);
// 通知子组件重新计算滚动状态
this.$nextTick(() => {
this.$children.forEach(child => {
if (child.$options.name === 'HorizontalDateList') {
child.updateScrollState();
}
});
});
}
},
immediate: true
},
month() {
if (this.mode === 'Daily') {
this.selectedDate = '';
}
this.autoSelectCurrentDate();
}
},
};
</script>
<style scoped>
.date-picker-core {
padding: 10px;
}
.picker-container {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding: 12px;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
background-color: #ffffff;
}
.daily-picker,
.weekly-picker,
.monthly-picker {
display: flex;
flex-wrap: wrap;
gap: 6px;
width: 100%;
}
.daily-picker button,
.weekly-picker button,
.monthly-picker button {
height: 36px;
text-align: center;
border: 1px solid #E2E8F0;
border-radius: 12px;
background: #fff;
cursor: pointer;
transition: all 0.2s;
font-size: 18px;
line-height: 22px;
color: #506179;
&:active {
opacity: 0.8;
}
}
.daily-picker button:hover,
.weekly-picker button:hover,
.monthly-picker button:hover {
border-color: #9ca3af;
}
.daily-picker button.selected,
.weekly-picker button.selected,
.monthly-picker button.selected {
color: #fff;
background: linear-gradient( 47deg, #2563EB 4%, #7B61FF 73%);
}
</style>