From 3b28809f4efe59feda57d7564e5ea251eb574a02 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Tue, 22 Jul 2025 15:13:28 +0800
Subject: [PATCH] feat:日历添加月份选择

---
 src/views/wel/components/proportionStatic.vue |    1 
 src/views/wel/components/calendarBox.vue      |  264 +++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 176 insertions(+), 89 deletions(-)

diff --git a/src/views/wel/components/calendarBox.vue b/src/views/wel/components/calendarBox.vue
index b38e237..4e9db2c 100644
--- a/src/views/wel/components/calendarBox.vue
+++ b/src/views/wel/components/calendarBox.vue
@@ -1,10 +1,16 @@
 <template>
   <div class="calenBox">
-    <el-calendar ref="calendar" v-model="leftValue">
+    <el-calendar ref="calendar" v-model="currentMonth">
       <template #header="{ date }">
         <div>
           <img :src="caleft" alt="" @click="selectDate('prev-month')" />
-          <span>{{ date }}</span>
+          <el-date-picker
+            v-model="currentMonth"
+            type="month"
+            :clearable="false"
+            :prefix-icon="''"
+            @change="handleMonthChange"
+          />
           <img :src="caright" alt="" @click="selectDate('next-month')" />
         </div>
       </template>
@@ -33,92 +39,56 @@
 
 <script setup>
 import dayjs from 'dayjs';
-import { jobEventBar, getCalen } from '@/api/home/index';
+import { ref, watch, onMounted, nextTick } from 'vue';
+import { getCalen } from '@/api/home/index';
 import { useRouter } from 'vue-router';
 import ev1 from '@/assets/images/workbench/ev1.svg';
 import ev2 from '@/assets/images/workbench/ev2.svg';
 import caleft from '@/assets/images/workbench/caleft.png';
 import caright from '@/assets/images/workbench/caright.png';
-import { ElMessage } from 'element-plus';
-const calendar = ref();
+
 const router = useRouter();
+const calendar = ref();
 const events = ref({});
+const currentMonth = ref(new Date()); // 控制当前显示的月份
+const selectedDate = ref(null); // 控制选中的日期
 const params = ref({
   end_date: undefined,
   start_date: undefined,
 });
-const isCurrentMonth = (date) => {
-  return dayjs(date).isSame(dayjs(), 'month');
-};
-const leftValue = ref(null);
+
 const eventIcons = ref({
   'work-order': ev1,
   task: ev2,
 });
