362 lines
11 KiB
JavaScript
362 lines
11 KiB
JavaScript
|
import React, {
|
|||
|
useState,
|
|||
|
useImperativeHandle,
|
|||
|
useRef,
|
|||
|
useCallback,
|
|||
|
useEffect,
|
|||
|
useMemo,
|
|||
|
} from "react";
|
|||
|
import InfoCard from "./InfoCard";
|
|||
|
import Row from "../Row";
|
|||
|
|
|||
|
const gutter = 20;
|
|||
|
const cardBottom = 20;
|
|||
|
|
|||
|
const InfoCardList = React.forwardRef((props, ref) => {
|
|||
|
const {
|
|||
|
mainKey,
|
|||
|
speed = 50,
|
|||
|
span = 4,
|
|||
|
withClassify = false,
|
|||
|
autoNext = true,
|
|||
|
classifyKey = { name: "name", children: "children" },
|
|||
|
pageFinished,
|
|||
|
type = "move",
|
|||
|
extraColumnsOpt,
|
|||
|
...otherProps
|
|||
|
} = props;
|
|||
|
|
|||
|
const sizeRef = useRef();
|
|||
|
const infoCardListRef = useRef();
|
|||
|
const pageBoxRef = useRef();
|
|||
|
const pageRef = useRef(1);
|
|||
|
|
|||
|
const [data, setData] = useState([]);
|
|||
|
const [energy, setEnergy] = useState([]);
|
|||
|
const [autoScroll, setAutoScroll] = useState([0, 0]);
|
|||
|
|
|||
|
const classifyRef = useRef([]);
|
|||
|
const classifyBoxRef = useRef();
|
|||
|
|
|||
|
const pageSize = useMemo(() => Math.floor(24 / span), [span]);
|
|||
|
const totalPage = useMemo(() => {
|
|||
|
if (withClassify) {
|
|||
|
let { children } = classifyKey;
|
|||
|
let size = 0;
|
|||
|
classifyRef.current = [];
|
|||
|
data.forEach((item) => {
|
|||
|
let itemPageSize = Math.ceil((item[children].length || 0) / pageSize);
|
|||
|
size += itemPageSize;
|
|||
|
classifyRef.current.push(size);
|
|||
|
});
|
|||
|
return size;
|
|||
|
} else return Math.ceil(data.length / pageSize);
|
|||
|
}, [data, pageSize, withClassify, classifyKey]);
|
|||
|
const [pageHeight, setPageHeight] = useState(0);
|
|||
|
|
|||
|
const setActiveClassify = useCallback(
|
|||
|
(page) => {
|
|||
|
if (!classifyBoxRef.current) return;
|
|||
|
let classifyIndex =
|
|||
|
classifyRef.current.findIndex((maxPageSize) => page <= maxPageSize) ||
|
|||
|
0;
|
|||
|
let { name } = classifyKey;
|
|||
|
let oprationname = data?.[classifyIndex]?.[name].split("】")[1];
|
|||
|
let text = oprationname === undefined ? "" : "- " + oprationname;
|
|||
|
if (text) {
|
|||
|
classifyBoxRef.current.style.display = "block";
|
|||
|
classifyBoxRef.current.innerText = text;
|
|||
|
} else classifyBoxRef.current.style.display = "none";
|
|||
|
},
|
|||
|
[data]
|
|||
|
);
|
|||
|
|
|||
|
const setPageBoxCss = useCallback(
|
|||
|
(page) => {
|
|||
|
pageRef.current = page;
|
|||
|
setActiveClassify(page);
|
|||
|
pageBoxRef.current.style.transition =
|
|||
|
page === 1 ? "none" : "transform 0.3s";
|
|||
|
pageBoxRef.current.style.transform = `translateY(${
|
|||
|
-(page - 1) * (pageHeight + cardBottom)
|
|||
|
}px)`;
|
|||
|
},
|
|||
|
[pageHeight, setActiveClassify]
|
|||
|
);
|
|||
|
|
|||
|
const nextPage = useCallback(() => {
|
|||
|
// console.log();
|
|||
|
let page = pageRef.current;
|
|||
|
if (page + 1 > totalPage) {
|
|||
|
if (autoNext) {
|
|||
|
setPageBoxCss(1);
|
|||
|
} else {
|
|||
|
pageFinished && pageFinished();
|
|||
|
}
|
|||
|
} else {
|
|||
|
setPageBoxCss(page + 1);
|
|||
|
}
|
|||
|
}, [totalPage]);
|
|||
|
|
|||
|
const moveChecking = useCallback(() => {
|
|||
|
let { offsetWidth, scrollWidth } = infoCardListRef.current;
|
|||
|
setAutoScroll([offsetWidth, scrollWidth]);
|
|||
|
}, [data]);
|
|||
|
const pageChecking = useCallback(() => {
|
|||
|
let { scrollHeight, offsetHeight } = sizeRef.current;
|
|||
|
setPageHeight(scrollHeight);
|
|||
|
}, []);
|
|||
|
|
|||
|
useEffect(() => {
|
|||
|
if (type === "move") {
|
|||
|
let innerWindow = sizeRef.current.contentDocument.defaultView;
|
|||
|
innerWindow.addEventListener("resize", moveChecking);
|
|||
|
moveChecking();
|
|||
|
return () => {
|
|||
|
innerWindow.removeEventListener("resize", moveChecking);
|
|||
|
};
|
|||
|
}
|
|||
|
}, [moveChecking]);
|
|||
|
|
|||
|
useEffect(() => {
|
|||
|
if (type === "page") {
|
|||
|
let innerWindow = sizeRef.current.contentDocument.defaultView;
|
|||
|
innerWindow.addEventListener("resize", pageChecking);
|
|||
|
pageChecking();
|
|||
|
return () => {
|
|||
|
innerWindow.removeEventListener("resize", pageChecking);
|
|||
|
};
|
|||
|
}
|
|||
|
}, [pageChecking]);
|
|||
|
|
|||
|
useEffect(() => {
|
|||
|
setPageBoxCss(1);
|
|||
|
}, [data, setPageBoxCss]);
|
|||
|
|
|||
|
useImperativeHandle(
|
|||
|
ref,
|
|||
|
() => ({
|
|||
|
setData: (data) => {
|
|||
|
setData(data);
|
|||
|
setPageBoxCss(1);
|
|||
|
},
|
|||
|
setEnergy:(data)=>{
|
|||
|
setEnergy(data);
|
|||
|
},
|
|||
|
nextPage,
|
|||
|
}),
|
|||
|
[nextPage]
|
|||
|
);
|
|||
|
|
|||
|
return (
|
|||
|
<div className="infoCardList" ref={infoCardListRef}>
|
|||
|
{type === "move" && (
|
|||
|
<div className="box move">
|
|||
|
{data.map((item) => {
|
|||
|
return (
|
|||
|
<div key={item[mainKey]} className="item">
|
|||
|
<InfoCard {...otherProps} data={item} />
|
|||
|
</div>
|
|||
|
);
|
|||
|
})}
|
|||
|
</div>
|
|||
|
)}
|
|||
|
{type === "page" && (
|
|||
|
<div className="page-content">
|
|||
|
{withClassify === true && (
|
|||
|
<div className="classify" ref={classifyBoxRef}></div>
|
|||
|
)}
|
|||
|
<div className="classifycenter -mt-14 w-full text-center ">
|
|||
|
<label className="bg-[#1890ff] p-1 pt-0.5 pb-0.5">能源信息</label>
|
|||
|
</div>
|
|||
|
<div className="classifycenterval grid grid-cols-2 gap-1 place-items-start -mt-7 w-full">
|
|||
|
{console.log("ernergy",energy)}
|
|||
|
{/* {props.energy ?? `日期:${props.energy[0]} 水: ${props.energy[0].water} 电: ${1} 气: ${1}`} */}
|
|||
|
{
|
|||
|
energy.map(x=>{
|
|||
|
return (
|
|||
|
<span className={ energy.indexOf(x)===0?`flex-1 mr-20 justify-self-end`:`flex-1 ml-20 justify-self-start`}> 日期:{x.time} 水: {x.water} 电: {x.electricity} 气: {x.gas}</span>
|
|||
|
)
|
|||
|
})}
|
|||
|
</div>
|
|||
|
<div className="page-box">
|
|||
|
<object
|
|||
|
ref={sizeRef}
|
|||
|
tabIndex="-1"
|
|||
|
type="text/html"
|
|||
|
aria-hidden="true"
|
|||
|
data="about:blank"
|
|||
|
style={{
|
|||
|
display: "block",
|
|||
|
position: "absolute",
|
|||
|
top: 0,
|
|||
|
left: 0,
|
|||
|
width: "100%",
|
|||
|
height: "100%",
|
|||
|
border: "none",
|
|||
|
padding: 0,
|
|||
|
margin: 0,
|
|||
|
opacity: 0,
|
|||
|
zIndex: -1000,
|
|||
|
pointerEvents: "none",
|
|||
|
}}
|
|||
|
></object>
|
|||
|
<div className="page" ref={pageBoxRef}>
|
|||
|
{withClassify === false && (
|
|||
|
<Row className="height-100" gutter={20}>
|
|||
|
{data.map((item) => {
|
|||
|
let extraColumns = [];
|
|||
|
if (extraColumnsOpt) {
|
|||
|
let { key, name, val, max } = extraColumnsOpt;
|
|||
|
let extraData = item[key];
|
|||
|
extraData.forEach((i, index) => {
|
|||
|
if (index < max)
|
|||
|
extraColumns.push({ title: i[name], text: i[val] });
|
|||
|
});
|
|||
|
}
|
|||
|
return (
|
|||
|
<Row.Col span={span} key={item[mainKey]}>
|
|||
|
<div className="item height-100">
|
|||
|
<InfoCard
|
|||
|
{...otherProps}
|
|||
|
extraColumns={extraColumns}
|
|||
|
data={item}
|
|||
|
cardWidth={false}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
</Row.Col>
|
|||
|
);
|
|||
|
})}
|
|||
|
</Row>
|
|||
|
)}
|
|||
|
{withClassify === true &&
|
|||
|
data.map((item) => {
|
|||
|
let { name, children } = classifyKey;
|
|||
|
return (
|
|||
|
<Row gutter={20} key={item[name]}>
|
|||
|
{item[children].map((item) => {
|
|||
|
let extraColumns = [];
|
|||
|
if (extraColumnsOpt) {
|
|||
|
let { key, name, val, max } = extraColumnsOpt;
|
|||
|
let extraData = item[key];
|
|||
|
extraData.forEach((i, index) => {
|
|||
|
if (index < max)
|
|||
|
extraColumns.push({
|
|||
|
title: i[name],
|
|||
|
text: i[val],
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
return (
|
|||
|
<Row.Col span={span} key={item[mainKey]}>
|
|||
|
<div className="item">
|
|||
|
<InfoCard
|
|||
|
{...otherProps}
|
|||
|
extraColumns={extraColumns}
|
|||
|
data={item}
|
|||
|
cardWidth={false}
|
|||
|
/>
|
|||
|
</div>
|
|||
|
</Row.Col>
|
|||
|
);
|
|||
|
})}
|
|||
|
</Row>
|
|||
|
);
|
|||
|
})}
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
)}
|
|||
|
<style jsx>{`
|
|||
|
.infoCardList {
|
|||
|
height: 100%;
|
|||
|
overflow: hidden;
|
|||
|
position: relative;
|
|||
|
}
|
|||
|
.infoCardList > .box {
|
|||
|
height: 100%;
|
|||
|
display: flex;
|
|||
|
justify-content: flex-start;
|
|||
|
}
|
|||
|
.infoCardList > .box > .item {
|
|||
|
height: 100%;
|
|||
|
padding-right: ${gutter}px;
|
|||
|
}
|
|||
|
.infoCardList > .box.move {
|
|||
|
animation: move ${autoScroll[1] / speed}s linear infinite;
|
|||
|
animation-fill-mode: forwards;
|
|||
|
transform: translateX(0px);
|
|||
|
}
|
|||
|
@keyframes move {
|
|||
|
from {
|
|||
|
transform: translateX(${autoScroll[0]}px);
|
|||
|
}
|
|||
|
to {
|
|||
|
transform: translateX(${-autoScroll[1]}px);
|
|||
|
}
|
|||
|
}
|
|||
|
.infoCardList .page {
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
.infoCardList .page :global(.col) {
|
|||
|
margin-bottom: ${cardBottom}px;
|
|||
|
}
|
|||
|
.infoCardList .page .item {
|
|||
|
height: ${pageHeight}px;
|
|||
|
}
|
|||
|
|
|||
|
.infoCardList .page-content {
|
|||
|
height: 100%;
|
|||
|
padding-top: 55px;
|
|||
|
padding-bottom: 15px;
|
|||
|
position: relative;
|
|||
|
}
|
|||
|
.infoCardList .classify {
|
|||
|
position: absolute;
|
|||
|
z-index: 100;
|
|||
|
font-weight: 600;
|
|||
|
font-size: 1.125rem;
|
|||
|
left: 100px;
|
|||
|
top: 0px;
|
|||
|
// background: #15579f;
|
|||
|
// border-radius: 3px;
|
|||
|
// transition: all .3s;
|
|||
|
}
|
|||
|
.infoCardList .classifycenter label {
|
|||
|
font-weight: 600;
|
|||
|
font-size: 1.125rem;
|
|||
|
}
|
|||
|
.infoCardList .classifycenter {
|
|||
|
position: absolute;
|
|||
|
z-index: 100;
|
|||
|
|
|||
|
// left: 48.5%;
|
|||
|
// padding: 2px 5px;
|
|||
|
// top: -3px;
|
|||
|
// background: #1890ff;
|
|||
|
// border-radius: 3px;
|
|||
|
// transition: all .3s;
|
|||
|
}
|
|||
|
.infoCardList .classifycenterval {
|
|||
|
position: absolute;
|
|||
|
z-index: 100;
|
|||
|
font-weight: 600;
|
|||
|
font-size: 1.125rem;
|
|||
|
// left: 19%;
|
|||
|
// top: 20px;
|
|||
|
// padding: 2px 5px;
|
|||
|
// border-radius: 3px;
|
|||
|
// transition: all .3s;
|
|||
|
}
|
|||
|
.infoCardList .page-box {
|
|||
|
height: 100%;
|
|||
|
overflow: hidden;
|
|||
|
position: relative;
|
|||
|
}
|
|||
|
`}</style>
|
|||
|
</div>
|
|||
|
);
|
|||
|
});
|
|||
|
|
|||
|
export default InfoCardList;
|