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>
)
}
本文来自博客园,作者:zjxgdq,转载请注明原文链接:https://www.cnblogs.com/zjxzhj/p/18184415

浙公网安备 33010602011771号