@@ -80,9 +64,10 @@
}
]"
@mouseenter="selectDate(date, $event)"
+ @mouseleave="onMouseLeave"
>
{{ date.day }}
-
+
休
休
@@ -295,6 +280,7 @@ const selectedDate = ref(null);
const today = new Date();
const showTooltip = ref(false);
const tooltipPosition = ref({ x: 0, y: 0 });
+const hoverTimer = ref(null);
// 营期设置相关
const showCampModal = ref(false);
@@ -473,22 +459,31 @@ const nextMonth = async () => {
}
};
-// 方法:选择日期
+// 方法:选择日期(鼠标悬停延迟触发)
const selectDate = (date, event) => {
selectedDate.value = date;
+ // 清除之前的定时器
+ if (hoverTimer.value) {
+ clearTimeout(hoverTimer.value);
+ }
+
// 只有当日期有事件时才显示悬浮框
if (event && date.hasEvent) {
tooltipPosition.value = {
x: event.clientX + 10,
y: event.clientY - 10
};
- showTooltip.value = true;
- // 3秒后自动隐藏
- setTimeout(() => {
- showTooltip.value = false;
- }, 3000);
+ // 延迟500毫秒后显示悬浮框
+ hoverTimer.value = setTimeout(() => {
+ showTooltip.value = true;
+
+ // 3秒后自动隐藏
+ setTimeout(() => {
+ showTooltip.value = false;
+ }, 3000);
+ }, 500);
}
};
@@ -497,6 +492,15 @@ const hideTooltip = () => {
showTooltip.value = false;
};
+// 方法:鼠标离开日期单元格
+const onMouseLeave = () => {
+ // 清除延迟显示的定时器
+ if (hoverTimer.value) {
+ clearTimeout(hoverTimer.value);
+ hoverTimer.value = null;
+ }
+};
+
// 方法:显示历史记录
const showHistory = async () => {
try {
@@ -558,10 +562,14 @@ const switchToHistoryPeriod = async (period) => {
// 关闭历史营期弹框
showHistoryModal.value = false;
- // 重新获取营期数据以更新日历显示
- await CenterCampPeriodAdmin();
+ // 使用历史营期数据构建日历显示
+ mapHistoryPeriodToCalendar(period);
+
+ // 切换日历到历史营期的时间段
+ const startDate = new Date(period.startDate);
+ currentYear.value = startDate.getFullYear();
+ currentMonth.value = startDate.getMonth();
- alert(`已切换到第${period.periodNum}期历史营期`);
} else {
alert('切换历史营期失败,请重试');
}
@@ -580,6 +588,11 @@ const returnToCurrentPeriod = async () => {
// 重新获取当前营期数据
await CenterCampPeriodAdmin();
+ // 切换日历回到当前时间
+ const now = new Date();
+ currentYear.value = now.getFullYear();
+ currentMonth.value = now.getMonth();
+
alert('已返回当前营期');
} catch (error) {
console.error('返回当前营期失败:', error);
@@ -671,6 +684,9 @@ const isRestDay = (dateStr) => {
// 方法:检查营期是否应该结束
const shouldShowFinishCamp = () => {
+ // 如果正在查看历史营期,不显示结束营期按钮
+ if (isViewingHistory.value) return false;
+
if (isCampFinished.value) return false;
// 检查是否有营期相关的事件
@@ -908,6 +924,71 @@ const parseDateRange = (dateRangeStr) => {
};
};
+// 方法:将历史营期数据映射到日历
+const mapHistoryPeriodToCalendar = (historyPeriod) => {
+ // 清除之前的营期相关事件
+ events.value = events.value.filter(event => !event.isCampEvent);
+
+ let eventId = events.value.length + 1;
+ const startDate = new Date(historyPeriod.startDate);
+ const endDate = new Date(historyPeriod.endDate);
+
+ // 计算营期总天数
+ const totalDays = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
+
+ let currentDate = new Date(startDate);
+
+ // 1. 添加接数据事件
+ for (let i = 0; i < historyPeriod.dataDays; i++) {
+ const dateStr = formatDateToString(currentDate);
+ events.value.push({
+ id: eventId++,
+ date: dateStr,
+ title: '接数据',
+ description: `第${historyPeriod.periodNum}期历史营期 - 数据接收阶段 (第${i + 1}天)`,
+ isCampEvent: true,
+ type: 'data'
+ });
+ currentDate.setDate(currentDate.getDate() + 1);
+ }
+
+ // 2. 添加课程事件(课1-4,连续4天)
+ const courses = ['课1', '课2', '课3', '课4'];
+ courses.forEach((courseTitle, index) => {
+ if (currentDate <= endDate) {
+ const dateStr = formatDateToString(currentDate);
+ events.value.push({
+ id: eventId++,
+ date: dateStr,
+ title: courseTitle,
+ description: `第${historyPeriod.periodNum}期历史营期 - ${courseTitle}阶段`,
+ isCampEvent: true,
+ type: 'course'
+ });
+ currentDate.setDate(currentDate.getDate() + 1);
+ }
+ });
+
+ // 3. 添加休息日事件(在营期结束前的几天)
+ const restStartDate = new Date(endDate);
+ restStartDate.setDate(endDate.getDate() - historyPeriod.restDays + 1);
+
+ for (let i = 0; i < historyPeriod.restDays; i++) {
+ const restDate = new Date(restStartDate);
+ restDate.setDate(restStartDate.getDate() + i);
+ const dateStr = formatDateToString(restDate);
+
+ events.value.push({
+ id: eventId++,
+ date: dateStr,
+ title: '休息',
+ description: `第${historyPeriod.periodNum}期历史营期 - 休息日 (第${i + 1}天)`,
+ isCampEvent: true,
+ type: 'rest'
+ });
+ }
+};
+
@@ -1376,6 +1457,28 @@ onMounted(async () => {
box-shadow: 0 2px 4px rgba(40, 167, 69, 0.3);
}
+/* 历史营期事件点样式 */
+.event-dot.history-period {
+ opacity: 0.6;
+ border: 2px solid #6c757d;
+ transform: scale(0.8);
+}
+
+.event-dot.history-period.event-data {
+ background: #6c757d;
+ box-shadow: 0 2px 4px rgba(108, 117, 125, 0.3);
+}
+
+.event-dot.history-period.event-course {
+ background: #6c757d;
+ box-shadow: 0 2px 4px rgba(108, 117, 125, 0.3);
+}
+
+.event-dot.history-period.event-rest {
+ background: #6c757d;
+ box-shadow: 0 2px 4px rgba(108, 117, 125, 0.3);
+}
+
/* 休息日文字样式 */
.rest-text {
position: absolute;
@@ -1702,40 +1805,5 @@ onMounted(async () => {
box-shadow: 0 2px 4px rgba(40, 167, 69, 0.2);
}
-/* 营期状态指示器样式 */
-.period-indicator {
- display: flex;
- justify-content: center;
- padding: 8px 0;
- margin-bottom: 8px;
- border-bottom: 1px solid #e9ecef;
-}
-.history-indicator,
-.current-indicator {
- display: flex;
- align-items: center;
- gap: 6px;
- padding: 6px 12px;
- border-radius: 20px;
- font-size: 13px;
- font-weight: 500;
-}
-
-.history-indicator {
- background: linear-gradient(135deg, #ffc107, #fd7e14);
- color: white;
- box-shadow: 0 2px 4px rgba(255, 193, 7, 0.3);
-}
-
-.current-indicator {
- background: linear-gradient(135deg, #28a745, #20c997);
- color: white;
- box-shadow: 0 2px 4px rgba(40, 167, 69, 0.3);
-}
-
-.history-indicator svg,
-.current-indicator svg {
- flex-shrink: 0;
-}
\ No newline at end of file