From 1b736033f6d01b774d58b4c2d7cd2ce8607a44fa Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期日, 28 十二月 2025 20:28:46 +0800
Subject: [PATCH] 页面完善

---
 src/views/OfficeRelated/checkingIn/components/AttendanceCalendar.vue |  542 +++--------------------------------------------------
 1 files changed, 35 insertions(+), 507 deletions(-)

diff --git a/src/views/OfficeRelated/checkingIn/components/AttendanceCalendar.vue b/src/views/OfficeRelated/checkingIn/components/AttendanceCalendar.vue
index c43976e..5f90278 100644
--- a/src/views/OfficeRelated/checkingIn/components/AttendanceCalendar.vue
+++ b/src/views/OfficeRelated/checkingIn/components/AttendanceCalendar.vue
@@ -1,132 +1,23 @@
 <template>
   <div class="attendance-calendar">
-    <!-- 鏃ュ巻澶撮儴缁熻淇℃伅 -->
-    <div class="calendar-stats">
-      <div class="stat-item">
-        <span class="stat-dot present"></span>
-        <span>姝e父鍑哄嫟: {{ stats.presentDays }}澶�</span>
-      </div>
-      <div class="stat-item">
-        <span class="stat-dot absent"></span>
-        <span>缂哄嫟/寮傚父: {{ stats.absentDays }}澶�</span>
-      </div>
-      <div class="stat-item">
-        <span class="stat-dot trip"></span>
-        <span>鍑哄樊: {{ stats.tripDays }}澶�</span>
-      </div>
-      <div class="stat-item">
-        <span class="stat-dot late"></span>
-        <span>杩熷埌/鏃╅��: {{ stats.lateDays }}澶�</span>
-      </div>
-    </div>
-
-    <!-- Element UI 鏃ュ巻缁勪欢 -->
-    <el-calendar v-model="calendarValue" :first-day-of-week="1">
+    <el-calendar v-model="calendarValue">
       <template #date-cell="{ data }">
-        <div
-          class="calendar-date"
-          :class="getDateStatusClass(data.day)"
-          @click="handleDateClick(data)"
-        >
+        <div class="calendar-date">
           <div class="date-number">{{ data.day.split('-')[2] }}</div>
-
-          <!-- 鐘舵�佽儗鏅壊鍧� -->
-          <div class="status-background" :class="getBackgroundStatus(data.day)"></div>
-
           <div class="date-events">
-            <!-- 鍑哄嫟鐘舵�佹爣璁� -->
-            <div v-if="getAttendanceStatus(data.day) !== 'absent'" class="status-mark">
-              <el-tooltip
-                :content="getAttendanceTooltip(data.day)"
-                placement="top"
-              >
-                <span class="status-dot" :class="getAttendanceStatus(data.day)"></span>
-              </el-tooltip>
-            </div>
-
-            <!-- 鍑哄樊鏍囪 -->
-            <div v-if="hasBusinessTrip(data.day)" class="trip-mark">
-              <el-tooltip content="鍑哄樊" placement="top">
-                <i class="el-icon-location-outline"></i>
-              </el-tooltip>
-            </div>
-
-            <!-- 缂哄嫟鏍囪 -->
-            <div v-if="getAttendanceStatus(data.day) === 'absent'" class="absent-mark">
-              <el-tooltip content="缂哄嫟" placement="top">
-                <i class="el-icon-close"></i>
-              </el-tooltip>
-            </div>
-          </div>
-
-          <!-- 绠�鐣ヤ俊鎭樉绀� -->
-          <div class="brief-info">
-            <div v-if="getAttendanceStatus(data.day) === 'present'" class="info-item present-info">
-              鈭�
-            </div>
-            <div v-else-if="getAttendanceStatus(data.day) === 'late'" class="info-item late-info">
-              !
-            </div>
-            <div v-else-if="getAttendanceStatus(data.day) === 'absent'" class="info-item absent-info">
-              脳
-            </div>
-            <div v-if="hasBusinessTrip(data.day)" class="info-item trip-info">
-              鉁�
-            </div>
-          </div>
-
-          <!-- 鏃ユ湡璇︾粏淇℃伅锛堟偓娴樉绀猴級 -->
-          <div class="date-details">
             <div
               v-for="event in getDateEvents(data.day)"
               :key="event.id"
-              class="detail-item"
+              class="event-item"
+              :class="event.type"
             >
-              <span class="detail-type">{{ event.type === 'attendance' ? '鍑哄嫟' : '鍑哄樊' }}</span>
-              <span class="detail-info">{{ event.text }}</span>
-            </div>
-            <div v-if="getDateEvents(data.day).length === 0" class="detail-item">
-              <span class="detail-type">鏃犺褰�</span>
+              <span class="event-dot"></span>
+              <span class="event-text">{{ event.text }}</span>
             </div>
           </div>
         </div>
       </template>
     </el-calendar>