-const getEventIcon = type => {
-  return eventIcons.value[type] || eventIcons.value.default;
+// 检查日期是否是当前月份
+const isCurrentMonth = date => {
+  return dayjs(date).isSame(dayjs(), 'month');
 };
-function getCurrentMonthRange() {
-  return {
-    start_date: dayjs().startOf('month').format('YYYY-MM-DD HH:mm:ss'),
-    end_date: dayjs().endOf('month').format('YYYY-MM-DD HH:mm:ss'),
-  };
-}
-const selectDate = val => {
-  if (!calendar.value) return;
-  calendar.value.selectDate(val);
+// 处理月份选择器变化
+const handleMonthChange = val => {
+  const selectedDate = new Date(val);
+  const now = new Date();
+
+  // 如果是当前月份,则选中当天;否则不选中
+  if (
+    selectedDate.getFullYear() === now.getFullYear() &&
+    selectedDate.getMonth() === now.getMonth()
+  ) {
+    currentMonth.value = selectedDate;
+  } else {
+    currentMonth.value = selectedDate;
+    // 清除选中状态
+    nextTick(() => {
+      const selectedCells = document.querySelectorAll('.el-calendar-table td.is-selected');
+      selectedCells.forEach(cell => {
+        cell.classList.remove('is-selected');
+      });
+    });
+  }
 };
 
-// watch(
-//   () => leftValue.value,
-//   (newV, oldV) => {
-//     if (newV && oldV) {
-//       const newDate = dayjs(newV);
-//       params.value = {
-//         start_date: newDate.startOf('month').format('YYYY-MM-DD HH:mm:ss'),
-//         end_date: newDate.endOf('month').format('YYYY-MM-DD HH:mm:ss'),
-//       };
-//       getJobEventBar();
-//     }
-//   },
-//   { deep: true, immediate: true }
-// );
-watch(
-  () => leftValue.value,
-  (newV, oldV) => {
-    if (newV) {
-      const newDate = dayjs(newV);
-      params.value = {
-        start_date: newDate.startOf('month').format('YYYY-MM-DD HH:mm:ss'),
-        end_date: newDate.endOf('month').format('YYYY-MM-DD HH:mm:ss'),
-      };
-      
-      // 新增:如果是当前月份,自动选中当天
-      if (isCurrentMonth(newV)) {
-        nextTick(() => {
-          if (calendar.value) {
-            calendar.value.selectDate(new Date());
-          }
-        });
-      }
-      
-      getJobEventBar();
-    }
-  },
-  { deep: true, immediate: true }
-);
-// 获取日期数字
-const getDate = date => {
-  return date.getDate();
-};
-
-// 获取对应日期的事件
-const getEvents = dateString => {
-  return events.value[dateString] || [];
-};
-const monthRange = getCurrentMonthRange();
-params.value = monthRange;
-
+// 获取日历数据
 const getJobEventBar = () => {
   getCalen(params.value).then(res => {
     if (res.data.code !== 0) return;
@@ -128,9 +98,83 @@
       filteredData[date] = a[date].filter(item => item.type !== 'work-order');
     }
     events.value = filteredData;
-    // events.value = res.data.data
   });
 };
+
+// 获取事件图标
+const getEventIcon = type => {
+  return eventIcons.value[type] || eventIcons.value.default;
+};
+
+// 获取当前月份范围
+function getCurrentMonthRange() {
+  return {
+    start_date: dayjs().startOf('month').format('YYYY-MM-DD HH:mm:ss'),
+    end_date: dayjs().endOf('month').format('YYYY-MM-DD HH:mm:ss'),
+  };
+}
+
+// 月份切换处理
+const selectDate = async val => {
+  if (!calendar.value) return;
+
+  if (val === 'prev-month') {
+    currentMonth.value = dayjs(currentMonth.value).subtract(1, 'month').toDate();
+  } else if (val === 'next-month') {
+    currentMonth.value = dayjs(currentMonth.value).add(1, 'month').toDate();
+  }
+
+  // 等待DOM更新
+  await nextTick();
+
+  // 强制清除所有选中状态
+  const selectedCells = document.querySelectorAll('.el-calendar-table td.is-selected');
+  selectedCells.forEach(cell => {
+    cell.classList.remove('is-selected');
+  });
+
+  // 如果是当前月份才设置选中
+  if (isCurrentMonth(currentMonth.value)) {
+    selectedDate.value = new Date();
+  }
+};
+
+// 监听当前月份变化
+watch(
+  () => currentMonth.value,
+  newMonth => {
+    const newDate = dayjs(newMonth);
+    params.value = {
+      start_date: newDate.startOf('month').format('YYYY-MM-DD HH:mm:ss'),
+      end_date: newDate.endOf('month').format('YYYY-MM-DD HH:mm:ss'),
+    };
+
+    // 如果是当前月份,则选中当天;否则清除选中
+    if (isCurrentMonth(newMonth)) {
+      selectedDate.value = new Date();
+    } else {
+      selectedDate.value = null;
+    }
+
+    getJobEventBar();
+  },
+  { deep: true, immediate: true }
+);
+
+// 获取日期数字
+const getDate = date => {
+  return date.getDate();
+};
+
+// 获取对应日期的事件
+const getEvents = dateString => {
+  return events.value[dateString] || [];
+};
+
+// 初始化月份范围
+const monthRange = getCurrentMonthRange();
+params.value = monthRange;
+
 const jumpcalendar = (event, day) => {
   if (event.name === '工单') {
     router.push({
@@ -148,14 +192,18 @@
     });
   }
 };
+
 onMounted(() => {
-  // 新增:挂载时如果是当前月份,设置默认选中
-  if (isCurrentMonth(leftValue.value)) {
-    leftValue.value = new Date();
+  // 初始化时如果是当前月份,选中当天;否则不选中
+  if (isCurrentMonth(currentMonth.value)) {
+    selectedDate.value = new Date();
+  } else {
+    selectedDate.value = null;
   }
   getJobEventBar();
 });
 </script>
+
 <style lang="scss">
 .calenBox {
   height: pxToVh(660);
@@ -171,7 +219,7 @@
   }
   .el-calendar__header {
     justify-content: center;
-    margin-top: 18px;
+    margin-top: 10px;
     padding-bottom: 0;
     border-bottom: transparent;
     div {
@@ -199,7 +247,6 @@
   }
   .el-calendar-table .el-calendar-day {
     box-sizing: border-box;
-
     padding: 0.8rem;
     background: #f5f7fa;
     border-radius: 6px 6px 6px 6px;
@@ -207,18 +254,57 @@
     margin-right: 5px;
     margin-bottom: 8px;
   }
+
+  // 非选中日期的样式
+  .el-calendar-table td:not(.is-selected) {
+    .el-calendar-day {
+      background: #f5f7fa;
+      border: 1px solid #efefef;
+
+      .date-number {
+        font-weight: normal;
+        color: inherit;
+      }
+    }
+  }
+  .el-input__prefix-inner {
+    display: none !important;
+  }
+  .el-input__suffix {
+    width: 0 !important;
+  }
+  .el-input__wrapper {
+    align-items: center !important;
+    cursor: text;
+    box-shadow: none !important;
+    display: inline-flex !important;
+    flex-grow: 1;
+    justify-content: center;
+  }
+  .el-input__inner {
+    font-weight: bold;
+    font-size: 14px;
+    color: #363636;
+  }
+  .el-date-editor.el-input,
+  .el-date-editor.el-input__wrapper {
+    height: var(--el-input-height, var(--el-component-size));
+
+    width: 150px !important;
+  }
 }
 </style>
 
 <style lang="scss" scoped>
 .calenBox {
   margin-top: 10px;
-  // height: 630px;
   height: pxToVh(622);
   border-radius: 10px;
   overflow: hidden;
   background-color: #fff;
-
+  :deep(.el-date-picker .el-input__prefix-inner) {
+    display: none !important;
+  }
   ::v-deep(.el-calendar) {
     // 标题样式
     .el-calendar__title {
@@ -227,24 +313,24 @@
       color: #363636;
     }
     .el-calendar-table .el-calendar-day {
-      height: pxToVh(88) !important;
+      height: pxToVh(85) !important;
     }
 
     // 选中日期样式
     .el-calendar-table td.is-selected {
-    .el-calendar-day {
-      outline: 2px solid #409eff;
-      outline-offset: -2px;
-      border: none !important;
-      .date-number {
-        font-weight: bold;
-        color: #409eff;
+      .el-calendar-day {
+        outline: 2px solid #409eff;
+        outline-offset: -2px;
+        border: none !important;
+        .date-number {
+          font-weight: bold;
+          color: #409eff;
+        }
       }
-    }}
+    }
     .el-calendar-table td.is-selected {
       background-color: transparent;
     }
-   
   }
 
   .event-item {
@@ -252,6 +338,8 @@
     text-align: center;
     border-radius: 3px;
     white-space: nowrap;
+    position: relative;
+    z-index: 2;
 
     &.work-order {
       font-weight: 400;
diff --git a/src/views/wel/components/proportionStatic.vue b/src/views/wel/components/proportionStatic.vue
index 41f2d56..ac04e28 100644
--- a/src/views/wel/components/proportionStatic.vue
+++ b/src/views/wel/components/proportionStatic.vue
@@ -71,7 +71,6 @@
 const getTypeData = () => {
   getJobEventByStatus(params.value).then(res => {
     const resList = res?.data?.data || [];
-
     resList.forEach(item => {
       eventTypeList.value.forEach(item1 => {
         if (item1.name === item.name) {

--
Gitblit v1.9.3