react甘特图

 
import React, { useEffect, useRef, useState } from 'react'
import './indexgun.less'
export default function GunttCharts(props: any) {
  const {
    dataSource,
    widthgezi=55,
    rowHeight = 40, ///数据行高
    hourWidth = 80, ///数据行宽
    startTime = 7, ///默认起始时间     小屏幕会生效
    columns } = props
  const [offsetX, setOffsetX] = useState(0);
  const [offsetY, setOffsetY] = useState(0);
  const [translateX, setTranslateX] = useState(0);
  const [tooltipData, setTooltipData] = useState<any>(null);
  const [tooltipVisble, setTooltipVisble] = useState("none");
  function getMonthDays(year: any) {
    const result = [];
    for (let month = 1; month <= 12; month++) {
      const daysInMonth = new Date(year, month, 0).getDate();
      const monthInfo: any = {
        month: month,
        colors: []
      };
      for (let day = 1; day <= daysInMonth; day++) {
        const date = new Date(year, month - 1, day);
        const dayOfWeek = date.getDay();
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
          monthInfo.colors.push('red');
        } else {
          monthInfo.colors.push('black');
        }
      }
      result.push(monthInfo);
    }
    return result;
  }

  const year = 2024;
  const yearInfo = getMonthDays(year);
  console.log("yearInfo", yearInfo);
  function getDaysInYear(year: any) {
    if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
      // 是闰年  
      return 366;
    } else {
      // 不是闰年  
      return 365;
    }
  }

  // 使用示例  
  console.log(getDaysInYear(year));
  const onMouseEnter = (e: any, value: any) => {
    setTooltipData(value);
    setTooltipVisble("block");
  };

  const onMouseMove = (e: any) => {
    e.nativeEvent.stopImmediatePropagation();
    const offset: any = ((e.clientX / document.body.clientWidth) * 100).toFixed(0);
    setTranslateX(offset);
    setOffsetX(e.clientX);
    setOffsetY(e.clientY);
  };

  const onMouseLeave = (e: any) => {
    setTooltipVisble("none");
  };
  const valueScrollRef: any = useRef();
  const onScrollY = (e: any) => {
    valueScrollRef.current.scrollTop = e.target.scrollTop;
  };
  const onScrollX = (e: any) => {
    timeScrollRef.current.scrollLeft = e.target.scrollLeft;
  };
  const onWheel = (e: any) => {
    timeScrollRef.current.scrollLeft += e.deltaY;
    valueScrollRef.current.scrollLeft += e.deltaY;
  };
  const timeScrollRef: any = useRef();

  const timeInterval: any = (start:any) => {
    const t1 = "2024-09-10";
    
  const sum = start.substring(5, 7)
  console.log("fdfdfdfdfd",sum);
  
    const interval = start.substring(8, 10)
    return interval*sum;
  };
 const timeIntervalw =(dateString:any)=>{
  const date:any = new Date(dateString);
  const start:any = new Date(date.getFullYear(), 0, 0);
  const diff = date - start;
  const oneDay = 1000 * 60 * 60 * 24;
  const dayOfYear = Math.floor(diff / oneDay);
  return dayOfYear;
 }

 const timeIntervals=(dateString:any)=> {
  const date:any = new Date(dateString);
  const start:any = new Date(date.getFullYear(), 0, 0);
  const diff = date - start;
  const oneDay = 1000 * 60 * 60 * 24;
  const dayOfYear = Math.floor(diff / oneDay);
  return dayOfYear - 1;
}

  const arrayLength = Array.from({ length: 365 }, (_, index) => index);
  console.log("new Array(getDaysInYear(year))", arrayLength);
  useEffect(() => {
    valueScrollRef.current.scrollLeft = hourWidth * startTime;
  }, [])
  return (
    <div className='gun-wrap'>
      <div className='gun-left'>
        <div
          ref={timeScrollRef}
          style={{ display: "flex", height: "100px", width: 100 * Number(columns.lenght) + "px" }}
        >
          {
            columns?.map((i: any, v: any) => {
              return (
                <div key={v} className="rowTitle" style={{ width: 100  }}>
                  {i?.title || null}
                </div>
              )
            })
          }
        </div>
        {
          columns?.map((item: any, index: number) => {
            return (
              <div
                key={index}
                className="desc_container"
                onScroll={onScrollY}
                style={{ width: 100 }}
              >
                {dataSource?.map((row: any, rowi: number) => (
                  <div
                    key={rowi}
                    className="row_desc_container"
                    style={{ height: rowHeight, lineHeight: `${rowHeight}px` }}
                  >
                    {
                      item?.render(row[item?.dataIndex]) || '--'
                    }
                  </div>
                ))}
              </div>
            )
          })
        }
      </div>
      <div className='gun-right'
        ref={valueScrollRef}
        onScroll={onScrollX}
        onWheel={onWheel}>
        {
          <div style={{ display: "flex" }}>
            {
              yearInfo?.map((a, b) => {
                return (
                  <div key={b} > <div
                    className="header_container"
                    ref={timeScrollRef}
                    style={{ flex: "1", flexWrap: "nowrap" }}
                  >
                    <div style={{ textAlign: "center", width: widthgezi * a?.colors?.length, height: "50px", backgroundColor: "#f0f0f0", border: "1px solid #ccc", lineHeight: "50px" }}>
                      {year}- {a?.month < 10 ? "0" + a?.month : a?.month}
                    </div>
                    <div className="time_header_container">
                      {a?.colors?.map((c: any, d: number) => {
                        return (
                          <div key={d} className="time_header_item" style={{ color: c, width: hourWidth - 25 }}>
                            {d < 9 ? "0" + (d + 1) : d + 1}
                          </div>
                        )
                      })}
                    </div>
                  </div></div>

                )
              })
            }
          </div>
        }
        {dataSource.map((row: any, index: number) => (
          <div
            key={index}
            className="row_val_container"
            style={{
              display: "flex",
              height: rowHeight,
              lineHeight: `${rowHeight}px`,
              width: getDaysInYear(year) * widthgezi
            }}
          >
            {arrayLength?.map((i: any, v: number) => {
              return (
                <div key={v} style={{ width: widthgezi+"px", textAlign: "center", borderRight: "1px solid #ccc" }}>

                </div>
              )
            })}
            <div
              onMouseEnter={(e) => onMouseEnter(e, row)}
              onMouseLeave={onMouseLeave}
              onMouseMove={onMouseMove}
              className="activity"
              style={{
                width: (timeIntervalw(row.end)-timeIntervalw(row.start)) * widthgezi +widthgezi,
                left:
                  timeIntervals(row.start) * widthgezi,
                backgroundColor: "#67C13A",
                height: rowHeight,
              }}
            >
            </div>
          </div>
        ))}
      </div>
      <div
        className="tooltip"
        style={{
          left: offsetX,
          top: offsetY - 60,
          position: "fixed",
          display: tooltipVisble,
          transform: `translateX(-${translateX}%)`
        }}
      >
        <div className="title">{tooltipData ? tooltipData.name : ""}saaaaad</div>
        <div className="time">
          {`${tooltipData ? tooltipData.start : ""} - ${tooltipData ? tooltipData.end : ""
            }`}
        </div>
      </div>
    </div>
  )
}

  

