qq_38555220 2025-11-23 14:34 采纳率: 100%
浏览 8
已结题

fullcalendar 显示每天工时总数

fullcalendar 日程显示每天已有的工时总数,我开发了一个日程组件,可以按日历显示每天的事件,现在有个需求要显示每天日程所有事件的总工时

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-11-23 15:05
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案能帮助您,请采纳,非常感谢!
    .
    每日一句正能量,让它带给您好心情:把快乐装进口袋,随身携带,生活就会充满阳光。
    .

    FullCalendar 显示每天工时总数

    实现思路

    要在 FullCalendar 中显示每天所有事件的总工时,可以通过以下几种方式实现:

    方法一:使用 dayCellContent 回调函数

    import FullCalendar from '@fullcalendar/react'
    import dayGridPlugin from '@fullcalendar/daygrid'
    
    
    function CalendarWithTotalHours() {
      const events = [
        {
          id: '1',
          title: '项目A开发',
          start: '2024-01-15T09:00:00',
          end: '2024-01-15T17:00:00',
          extendedProps: { hours: 8 }
        },
        {
          id: '2',
          title: '项目B会议',
          start: '2024-01-15T13:00:00',
          end: '2024-01-15T15:00:00',
          extendedProps: { hours: 2 }
        }
      ]
    
    
      // 计算某天所有事件的总工时
      const calculateDailyTotalHours = (date) => {
        const dayStart = new Date(date)
        dayStart.setHours(0, 0, 0, 0)
        
        const dayEnd = new Date(date)
        dayEnd.setHours(23, 59, 59, 999)
        
        const dayEvents = events.filter(event => {
          const eventStart = new Date(event.start)
          return eventStart >= dayStart && eventStart <= dayEnd
        })
        
        return dayEvents.reduce((total, event) => {
          return total + (event.extendedProps?.hours || 0)
        }, 0)
      }
    
    
      return (
        <FullCalendar
          plugins={[dayGridPlugin]}
          initialView="dayGridMonth"
          events={events}
          dayCellContent={(args) => {
            const totalHours = calculateDailyTotalHours(args.date)
            return (
              <div>
                <div className="fc-daygrid-day-number">
                  {args.dayNumberText}
                </div>
                {totalHours > 0 && (
                  <div className="total-hours">
                    总工时: {totalHours}h
                  </div>
                )}
              </div>
            )
          }}
        />
      )
    }
    

    方法二:使用自定义 CSS 和 dayCellDidMount

    function CalendarWithCustomDayCell() {
      const events = [
        // 事件数据...
      ]
    
    
      const calculateDailyTotalHours = (date) => {
        // 同上的计算逻辑
      }
    
    
      return (
        <FullCalendar
          plugins={[dayGridPlugin]}
          initialView="dayGridMonth"
          events={events}
          dayCellDidMount={(info) => {
            const totalHours = calculateDailyTotalHours(info.date)
            if (totalHours > 0) {
              const hoursElement = document.createElement('div')
              hoursElement.className = 'daily-total-hours'
              hoursElement.innerHTML = `${totalHours}h`
              info.el.querySelector('.fc-daygrid-day-frame').appendChild(hoursElement)
            }
          }}
        />
      )
    }
    

    方法三:使用 slotLabelContent(时间轴视图)

    import timeGridPlugin from '@fullcalendar/timegrid'
    
    
    function TimelineCalendarWithHours() {
      const events = [
        // 事件数据...
      ]
    
    
      return (
        <FullCalendar
          plugins={[timeGridPlugin]}
          initialView="timeGridWeek"
          events={events}
          slotLabelContent={(args) => {
            if (args.isWeek) {
              const date = args.date
              const totalHours = calculateDailyTotalHours(date)
              return (
                <div>
                  <div>{args.text}</div>
                  {totalHours > 0 && (
                    <div style={{ fontSize: '10px', color: '#666' }}>
                      {totalHours}h
                    </div>
                  )}
                </div>
              )
            }
            return args.text
          }}
        />
      )
    }
    

    配套 CSS 样式

    /* 每日总工时显示样式 */
    .total-hours {
      font-size: 10px;
      color: #666;
      background-color: #f0f0f0;
      padding: 2px 4px;
      border-radius: 3px;
      margin-top: 2px;
    }
    
    
    .daily-total-hours {
      position: absolute;
      bottom: 2px;
      right: 2px;
      font-size: 10px;
      color: #fff;
      background-color: rgba(0, 0, 0, 0.6);
      padding: 1px 3px;
      border-radius: 2px;
    }
    
    
    /* 高亮显示工时较多的天数 */
    .fc-daygrid-day[data-total-hours="8"] {
      background-color: #e8f5e8 !important;
    }
    
    
    .fc-daygrid-day[data-total-hours="10"] {
      background-color: #fff3cd !important;
    }
    
    
    .fc-daygrid-day[data-total-hours="12"] {
      background-color: #f8d7da !important;
    }
    

    完整示例代码

    import React from 'react'
    import FullCalendar from '@fullcalendar/react'
    import dayGridPlugin from '@fullcalendar/daygrid'
    import timeGridPlugin from '@fullcalendar/timegrid'
    import interactionPlugin from '@fullcalendar/interaction'
    
    
    const WorkHoursCalendar = () => {
      const [events, setEvents] = React.useState([
        {
          id: '1',
          title: '前端开发',
          start: '2024-01-15T09:00:00',
          end: '2024-01-15T12:00:00',
          extendedProps: { hours: 3, project: '项目A' }
        },
        {
          id: '2',
          title: '后端联调',
          start: '2024-01-15T14:00:00',
          end: '2024-01-15T18:00:00',
          extendedProps: { hours: 4, project: '项目A' }
        },
        {
          id: '3',
          title: '团队会议',
          start: '2024-01-16T10:00:00',
          end: '2024-01-16T12:00:00',
          extendedProps: { hours: 2, project: '团队' }
        }
      ])
    
    
      const calculateDailyTotalHours = (date) => {
        const dayStart = new Date(date)
        dayStart.setHours(0, 0, 0, 0)
        
        const dayEnd = new Date(date)
        dayEnd.setHours(23, 59, 59, 999)
        
        const dayEvents = events.filter(event => {
          const eventStart = new Date(event.start)
          return eventStart >= dayStart && eventStart <= dayEnd
        })
        
        return dayEvents.reduce((total, event) => {
          return total + (event.extendedProps?.hours || 0)
        }, 0)
      }
    
    
      const dayCellDidMount = (info) => {
        const totalHours = calculateDailyTotalHours(info.date)
        
        // 设置数据属性用于CSS样式
        info.el.setAttribute('data-total-hours', totalHours)
        
        // 添加总工时显示
        if (totalHours > 0) {
          const hoursBadge = document.createElement('div')
          hoursBadge.className = 'total-hours-badge'
          hoursBadge.innerHTML = `${totalHours}h`
          info.el.querySelector('.fc-daygrid-day-frame').appendChild(hoursBadge)
        }
      }
    
    
      return (
        <div className="work-hours-calendar">
          <FullCalendar
            plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
            initialView="dayGridMonth"
            headerToolbar={{
              left: 'prev,next today',
              center: 'title',
              right: 'dayGridMonth,timeGridWeek,timeGridDay'
            }}
            events={events}
            dayCellDidMount={dayCellDidMount}
            eventContent={(eventInfo) => (
              <div>
                <b>{eventInfo.timeText}</b>
                <i>{eventInfo.event.title}</i>
                <small>({eventInfo.event.extendedProps.hours}h)</small>
              </div>
            )}
          />
        </div>
      )
    }
    
    
    export default WorkHoursCalendar
    

    关键要点

    1. 工时计算:确保事件数据中包含工时信息,可以通过 extendedProps 字段存储
    2. 日期匹配:准确计算某一天的所有事件,注意时区处理
    3. 显示位置:选择合适的显示位置,避免遮挡日历内容
    4. 性能优化:对于大量事件,考虑缓存计算结果
    5. 响应式设计:在不同视图(月、周、日)下都能正常显示

    这样实现后,用户就能在日历上直观地看到每天的总工时情况,便于工时管理和项目进度跟踪。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 12月1日
  • 已采纳回答 11月23日
  • 创建了问题 11月23日