Files
AIProd/pages/Launches/components/OptionDates.vue

424 lines
11 KiB
Vue
Raw Permalink 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
class="bt-d"
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
class="bt-w"
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
class="bt-m"
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';
// 从 sessionStorage 获取缓存数据的辅助函数
function getCachedData() {
try {
const cachedData = sessionStorage.getItem('launches_search_cache');
return cachedData ? JSON.parse(cachedData) : null;
} catch (e) {
// console.error('获取缓存数据失败', e);
return null;
}
}
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() {
const cachedData = getCachedData();
let initialSelectedDate = this.mode === 'Daily' ? '' : ['', ''];
let initialSelectedMonth = this.month;
// 改进:优先从缓存中获取月份
if (cachedData && cachedData.currentMonth) {
initialSelectedMonth = cachedData.currentMonth;
}
// 如果有缓存数据,优先使用缓存数据
if (cachedData && cachedData.lastSelectedValue) {
try {
const lastSelectedValue = JSON.parse(cachedData.lastSelectedValue);
if (lastSelectedValue) {
if (this.mode === 'Daily' && typeof lastSelectedValue === 'string') {
initialSelectedDate = lastSelectedValue;
} else if (this.mode !== 'Daily' && Array.isArray(lastSelectedValue)) {
initialSelectedDate = lastSelectedValue;
}
}
} catch (e) {
console.error('解析缓存的lastSelectedValue失败', e);
}
}
return {
selectedDate: initialSelectedDate,
selectedMonth: initialSelectedMonth,
};
},
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() {
// 先从props获取月份避免初始为null
this.selectedMonth = this.month;
// 立即尝试获取缓存数据
this.updateFromCache();
// 添加一个小延迟再次尝试确保父组件的loadSearchCache执行完毕
setTimeout(() => {
this.updateFromCache();
// 强制更新UI确保选中状态正确显示
this.$forceUpdate();
}, 100);
},
methods: {
updateFromCache() {
const cachedData = getCachedData();
if (cachedData) {
// 优先从缓存获取currentMonth
if (cachedData.currentMonth) {
this.selectedMonth = cachedData.currentMonth;
}
// 处理lastSelectedValue
if (cachedData.lastSelectedValue) {
try {
const lastSelectedValue = JSON.parse(cachedData.lastSelectedValue);
if (lastSelectedValue) {
if (this.mode === 'Monthly') {
// 月模式下确保selectedMonth和lastSelectedValue一致
let monthToUse = this.selectedMonth;
// 如果缓存中有currentMonth优先使用
if (cachedData.currentMonth) {
monthToUse = cachedData.currentMonth;
this.selectedMonth = monthToUse;
}
// 生成与selectedMonth对应的日期范围
const [start, end] = this.getMonthRange(this.year, monthToUse);
// 使用$nextTick确保DOM更新后再发出事件
this.$nextTick(() => {
this.$emit('select', [start, end]);
this.$emit('month-change', monthToUse);
});
} else if ((this.mode === 'Daily' && typeof lastSelectedValue === 'string') ||
(this.mode !== 'Daily' && Array.isArray(lastSelectedValue))) {
this.$emit('select', lastSelectedValue);
}
}
} catch (e) {
console.error('使用缓存的lastSelectedValue失败', e);
}
}
}
},
// 自动选中当前日期或周
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;
// 强制更新UI
this.$forceUpdate();
const [start, end] = this.getMonthRange(this.year, month);
// 先发出month-change事件确保父组件的currentMonth先更新
this.$emit('month-change', month);
// 然后发出select事件更新lastSelectedValue包含正确的时间格式
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);
const formatDateWithTime = (date, isStart = true) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const time = isStart ? '00:00:00' : '23:59:59';
return `${year}-${month}-${day} ${time}`;
};
return [formatDateWithTime(start), formatDateWithTime(end, false)];
},
// 辅助:获取某年的所有完整周区间(假设周从周日开始,到周六结束)
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>
.bt-d {
width: 36px; margin: 0 10px;
}
.bt-w {
margin: 0 30px; width: 105px;
}
.bt-m {
margin: 0 20px; width: 55px;
}
.picker-container {
display: flex;
flex-wrap: wrap;
gap: 8px;
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>