-
-    <!-- 鏃ユ湡璇︽儏瀵硅瘽妗� -->
-    <el-dialog
-      :title="`${selectedDate} 鑰冨嫟璇︽儏`"
-      v-model="detailDialogVisible"
-      width="500px"
-    >
-      <div v-if="selectedDateInfo">
-        <div class="detail-section">
-          <h4>鍑哄嫟淇℃伅</h4>
-          <div v-if="selectedDateInfo.attendance">
-            <p>涓婄彮鏃堕棿: {{ selectedDateInfo.attendance.checkIn || '鏈墦鍗�' }}</p>
-            <p>涓嬬彮鏃堕棿: {{ selectedDateInfo.attendance.checkOut || '鏈墦鍗�' }}</p>
-            <p>鐘舵��:
-              <el-tag :type="getStatusTagType(selectedDateInfo.attendance.status)">
-                {{ getStatusText(selectedDateInfo.attendance.status) }}
-              </el-tag>
-            </p>
-          </div>
-          <div v-else>
-            <p class="no-data">鏃犲嚭鍕よ褰�</p>
-          </div>
-        </div>
-
-        <div class="detail-section" v-if="selectedDateInfo.businessTrip">
-          <h4>鍑哄樊淇℃伅</h4>
-          <p>鐩殑鍦�: {{ selectedDateInfo.businessTrip.destination }}</p>
-          <p>浜嬬敱: {{ selectedDateInfo.businessTrip.reason }}</p>
-          <p>閲岀▼: {{ selectedDateInfo.businessTrip.distance }}鍏噷</p>
-        </div>
-      </div>
-      <template #footer>
-        <el-button @click="detailDialogVisible = false">鍏抽棴</el-button>
-      </template>
-    </el-dialog>
   </div>
 </template>
 