.gun-wrap {
  display: flex;
  overflow: hidden;
}
.gun-left {
  .rowTitle {
    box-sizing: border-box;
    background-color: #f0f0f0;
    border-right: solid 1px #e0e0e0;
    border-bottom: solid 1px #e0e0e0;
    text-align: center;
    line-height: 100px;
  }
}
.gun-right {
  vertical-align: top;
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  padding-bottom: 0px;
  // flex: 1;
}

.desc_container {
  display: block;
  float: left;
  border-right: 1px solid #ccc;
  text-align: center;
  box-sizing: border-box;
  font-weight: bold;
  overflow-y: auto;

  .row_desc_container {
    display: block;
  }

  .row_desc_container:nth-child(even) {
    background-color: #e0e0e0;
  }

  .row_desc_container:nth-child(odd) {
    background-color: #f0f0f0;
  }

  .row_desc_container:first-child {
    border-top-left-radius: 2px;
  }

  .row_desc_container:last-child {
    border-bottom-left-radius: 2px;
  }
}

.header_container {
  .time_header_container {
    white-space: nowrap;
    font-weight: bold;
    .time_header_item {
      height: 50px;
      line-height: 50px;
      display: inline-block;
      box-sizing: border-box;
      background-color: #f0f0f0;
      border-right: solid 1px #e0e0e0;
      border-bottom: solid 1px #e0e0e0;
      text-align: center;
      vertical-align: middle;
    }
  }
}
.row_val_container {
  position: relative;
  .activity {
    box-sizing: border-box;
    position: absolute;
    border-radius: 2px;
    padding: 0 5px;
    top: 50%;
    transform: translateY(-50%);
    min-width: 1px;
    font-size: 14px;
    text-align: center;
    line-height: 50px;
    color: #fff;
    background-color: #67c13a;
    cursor: pointer;
  }
}

