From d6db489f801fe495930eb8261f7f968d05da1204 Mon Sep 17 00:00:00 2001 From: lbw_9527443 <780139497@qq.com> Date: Fri, 29 Aug 2025 17:18:44 +0800 Subject: [PATCH] =?UTF-8?q?fix(calendar):=20=E4=BC=98=E5=8C=96=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=90=A5=E6=9C=9F=E6=98=BE=E7=A4=BA=E5=92=8C=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除顶部状态指示器,改为通过事件点样式区分历史营期 - 添加鼠标悬停延迟显示和离开隐藏功能 - 实现历史营期数据映射到日历的功能 - 调整历史营期切换时的日期跳转逻辑 - 优化历史营期事件点的视觉样式 --- my-vue-app/src/utils/https.js | 4 +- .../views/secondTop/components/Calendar.vue | 190 ++++++++++++------ 2 files changed, 131 insertions(+), 63 deletions(-) diff --git a/my-vue-app/src/utils/https.js b/my-vue-app/src/utils/https.js index 29dbac9..ae8c3b2 100644 --- a/my-vue-app/src/utils/https.js +++ b/my-vue-app/src/utils/https.js @@ -5,8 +5,8 @@ import { useUserStore } from '@/stores/user' // 创建axios实例 const service = axios.create({ - // baseURL: 'https://mldash.nycjy.cn/' || '', // API基础路径,支持完整URL - baseURL: 'http://192.168.15.121:8890' || '', // API基础路径,支持完整URL + baseURL: 'https://mldash.nycjy.cn/' || '', // API基础路径,支持完整URL + // baseURL: 'http://192.168.15.121:8890' || '', // API基础路径,支持完整URL timeout: 100000, // 请求超时时间 headers: { 'Content-Type': 'application/json;charset=UTF-8' diff --git a/my-vue-app/src/views/secondTop/components/Calendar.vue b/my-vue-app/src/views/secondTop/components/Calendar.vue index 03cce9d..9c7fd05 100644 --- a/my-vue-app/src/views/secondTop/components/Calendar.vue +++ b/my-vue-app/src/views/secondTop/components/Calendar.vue @@ -41,22 +41,6 @@ - -
-
- - - - 正在查看:第{{ selectedHistoryPeriod.periodNum }}期历史营期 -
-
- - - - 当前营期 -
-
-
@@ -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