@@ -134,211 +25,41 @@
 export default {
   name: 'AttendanceCalendar',
   props: {
-    attendanceData: {
-      type: Array,
-      default: () => []
-    },
-    businessTripData: {
-      type: Array,
-      default: () => []
-    }
+    attendanceData: Array,
+    businessTripData: Array
   },
   data() {
     return {
-      calendarValue: new Date(),
-      detailDialogVisible: false,
-      selectedDate: '',
-      selectedDateInfo: null,
-      stats: {
-        presentDays: 0,
-        absentDays: 0,
-        tripDays: 0,
-        lateDays: 0
-      }
-    }
-  },
-  mounted() {
-    this.calculateStats()
-  },
-  watch: {
-    attendanceData: {
-      handler() {
-        this.calculateStats()
-      },
-      deep: true
-    },
-    businessTripData: {
-      handler() {
-        this.calculateStats()
-      },
-      deep: true
+      calendarValue: new Date()
     }
   },
   methods: {
-    // 鑾峰彇鏃ユ湡鐘舵�佺被鍚�
-    getDateStatusClass(date) {
-      const classes = []
-      if (this.isToday(date)) {
-        classes.push('today')
-      }
-      if (this.isSelected(date)) {
-        classes.push('selected')
-      }
-
-      // 娣诲姞鐘舵�佺被鍚�
-      const status = this.getBackgroundStatus(date)
-      if (status) {
-        classes.push(status)
-      }
-
-      return classes
-    },
-
-    // 鑾峰彇鑳屾櫙鐘舵�侊紙鐢ㄤ簬鑳屾櫙鑹诧級
-    getBackgroundStatus(date) {
-      const attendance = this.attendanceData.find(item => item.date === date)
-      const hasTrip = this.hasBusinessTrip(date)
-
-      if (hasTrip) {
-        return 'has-trip'
-      }
-
-      if (attendance) {
-        switch (attendance.status) {
-          case 'present': return 'has-attendance'
-          case 'late': return 'has-late'
-          case 'absent': return 'has-absent'
-          default: return ''
-        }
-      }
-
-      return ''
-    },
-
-    // 鍒ゆ柇鏄惁涓轰粖澶�
-    isToday(date) {
-      const today = new Date()
-      const compareDate = new Date(date)
-      return today.toDateString() === compareDate.toDateString()
-    },
-
-    // 鍒ゆ柇鏄惁琚�変腑
-    isSelected(date) {
-      return this.selectedDate === date
-    },
-
-    // 鑾峰彇鑰冨嫟鐘舵��
-    getAttendanceStatus(date) {
-      const attendance = this.attendanceData.find(item => item.date === date)
-      if (!attendance) return 'absent'
-
-      switch (attendance.status) {
-        case 'present': return 'present'
-        case 'late': return 'late'
-        case 'absent': return 'absent'
-        default: return 'absent'
-      }
-    },
-
-    // 鑾峰彇鐘舵�佹枃鏈�
-    getStatusText(status) {
-      const statusMap = {
-        present: '姝e父鍑哄嫟',
-        late: '杩熷埌/鏃╅��',
-        absent: '缂哄嫟/寮傚父'
-      }
-      return statusMap[status] || '鏈煡鐘舵��'
-    },
-
-    // 鑾峰彇鑰冨嫟鐘舵�佹彁绀�
-    getAttendanceTooltip(date) {
-      const statusMap = {
-        present: '姝e父鍑哄嫟',
-        late: '杩熷埌/鏃╅��',
-        absent: '缂哄嫟/寮傚父'
-      }
-      return statusMap[this.getAttendanceStatus(date)] || '鏃犺褰�'
-    },
-
-    // 鍒ゆ柇鏄惁鏈夊嚭宸�
-    hasBusinessTrip(date) {
-      return this.businessTripData.some(item =>
-        date >= item.startDate && date <= item.endDate
-      )
-    },
-
-    // 鑾峰彇鏃ユ湡浜嬩欢
     getDateEvents(date) {
       const events = []
-      const attendance = this.attendanceData.find(item => item.date === date)
 
+      // 妫�鏌ュ嚭鍕よ褰�
+      const attendance = this.attendanceData.find(item => item.date === date)
       if (attendance) {
         events.push({
           id: `attendance-${date}`,
           type: 'attendance',
-          text: `${attendance.checkIn || '鏈墦鍗�'} - ${attendance.checkOut || '鏈墦鍗�'}`
+          text: `${attendance.checkIn}-${attendance.checkOut}`
         })
       }
 
+      // 妫�鏌ュ嚭宸褰�
       const businessTrip = this.businessTripData.find(item =>
         date >= item.startDate && date <= item.endDate
       )
       if (businessTrip) {
         events.push({
           id: `business-trip-${date}`,
-          type: 'businessTrip',
-          text: `鍓嶅線${businessTrip.destination}`
+          type: 'business-trip',
+          text: `鍑哄樊: ${businessTrip.endCity}`
         })
       }
 
       return events
-    },
-
-    // 澶勭悊鏃ユ湡鐐瑰嚮浜嬩欢
-    handleDateClick(data) {
-      this.selectedDate = data.day
-      this.selectedDateInfo = {
-        attendance: this.attendanceData.find(item => item.date === data.day),
-        businessTrip: this.businessTripData.find(item =>
-          data.day >= item.startDate && data.day <= item.endDate
-        )
-      }
-      this.detailDialogVisible = true
-    },
-
-    // 鑾峰彇鐘舵�佹爣绛剧被鍨�
-    getStatusTagType(status) {
-      const typeMap = {
-        present: 'success',
-        late: 'warning',
-        absent: 'danger'
-      }
-      return typeMap[status] || 'info'
-    },
-
-    // 璁$畻缁熻淇℃伅
-    calculateStats() {
-      // 閲嶇疆缁熻
-      this.stats = { presentDays: 0, absentDays: 0, tripDays: 0, lateDays: 0 }
-
-      this.attendanceData.forEach(item => {
-        switch (item.status) {
-          case 'present': this.stats.presentDays++; break
-          case 'late': this.stats.lateDays++; break
-          case 'absent': this.stats.absentDays++; break
-        }
-      })
-
-      // 璁$畻鍑哄樊澶╂暟
-      const tripDays = new Set()
-      this.businessTripData.forEach(item => {
-        const start = new Date(item.startDate)
-        const end = new Date(item.endDate)
-        for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
-          tripDays.add(d.toISOString().split('T')[0])
-        }
-      })
-      this.stats.tripDays = tripDays.size
     }
   }
 }
@@ -347,242 +68,49 @@
 <style scoped>
 .attendance-calendar {
   padding: 20px;
-  max-width: 100%;
 }