.row_val_container:nth-child(even) {
  background-color: #f0f0f0;
}

.row_val_container:nth-child(odd) {
  background-color: #e0e0e0;
}

.tooltip {
  z-index: 99999;
  border-radius: 2px;
  background-color: #fff;
  box-shadow: 1px 1px 3px 3px rgba(0, 0, 0, 0.3);
  overflow: hidden;
  white-space: pre;

  .title {
    background-color: #718fbd;
    color: #fff;
    padding: 2px 6px;
    text-align: center;
    font-weight: 500;
  }

  .time {
    font-size: 14px;
    padding: 2px 6px;
    text-align: center;
    border: 1px solid #718fbd;
    border-radius: 0px 0px 2px 2px;
  }
}

.tooltip::before {
  position: absolute;
  left: -12px;
  width: 0;
  height: 0;
  border: 6px solid transparent;
  border-right: 6px solid#fff;
  content: '';
}

  

import React from 'react'
import GunttChart from '../GunttChart'
import { Tooltip } from 'antd'
import GunttCharts from '../gun'

export default function CustomerNeed() {

  const columns  = [
    {
      title: '任务名称',
      dataIndex: 'name',
      render: (text: string) => (
        <Tooltip placement="topLeft" title={text}>
          {text || '--'}
        </Tooltip>
      )
    },
    {
      title: '工序',
      dataIndex: 'gx',
      render: (text: string) => (
        <Tooltip placement="topLeft" title={text}>
          {text || '--'}
        </Tooltip>
      )
    },
    {
      title: '开始',
      dataIndex: 'start',
      render: (text: string) => (
        <Tooltip placement="topLeft" title={text}>
          {text || '--'}
        </Tooltip>
      )
    },
    {
      title: '结束',
      dataIndex: 'end',
      render: (text: string) => (
        <Tooltip placement="topLeft" title={text}>
          {text || '--'}
        </Tooltip>
      )
    }
  ]
  const dataSource = [
    {
      start: "2024-01-03",
      end: "2024-02-04",
      title: "阅读会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-03-01",
      end: "2024-03-08",
      title: "茶话会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-04-01",
      end: "2024-04-9",
      title: "阅读会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-05-01",
      end: "2024-05-08",
      title: "茶话会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-06-01",
      end: "2024-06-08",
      title: "阅读会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-07-01",
      end: "2024-07-05",
      title: "茶话会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-08-01",
      end: "2024-08-08",
      title: "阅读会",
      gx: "sd",
      name: "sdf"
    },
    {
      start: "2024-08-01",
      end: "2024-08-20",
      title: "茶话会",
      gx: "sd",
      name: "sdf"
    },

  ]
  return (
   <div>
     {/* <GunttChart  columns={columns}  dataSource={dataSource}></GunttChart> */}
     <GunttCharts columns={columns} dataSource={dataSource}></GunttCharts>
   </div>
  )
}

  

posted @ 2024-05-10 15:13  zjxgdq  阅读(110)  评论(0编辑  收藏  举报