-
-.calendar-stats {
-  display: flex;
-  justify-content: space-around;
-  margin-bottom: 20px;
-  padding: 15px;
-  background: #f5f7fa;
-  border-radius: 8px;
-}
-
-.stat-item {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-.stat-dot {
-  width: 12px;
-  height: 12px;
-  border-radius: 50%;
-  display: inline-block;
-}
-
-.stat-dot.present { background-color: #67c23a; }
-.stat-dot.absent { background-color: #f56c6c; }
-.stat-dot.trip { background-color: #409eff; }
-.stat-dot.late { background-color: #e6a23c; }
 
 .calendar-date {
-  height: 80px;
-  padding: 4px;
-  border: 1px solid #ebeef5;
-  border-radius: 4px;
-  cursor: pointer;
-  transition: all 0.3s;
-  position: relative;
-  overflow: hidden;
-}
-
-.calendar-date:hover {
-  background-color: #f0f9ff;
-  border-color: #409eff;
-  transform: translateY(-2px);
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
-}
-
-.calendar-date.today {
-  border-color: #409eff;
-  background-color: #f0f9ff;
-}
-
-.calendar-date.selected {
-  background-color: #ecf5ff;
-  border-color: #409eff;
-}
-
-/* 鐘舵�佽儗鏅壊 */
-.status-background {
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  opacity: 0.1;
-  z-index: 0;
-}
-
-.calendar-date.has-attendance .status-background {
-  background-color: #67c23a;
-}
-
-.calendar-date.has-late .status-background {
-  background-color: #e6a23c;
-}
-
-.calendar-date.has-absent .status-background {
-  background-color: #f56c6c;
-}
-
-.calendar-date.has-trip .status-background {
-  background: linear-gradient(135deg, #409eff 0%, #67c23a 100%);
+  height: 100%;
+  display: flex;
+  flex-direction: column;
 }
 
 .date-number {
   font-weight: bold;
-  font-size: 14px;
-  margin-bottom: 2px;
-  position: relative;
-  z-index: 1;
+  margin-bottom: 4px;
 }
 
 .date-events {
-  display: flex;
-  flex-direction: column;
-  gap: 2px;
-  position: relative;
-  z-index: 1;
+  flex: 1;
+  overflow: hidden;
 }
 
-.status-mark, .trip-mark, .absent-mark {
+.event-item {
   display: flex;
   align-items: center;
-  gap: 4px;
+  margin-bottom: 2px;
+  font-size: 12px;
 }
 
-.status-dot {
-  width: 8px;
-  height: 8px;
+.event-dot {
+  width: 6px;
+  height: 6px;
   border-radius: 50%;
-  display: inline-block;
-}
-
-.status-dot.present { background-color: #67c23a; }
-.status-dot.late { background-color: #e6a23c; }
-.status-dot.absent { background-color: #f56c6c; }
-
-.trip-mark i {
-  color: #409eff;
-  font-size: 12px;
-}
-
-.absent-mark i {
-  color: #f56c6c;
-  font-size: 12px;
-}
-
-/* 绠�鐣ヤ俊鎭樉绀� */
-.brief-info {
-  position: absolute;
-  bottom: 4px;
-  right: 4px;
-  display: flex;
-  gap: 2px;
-  z-index: 1;
-}
-
-.info-item {
-  width: 16px;
-  height: 16px;
-  border-radius: 50%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 10px;
-  font-weight: bold;
-}
-
-.present-info {
-  background-color: #67c23a;
-  color: white;
-}
-
-.late-info {
-  background-color: #e6a23c;
-  color: white;
-}
-
-.absent-info {
-  background-color: #f56c6c;
-  color: white;
-}
-
-.trip-info {
-  background-color: #409eff;
-  color: white;
-}
-
-.date-details {
-  position: absolute;
-  top: 100%;
-  left: 0;
-  right: 0;
-  background: white;
-  border: 1px solid #ddd;
-  border-radius: 4px;
-  padding: 8px;
-  z-index: 1000;
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
-  display: none;
-}
-
-.calendar-date:hover .date-details {
-  display: block;
-}
-
-.detail-item {
-  font-size: 12px;
-  margin-bottom: 4px;
-  display: flex;
-  align-items: center;
-}
-
-.detail-type {
-  font-weight: bold;
   margin-right: 4px;
-  min-width: 40px;
 }
 
-.detail-info {
-  color: #606266;
+.event-item.attendance .event-dot {
+  background-color: #67c23a;
 }
 
-.detail-section {
-  margin-bottom: 20px;
+.event-item.business-trip .event-dot {
+  background-color: #409eff;
 }
 
-.detail-section h4 {
-  margin-bottom: 10px;
-  color: #303133;
-  border-left: 4px solid #409eff;
-  padding-left: 8px;
-}
-
-.no-data {
-  color: #909399;
-  font-style: italic;
-}
-
-:deep(.el-calendar__header) {
-  padding: 10px;
-  border-bottom: 1px solid #ebeef5;
-}
-
-:deep(.el-calendar-day) {
-  padding: 0 !important;
-  height: 80px;
-}
-
-:deep(.el-calendar-table:not(.is-range) td) {
-  border: 1px solid #f0f0f0;
-}
-
-:deep(.el-calendar-table .el-calendar-day) {
-  height: 80px !important;
-  padding: 0 !important;
+.event-text {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
 }
 </style>

--
Gitblit v1.9.3